# This is a BitKeeper generated diff -Nru style patch. # # drivers/net/sungem.c # 2004/02/20 01:11:45-08:00 benh@kernel.crashing.org +12 -1 # Be careful about memory ordering in sungem driver # # ChangeSet # 2004/02/19 22:48:46-08:00 torvalds@ppc970.osdl.org # Include the header file for DMA mapping. # # You know you want it. Give it to me. # # drivers/usb/host/ehci-hcd.c # 2004/02/19 22:48:41-08:00 torvalds@ppc970.osdl.org +1 -0 # Include the header file for DMA mapping. # # ChangeSet # 2004/02/19 22:14:58-08:00 cpg@puchol.com # [PATCH] initial support for transmeta's efficeon processors # # This implements the initial support for the AGP gart in Transmeta's # Efficeon processors. # # This code is based on linus' code from a while ago. Peter and I adapted # it for the current kernel. # # The note at the top indicates how it was tested, known issues, and so # forth. It is working quite well, and we'll work to fix the minor issues # and test it some more with s3, more cards, other southbridges, etc., # next. # # drivers/char/agp/efficeon-agp.c # 2004/02/18 16:02:05-08:00 cpg@puchol.com +467 -0 # initial support for transmeta's efficeon processors # # include/linux/pci_ids.h # 2004/02/18 16:02:05-08:00 cpg@puchol.com +3 -0 # initial support for transmeta's efficeon processors # # drivers/char/agp/efficeon-agp.c # 2004/02/18 16:02:05-08:00 cpg@puchol.com +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/drivers/char/agp/efficeon-agp.c # # drivers/char/agp/Makefile # 2004/02/18 16:02:05-08:00 cpg@puchol.com +1 -0 # initial support for transmeta's efficeon processors # # drivers/char/agp/Kconfig # 2004/02/18 16:02:05-08:00 cpg@puchol.com +10 -0 # initial support for transmeta's efficeon processors # # ChangeSet # 2004/02/19 21:43:37-08:00 B.Zolnierkiewicz@elka.pw.edu.pl # [PATCH] fix /proc/ide/ for IDE PCI modules # # Make IDE PCI drivers register /proc/ide/ entries themselves. # # include/linux/ide.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +6 -12 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/via82cxxx.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -18 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/via82cxxx.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/triflex.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -9 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/triflex.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/slc90e66.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -18 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/slc90e66.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/sis5513.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -18 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/sis5513.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/siimage.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -20 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/siimage.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/serverworks.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -18 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/serverworks.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/sc1200.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -18 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/sc1200.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/piix.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -18 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/piix.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/pdc202xx_old.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -19 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/pdc202xx_old.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/pdc202xx_new.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -19 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/pdc202xx_new.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/hpt366.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -18 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/hpt366.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/hpt34x.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -18 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/hpt34x.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/cs5530.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -18 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/cs5530.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/cs5520.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -18 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/cs5520.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/cmd64x.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -19 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/cmd64x.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/amd74xx.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -18 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/amd74xx.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +3 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/alim15x3.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -18 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/alim15x3.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/aec62xx.h # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -18 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/pci/aec62xx.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/ide.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +6 -0 # fix /proc/ide/ for IDE PCI modules # # drivers/ide/ide-proc.c # 2004/02/18 17:14:51-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +9 -54 # fix /proc/ide/ for IDE PCI modules # # ChangeSet # 2004/02/19 21:43:26-08:00 B.Zolnierkiewicz@elka.pw.edu.pl # [PATCH] remove unused ide_end_taskfile() # # Additionally ide_end_drive_cmd() contains all functionality of this function. # # include/linux/ide.h # 2004/02/18 17:12:33-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -3 # remove unused ide_end_taskfile() # # drivers/ide/ide-taskfile.c # 2004/02/18 17:12:33-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -60 # remove unused ide_end_taskfile() # # drivers/ide/ide-io.c # 2004/02/18 17:12:33-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -2 # remove unused ide_end_taskfile() # # drivers/ide/ide-disk.c # 2004/02/18 17:12:33-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -7 # remove unused ide_end_taskfile() # # ChangeSet # 2004/02/19 21:43:17-08:00 B.Zolnierkiewicz@elka.pw.edu.pl # [PATCH] remove dead/unfinished taskfile version of ide_cmd_ioctl() # # drivers/ide/ide-taskfile.c # 2004/02/18 17:11:21-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -65 # remove dead/unfinished taskfile version of ide_cmd_ioctl() # # ChangeSet # 2004/02/19 21:43:08-08:00 B.Zolnierkiewicz@elka.pw.edu.pl # [PATCH] remove bogus comment and code from ide_unregister_driver() # # When ide_remove_proc_entries() is called, driver specific /proc/ide/hdx/ # entries have been already removed by ->cleanup()->ide_unregister_subdriver(). # # drivers/ide/ide.c # 2004/02/18 17:10:43-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -6 # remove bogus comment and code from ide_unregister_driver() # # ChangeSet # 2004/02/19 21:42:59-08:00 B.Zolnierkiewicz@elka.pw.edu.pl # [PATCH] kill default_flushcache() and ide_drive_t->flushcache # # include/linux/ide.h # 2004/02/18 17:10:22-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -1 # kill default_flushcache() and ide_drive_t->flushcache # # drivers/ide/ide.c # 2004/02/18 17:10:22-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -15 # kill default_flushcache() and ide_drive_t->flushcache # # drivers/ide/ide-disk.c # 2004/02/18 17:10:22-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -1 # kill default_flushcache() and ide_drive_t->flushcache # # ChangeSet # 2004/02/19 21:42:50-08:00 B.Zolnierkiewicz@elka.pw.edu.pl # [PATCH] kill default_shutdown() and ide_drive_t->shutdown # # include/linux/ide.h # 2004/02/18 17:09:37-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -1 # kill default_shutdown() and ide_drive_t->shutdown # # drivers/ide/ide.c # 2004/02/18 17:09:37-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +2 -18 # kill default_shutdown() and ide_drive_t->shutdown # # ChangeSet # 2004/02/19 21:42:40-08:00 B.Zolnierkiewicz@elka.pw.edu.pl # [PATCH] kill useless IDE_SUBDRIVER_VERSION # # include/linux/ide.h # 2004/02/18 17:09:06-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -3 # kill useless IDE_SUBDRIVER_VERSION # # drivers/scsi/ide-scsi.c # 2004/02/18 17:09:06-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -2 # kill useless IDE_SUBDRIVER_VERSION # # drivers/ide/ide.c # 2004/02/18 17:09:06-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +6 -6 # kill useless IDE_SUBDRIVER_VERSION # # drivers/ide/ide-tape.c # 2004/02/18 17:09:06-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # kill useless IDE_SUBDRIVER_VERSION # # drivers/ide/ide-floppy.c # 2004/02/18 17:09:06-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # kill useless IDE_SUBDRIVER_VERSION # # drivers/ide/ide-disk.c # 2004/02/18 17:09:06-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # kill useless IDE_SUBDRIVER_VERSION # # drivers/ide/ide-default.c # 2004/02/18 17:09:06-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -2 # kill useless IDE_SUBDRIVER_VERSION # # drivers/ide/ide-cd.c # 2004/02/18 17:09:06-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +1 -1 # kill useless IDE_SUBDRIVER_VERSION # # ChangeSet # 2004/02/19 21:42:31-08:00 B.Zolnierkiewicz@elka.pw.edu.pl # [PATCH] keep documentation of kernel parameters in one place only # # drivers/ide/ide.c # 2004/02/18 17:08:03-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +2 -70 # keep documentation of kernel parameters in one place only # # Documentation/ide.txt # 2004/02/18 17:08:03-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +3 -2 # keep documentation of kernel parameters in one place only # # ChangeSet # 2004/02/19 21:42:22-08:00 B.Zolnierkiewicz@elka.pw.edu.pl # [PATCH] remove dead kernel parameters # # Remove "hdx=flash" (ignored since 2.5.63) and "hdx=slow" # (ignored since 2.5.41) kernel parameters. # # Also remove "slow" entry from /proc/ide/hdx/settings # and "ata_flash", "nobios" and "slow" fields from ide_drive_t. # # include/linux/ide.h # 2004/02/18 16:41:29-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -3 # remove dead kernel parameters # # drivers/ide/ide.c # 2004/02/18 16:41:29-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +2 -16 # remove dead kernel parameters # # drivers/ide/ide-probe.c # 2004/02/18 16:41:22-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +2 -20 # remove dead kernel parameters # # Documentation/ide.txt # 2004/02/18 16:41:22-08:00 B.Zolnierkiewicz@elka.pw.edu.pl +0 -7 # remove dead kernel parameters # # ChangeSet # 2004/02/19 21:42:12-08:00 akpm@osdl.org # [PATCH] x86_64 uniproc build fix # # From: Andi Kleen # # This fixes some more problems introduced by the IA32e merge on x86-64 # # - Make it compile on UP again. # - Let the microcode driver build as a module # # arch/x86_64/kernel/x8664_ksyms.c # 2004/02/19 13:09:39-08:00 akpm@osdl.org +2 -0 # x86_64 uniproc build fix # # arch/x86_64/kernel/setup.c # 2004/02/19 13:09:26-08:00 akpm@osdl.org +2 -0 # x86_64 uniproc build fix # # arch/x86_64/kernel/Makefile # 2004/02/19 13:09:26-08:00 akpm@osdl.org +1 -1 # x86_64 uniproc build fix # # ChangeSet # 2004/02/19 21:42:02-08:00 akpm@osdl.org # [PATCH] smbfs: remove debug code # # Remove an unneeded WSET() which snuck in there. # # fs/smbfs/smbiod.c # 2004/02/19 13:08:09-08:00 akpm@osdl.org +0 -1 # smbfs: remove debug code # # ChangeSet # 2004/02/19 21:41:53-08:00 akpm@osdl.org # [PATCH] Fix the display of max-ever-used-stack in sysrq-T output # # The sysrq-T output currently tries to display the mimimum amount of free # stack which each task has ever had available. It has been busted for years, # because we forgot to zero out the stack when it is first created. # # Fix that up, adding a conig option for it. # # If the option is disabled, or the arch is not x86 then the free stack usage # will display as zero. # # kernel/sched.c # 2004/02/19 13:08:09-08:00 akpm@osdl.org +10 -1 # Fix the display of max-ever-used-stack in sysrq-T output # # include/asm-i386/thread_info.h # 2004/02/19 13:08:09-08:00 akpm@osdl.org +14 -1 # Fix the display of max-ever-used-stack in sysrq-T output # # arch/i386/Kconfig # 2004/02/19 13:08:09-08:00 akpm@osdl.org +9 -0 # Fix the display of max-ever-used-stack in sysrq-T output # # ChangeSet # 2004/02/19 21:41:44-08:00 akpm@osdl.org # [PATCH] v850 ptrace.c task_struct leak # # From: Herbert Poetzl # # sys_ptrace() for v850, if pid == 1, doesn't put the struct task_struct # (child), the following patch should fix that ... # # arch/v850/kernel/ptrace.c # 2004/02/19 13:08:08-08:00 akpm@osdl.org +1 -1 # v850 ptrace.c task_struct leak # # ChangeSet # 2004/02/19 21:41:35-08:00 akpm@osdl.org # [PATCH] ppc64 compile fix # # From: Arjan van de Ven # # fix obvious non-C-standard stubs on ppc64 # # include/asm-ppc64/system.h # 2004/02/19 13:01:04-08:00 akpm@osdl.org +6 -6 # ppc64 compile fix # # ChangeSet # 2004/02/19 21:36:48-08:00 benh@kernel.crashing.org # [PATCH] Fix a DMA underrun problem with pmac IDE # # This fixes the behaviour of the pmac "macio" IDE driver when a DMA # transfer happen to get less data out of the device than expected when # setting up the DMA commands (the device underruns). This is very common # with recent ATAPI stuffs and used to cause problem & disable DMA. This # patch fixes the way we handle that condition, thus also fixing DVD # burning on a bunch of recent pmacs. # # drivers/ide/ppc/pmac.c # 2004/02/17 22:20:23-08:00 benh@kernel.crashing.org +28 -23 # Fix a DMA underrun problem with pmac IDE # # ChangeSet # 2004/02/19 21:36:39-08:00 benh@kernel.crashing.org # [PATCH] Be careful about memory ordering in sungem driver # # Some barriers between setting up the DMA regions and writing the # descriptor addresses would be most useful. # # I had some in my 2.4 version but they got lost someway, probably me not # properly merging with davem at this point. The 970 is definitely more # agressive at re-ordering stores than previous CPUs... # # Here is a patch adding some (probably too much, but better safe than # sorry). # # ChangeSet # 2004/02/19 22:56:14-05:00 jgarzik@redhat.com # Merge redhat.com:/spare/repo/netdev-2.6/e100-2 # into redhat.com:/spare/repo/net-drivers-2.5 # # drivers/net/Makefile # 2004/02/19 22:56:08-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/Kconfig # 2004/02/19 22:56:08-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/02/19 17:12:16-08:00 greg@kroah.com # Merge kroah.com:/home/greg/linux/BK/bleed-2.6 # into kroah.com:/home/greg/linux/BK/usb-2.6 # # drivers/usb/host/ehci-dbg.c # 2004/02/19 17:12:11-08:00 greg@kroah.com +0 -0 # Auto merged # # ChangeSet # 2004/02/19 16:25:15-08:00 torvalds@ppc970.osdl.org # Merge http://lia64.bkbits.net/to-linus-2.5 # into ppc970.osdl.org:/home/torvalds/v2.5/linux # # arch/ia64/sn/kernel/irq.c # 2004/02/19 16:25:12-08:00 torvalds@ppc970.osdl.org +0 -0 # Auto merged # # ChangeSet # 2004/02/19 16:19:27-08:00 greg@kroah.com # USB storage: sync up with some missing unusual_devs entries that were in my tree. # # drivers/usb/storage/unusual_devs.h # 2004/02/19 16:19:13-08:00 greg@kroah.com +18 -0 # USB storage: sync up with some missing unusual_devs entries that were in my tree. # # ChangeSet # 2004/02/19 15:42:36-08:00 Andries.Brouwer@cwi.nl # [PATCH] USB: add comments to sddr09.c # # People ask how to write the CIS on a SmartMedia card using an sddr09 # reader/writer. The patch below documents the required command (but does # not add the code). # # Two years ago or so I used this to fix the CIS on a card that my camera no # longer wanted to accept. A Linux utility to do this might be useful, but # the problem always is that we do not really have a good mechanism. # # How does one tell a driver that it has to do something special? Add yet # another ioctl? # # drivers/usb/storage/sddr09.c # 2004/01/25 03:12:23-08:00 Andries.Brouwer@cwi.nl +29 -0 # USB: add comments to sddr09.c # # ChangeSet # 2004/02/19 15:35:35-08:00 greg@kroah.com # [PATCH] USB: fix up compile errors in uhci driver. # # drivers/usb/host/uhci-hcd.c # 2004/02/19 07:31:38-08:00 greg@kroah.com +2 -2 # USB: fix up compile errors in uhci driver. # # ChangeSet # 2004/02/19 15:34:39-08:00 stern@rowland.harvard.edu # [PATCH] USB: Use driver-model logging in the UHCI driver # # The main item in this patch is the conversion of the UHCI driver from # using the old usb.h logging macros to the new driver-model dev_xxx # macros. # # There are a few other minor changes too: updated version number, author, # copyright, and maintainer information, removed some unneeded error # messages, added some line breaks, added a convenience macro for the device # pointer. # # drivers/usb/host/uhci-hub.c # 2004/02/19 08:15:06-08:00 stern@rowland.harvard.edu +4 -5 # USB: Use driver-model logging in the UHCI driver # # drivers/usb/host/uhci-hcd.h # 2004/02/19 08:15:06-08:00 stern@rowland.harvard.edu +1 -1 # USB: Use driver-model logging in the UHCI driver # # drivers/usb/host/uhci-hcd.c # 2004/02/19 08:15:06-08:00 stern@rowland.harvard.edu +62 -55 # USB: Use driver-model logging in the UHCI driver # # ChangeSet # 2004/02/19 15:34:09-08:00 stern@rowland.harvard.edu # [PATCH] USB: Repair unusual_devs.h entry # # On Fri, 20 Feb 2004, Gustavo Guillermo wrote: # # > Ok, I tested the patch, The camera works, just as in the old Kernel, # > Thanks, I'm including as an atachment the /proc/bus/usb/devices from # > kernel 2.4.x and 2.6.x, and the kernel log for 2.4.x, but ooops, I forgot # > to biold 2.4.x with full debug, if someone need it I will do. # > # > Please include this FIX in the Next Release. # # Greg, I now feel confident that this patch should be applied. # # drivers/usb/storage/unusual_devs.h # 2004/02/17 02:42:58-08:00 stern@rowland.harvard.edu +1 -1 # USB: Repair unusual_devs.h entry # # ChangeSet # 2004/02/19 15:32:56-08:00 stern@rowland.harvard.edu # [PATCH] USB: Another unusual_devs.h update # # On Thu, 19 Feb 2004, Agustin De Igartua wrote: # # > Initializing USB Mass Storage driver... # > usb-storage: This device (04e6,0002,0100 S 06 P 50) has unneeded SubClass and Protocol entries in unusual_devs.h # > Please send a copy of this message to scsi0 : SCSI emulation for USB Mass Storage devices # # Thank you for sending this in. Greg, here's the patch. # # drivers/usb/storage/unusual_devs.h # 2004/02/19 04:01:34-08:00 stern@rowland.harvard.edu +1 -1 # USB: Another unusual_devs.h update # # ChangeSet # 2004/02/19 11:28:05-08:00 davidm@tiger.hpl.hp.com # ia64: Back-port from libunwind: fix off-by-one error in kernel-unwinder. # # There are no known failures due to this bug, but it's clearly a bug and # given the right compiler, it could trigger and lead to bad stack traces etc. # # # arch/ia64/kernel/unwind.c # 2004/02/19 11:27:59-08:00 davidm@tiger.hpl.hp.com +1 -1 # (compile_reg): Fix off-by-one error. # # ChangeSet # 2004/02/19 11:06:58-08:00 pfg@sgi.com # [PATCH] ia64: cleanup SN2 pci_bus_cvlink.c # # I incorporated (at least in spirit I hope) hch's suggestions on the fixup code # put in some kfrees that I was missing and static for sn_alloc_pci_sysdata # (thanks Bartlomiej Zolnierkiewicz). White space clean up. # # arch/ia64/sn/io/machvec/pci_bus_cvlink.c # 2004/02/19 04:06:34-08:00 pfg@sgi.com +161 -172 # ia64: cleanup SN2 pci_bus_cvlink.c # # ChangeSet # 2004/02/19 10:50:29-08:00 mort@sgi.com # [PATCH] ia64: clean up SN2 setup.c # # Cleanup the SN setup.c file. Add __init and static to functions where # required. # # arch/ia64/sn/kernel/setup.c # 2004/02/14 23:22:40-08:00 mort@sgi.com +4 -4 # ia64: clean up SN2 setup.c # # ChangeSet # 2004/02/19 10:49:01-08:00 mort@sgi.com # [PATCH] ia64: SN2 header file cleanups # # Here is a patch to clean up some of the Altix header files and includes. # # I've run the patch past the appropriate people at SGI and they seem happy # with the changes. # # include/asm-ia64/sn/sn2/sn_private.h # 2004/02/13 07:00:22-08:00 mort@sgi.com +1 -0 # ia64: SN2 header file cleanups # # include/asm-ia64/sn/sgi.h # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # include/asm-ia64/sn/module.h # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -6 # ia64: SN2 header file cleanups # # include/asm-ia64/sn/leds.h # 2004/02/13 07:00:22-08:00 mort@sgi.com +1 -4 # ia64: SN2 header file cleanups # # include/asm-ia64/sn/iograph.h # 2004/02/13 07:00:22-08:00 mort@sgi.com +4 -30 # ia64: SN2 header file cleanups # # include/asm-ia64/sn/ioerror_handling.h # 2004/02/13 07:00:22-08:00 mort@sgi.com +1 -84 # ia64: SN2 header file cleanups # # include/asm-ia64/sn/ioconfig_bus.h # 2004/02/13 07:00:22-08:00 mort@sgi.com +6 -6 # ia64: SN2 header file cleanups # # include/asm-ia64/sn/ioc4.h # 2004/02/13 07:00:22-08:00 mort@sgi.com +1 -761 # ia64: SN2 header file cleanups # # include/asm-ia64/sn/io.h # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -2 # ia64: SN2 header file cleanups # # include/asm-ia64/sn/intr.h # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # include/asm-ia64/sn/driver.h # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -4 # ia64: SN2 header file cleanups # # include/asm-ia64/sn/dmamap.h # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -10 # ia64: SN2 header file cleanups # # include/asm-ia64/sn/clksupport.h # 2004/02/13 07:00:22-08:00 mort@sgi.com +4 -5 # ia64: SN2 header file cleanups # # arch/ia64/sn/kernel/irq.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # arch/ia64/sn/io/xswitch.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # arch/ia64/sn/io/sn2/shuberror.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # arch/ia64/sn/io/sn2/shub_intr.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # arch/ia64/sn/io/sn2/shub.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # arch/ia64/sn/io/sn2/pcibr/pcibr_reg.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # arch/ia64/sn/io/sn2/pcibr/pcibr_config.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # arch/ia64/sn/io/sn2/ml_SN_init.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # arch/ia64/sn/io/sn2/klconflib.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -2 # ia64: SN2 header file cleanups # # arch/ia64/sn/io/sn2/geo_op.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # arch/ia64/sn/io/sn2/bte_error.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # arch/ia64/sn/io/machvec/pci_bus_cvlink.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # arch/ia64/sn/io/io.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +0 -1 # ia64: SN2 header file cleanups # # arch/ia64/sn/io/drivers/ioconfig_bus.c # 2004/02/13 07:00:22-08:00 mort@sgi.com +1 -0 # ia64: SN2 header file cleanups # # ChangeSet # 2004/02/19 10:47:27-08:00 pfg@sgi.com # [PATCH] ia64: on SN2, skip init_platform_hubinfo() if on the simulator # # # arch/ia64/sn/io/sn2/ml_SN_init.c # 2004/02/09 09:37:20-08:00 pfg@sgi.com +5 -1 # ia64: on SN2, skip init_platform_hubinfo() if on the simulator # # ChangeSet # 2004/02/19 10:46:32-08:00 pfg@sgi.com # [PATCH] ia64: on SN2, use the pda to count interrupts # # # arch/ia64/sn/io/sn2/ml_SN_intr.c # 2004/02/09 09:37:16-08:00 pfg@sgi.com +3 -3 # ia64: on SN2, use the pda to count interrupts # # ChangeSet # 2004/02/19 08:40:04-08:00 akpm@osdl.org # [PATCH] show_task() is not SMP safe # # From: Arnd Bergmann # # Christian Bornträger noticed that the kernel can crash after -T. It # appears that the show_task function gets called for all tasks, which does # not work if one of the tasks is running in a system call on another CPU. # In that case the result of thread_saved_pc and show_stack is undefined and # likely to cause a crash. # # For tasks running in user space on other CPUs, show_task() is probably # harmless, but I'm not sure if that's true on all architectures. # # The patch below is still racy for tasks that are about to sleep, but it # demonstrates the problem. # # kernel/sched.c # 2004/02/18 22:54:13-08:00 akpm@osdl.org +6 -5 # show_task() is not SMP safe # # ChangeSet # 2004/02/19 08:39:53-08:00 akpm@osdl.org # [PATCH] show_task() fix and cleanup # # show_task() is preinting negative numbers for free stack due to arithmetic # against the wrong pointer. # # Fix that up, and clean up a few related things. # # show_task still has bogus code which atempts to work out how much stack the # task has ever used - it cannot work because we don't actually zero out the # stack pages when allocating them. We should fix that, or take it out. # # kernel/sched.c # 2004/02/18 22:54:12-08:00 akpm@osdl.org +9 -16 # show_task() fix and cleanup # # include/linux/sched.h # 2004/02/18 22:54:12-08:00 akpm@osdl.org +1 -0 # show_task() fix and cleanup # # ChangeSet # 2004/02/19 08:39:43-08:00 akpm@osdl.org # [PATCH] print some x86 build options during oopses # # I find this handy sometimes: it makes the oops output include info as to # whether the user has selected CONFIG_PREEMPT, CONFIG_SMP or, particularly, # CONFIG_DEBUG_PAGEALLOC. It can save one email round-trip. # # arch/i386/kernel/traps.c # 2004/02/18 22:54:11-08:00 akpm@osdl.org +15 -0 # print some x86 build options during oopses # # ChangeSet # 2004/02/19 08:39:33-08:00 akpm@osdl.org # [PATCH] config option for irqbalance # # From: "Martin J. Bligh" # # Make irqbalance into a config option - some people (jgarzik, arjan, etc) # wanted to be able to disable it and do things from userspace instead. This # patch allows each camp to do their own thing, which seems fair ;-) # # arch/i386/kernel/io_apic.c # 2004/02/18 22:54:10-08:00 akpm@osdl.org +5 -3 # config option for irqbalance # # arch/i386/Kconfig # 2004/02/18 22:54:10-08:00 akpm@osdl.org +8 -0 # config option for irqbalance # # ChangeSet # 2004/02/19 08:39:22-08:00 akpm@osdl.org # [PATCH] ia32: disallow NUMA on PC subarch # # From: "Martin J. Bligh" # # Disallow NUMA on the i386 PC subarch (it doesn't work, nor was it intended # to). # # arch/i386/Kconfig # 2004/02/18 22:54:09-08:00 akpm@osdl.org +1 -1 # ia32: disallow NUMA on PC subarch # # ChangeSet # 2004/02/19 08:39:12-08:00 akpm@osdl.org # [PATCH] ia32: pfn_to_nid fix # # From: "Martin J. Bligh" # # Makes sure pfn_to_nid is defined for all combinations of subarches, and that # it's defined before it's used so we don't run into implicit declaration # problems. # # include/linux/mmzone.h # 2004/02/18 22:54:09-08:00 akpm@osdl.org +1 -0 # ia32: pfn_to_nid fix # # include/asm-i386/mmzone.h # 2004/02/18 22:54:09-08:00 akpm@osdl.org +42 -39 # ia32: pfn_to_nid fix # # ChangeSet # 2004/02/19 08:39:02-08:00 akpm@osdl.org # [PATCH] fix pfn_valid on ia32 discontigmem # # From: "Martin J. Bligh" # # Fix pfn_valid for architctures with discontiguous memory. This only # changes the NUMA definition, and it leaves the NUMA-Q definition as was, # because it's faster that way, it's in hotpaths, and our memory is always # contiguous. # # include/asm-i386/mmzone.h # 2004/02/18 22:54:08-08:00 akpm@osdl.org +12 -7 # fix pfn_valid on ia32 discontigmem # # ChangeSet # 2004/02/19 08:38:51-08:00 akpm@osdl.org # [PATCH] fix access() POSIX compliance # # From: Andreas Gruenbacher # # The fix for permission() that makes it compliant with POSIX.1-2001 # apparently was lost. Here is the patch I sent before. (The relevant lines # from the standard text are cited in # http://www.ussg.iu.edu/hypermail/linux/kernel/0310.2/0286.html. The fix # proposed in that posting did not handle directories without execute # permissions correctly.) # # # Make permission check conform to POSIX.1-2001 # # The access(2) function does not conform to POSIX.1-2001: For root # and a file with no permissions, access(file, MAY_READ|MAY_EXEC) # returns 0 (it should return -1). # # fs/xfs/xfs_inode.c # 2004/02/18 22:54:07-08:00 akpm@osdl.org +2 -1 # fix access() POSIX compliance # # fs/namei.c # 2004/02/18 22:54:07-08:00 akpm@osdl.org +2 -1 # fix access() POSIX compliance # # fs/jfs/acl.c # 2004/02/18 22:54:07-08:00 akpm@osdl.org +2 -1 # fix access() POSIX compliance # # fs/ext3/acl.c # 2004/02/18 22:54:07-08:00 akpm@osdl.org +2 -1 # fix access() POSIX compliance # # fs/ext2/acl.c # 2004/02/18 22:54:07-08:00 akpm@osdl.org +2 -1 # fix access() POSIX compliance # # ChangeSet # 2004/02/19 08:38:40-08:00 akpm@osdl.org # [PATCH] gcc-3.5: bonding # # drivers/net/bonding/bond_alb.c: In function `bond_alb_xmit': # drivers/net/bonding/bond_alb.c:1188: error: invalid lvalue in assignment # # drivers/net/bonding/bond_alb.c # 2004/02/18 22:54:07-08:00 akpm@osdl.org +4 -1 # gcc-3.5: bonding # # ChangeSet # 2004/02/19 08:38:29-08:00 akpm@osdl.org # [PATCH] use noinline for rest_init() # # gcc-3.4 incorretly inlines rest_init() into start_kernel(), causing things to # crash when the .text.init section gets unloaded. Use noinline to prevent # that. # # init/main.c # 2004/02/18 22:54:06-08:00 akpm@osdl.org +3 -1 # use noinline for rest_init() # # ChangeSet # 2004/02/19 08:38:18-08:00 akpm@osdl.org # [PATCH] Add noinline attribute # # From: Andi Kleen # # This patch adds the `noinline' function attribute. It can be used to # explicitly tell the compiler to not inline functions. # # We need this due to what is, IMO, a bug present in gcc-3.4 and current # gcc-3.5 CVS: the compiler is inlining init/main.c:rest_init() inside # init/main.c:start_kernel(), despite the fact that thay are declared to be # placed in different text sections. # # include/linux/compiler.h # 2004/02/18 22:54:05-08:00 akpm@osdl.org +4 -0 # Add noinline attribute # # include/linux/compiler-gcc3.h # 2004/02/18 22:54:05-08:00 akpm@osdl.org +4 -0 # Add noinline attribute # # ChangeSet # 2004/02/19 08:38:07-08:00 akpm@osdl.org # [PATCH] Use -funit-at-a-time on ia32 # # From: Andi Kleen # # The upcomming gcc 3.4 has a new compilation mode called unit-at-a-time. # What it does is to first load the whole file into memory and then generate # the output. This allows it to use a better inlining strategy, drop unused # static functions and use -mregparm automatically for static functions. # # It does not seem to compile significantly slower. # # This is also available in some of the 3.3 based "hammer branch" # compilers used in distributions (at least in SuSE and Mandrake) # # Some tests show impressive .text shrinkage from unit-at-a-time. # # e.g. here is the same kernel compiled with -fno-unit-at-a-time and # -funit-at-a-time with a gcc 3.4 snapshot. The gains are really # impressive: # # text data bss dec hex filename # 4129346 708629 207240 5045215 4cfbdf vmlinux-nounitatatime # 3999250 674853 207208 4881311 4a7b9f vmlinux-unitatatime # # .text shrinks by over 130KB!. And .data shrinks too. # # At first look the numbers look nearly too good to be true, but they have been # verified with several configurations and seem to be real. It looks like # we have a lot of stupid inlines or dead functions. I'm really not # sure why it is that much better. But it's hard to argue with hard # numbers. # # [A bloat-o-meter comparision between the two vmlinuxes can be found in # http://www.firstfloor.org/~andi/unit-vs-no-unit.gz . It doesn't show # any obvious candidates unfortunately, just lots of small changes] # # With the gcc 3.3-hammer from SuSE 9.0 the gains are a bit smaller, but # still noticeable (>100KB on .text) # # This patch enables -funit-at-a-time on ia32 if the compiler is gcc-3.4 or # later. We had several reports of gcc-3.3 producing very early lockups. # # arch/x86_64/Makefile # 2004/02/18 22:54:04-08:00 akpm@osdl.org +4 -1 # Use -funit-at-a-time on ia32 # # arch/i386/Makefile # 2004/02/18 22:54:04-08:00 akpm@osdl.org +4 -0 # Use -funit-at-a-time on ia32 # # ChangeSet # 2004/02/19 08:37:55-08:00 akpm@osdl.org # [PATCH] Add CONFIG for -mregparm=3 # # From: Andi Kleen , me. # # Using -mregparm=3 shrinks the kernel further: # # (compiled with gcc 3.4, without -funit-at-a-time, using the later and # together with -Os shrinks .text even more, making over 700KB difference) # # 4129346 708629 207240 5045215 4cfbdf vmlinux # 3892905 708629 207240 4808774 496046 vmlinux-regparm # # This one helps even more, >236KB .text difference. Clearly worth # the effort. # # This patch adds an option to use -mregparm=3 while compiling the kernel. I # did an LTP run and it showed no additional failures over an non regparm # kernel. # # According to some gcc developers it should be safe to use in all gccs that # are still supports (2.95 and up) # # I didn't make it the default because it will break all binary only modules # (although they can be fixed by adding a wrapper that calls them with # "asmlinkage"). Actually it may be a good idea to make this default with # 2.7.1 or somesuch. # # We add new kbuild infrastructure: the command # # scripts/gcc-version.sh $(CC) # # will print out the version of gcc in a canonical 4-digit form suitable for # performing numerical tests against. # DESC # arch/i386/Makefile,scripts/gcc-version.sh,Makefile small fixes # EDESC # From: Serge Belyshev <33554432@mtu-net.ru> # # arch/i386/Makefile: # * omitted $(KBUILD_SRC)/ in script call. # # scripts/gcc-version.sh: # * GNU tail no longer supports 'tail -1' syntax. # # We should consider adding -fweb option: # # vanilla: # $ size vmlinux # text data bss dec hex filename # 3056270 526780 386056 3969106 3c9052 vmlinux # # with -fweb: # $ size vmlinux # text data bss dec hex filename # 3049523 526780 386056 3962359 3c75f7 vmlinux # # Also note 0.1 ... 1.0% speedup in various benchmarks. # This option is not enabled by default at -O2 because it # (like -fomit-frame-pointer) makes debugging impossible. # # scripts/gcc-version.sh # 2004/02/18 22:54:04-08:00 akpm@osdl.org +14 -0 # Add CONFIG for -mregparm=3 # # include/asm-i386/module.h # 2004/02/18 22:54:04-08:00 akpm@osdl.org +7 -1 # Add CONFIG for -mregparm=3 # # arch/i386/Makefile # 2004/02/18 22:54:04-08:00 akpm@osdl.org +5 -0 # Add CONFIG for -mregparm=3 # # arch/i386/Kconfig # 2004/02/18 22:54:04-08:00 akpm@osdl.org +13 -0 # Add CONFIG for -mregparm=3 # # scripts/gcc-version.sh # 2004/02/18 22:54:04-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/scripts/gcc-version.sh # # ChangeSet # 2004/02/19 08:37:44-08:00 akpm@osdl.org # [PATCH] page_add_rmap(): remove meaningless test # # Remove page validity test. I had a warning in there for a few weeks, no # reports of it happening. # # mm/rmap.c # 2004/02/18 22:54:03-08:00 akpm@osdl.org +1 -1 # page_add_rmap(): remove meaningless test # # ChangeSet # 2004/02/19 08:37:32-08:00 akpm@osdl.org # [PATCH] slab: hexdump for check_poison # # From: Manfred Spraul # # The patch is designed improve the diagnostics which are presented when the # slab memory poison detector triggers. # # # check_poison_obj checks for write accesses after kfree by comparing the # object contents with the poison value. The current implementation contains # several flaws: # # - it accepts both POISON_BEFORE and POISON_AFTER. check_poison_obj is # only called with POISON_AFTER poison bytes. Fix: only accept # POISON_AFTER. # # - the output is unreadable. Fix: use hexdump. # # - if a large objects is corrupted, then the relevant lines can scroll of # the screen/dmesg buffer. Fix: line limit. # # - it can access addresses behind the end of the object, which can oops # with CONFIG_DEBUG_PAGEALLOC. Fix: bounds checks. # # Additionally, the patch contains the following changes: # # - rename POISON_BEFORE and POISON_AFTER to POISON_FREE and POISON_INUSE. # The old names are ambiguous. # # - use the new hexdump object function in ptrinfo. # # - store_stackinfo was called with wrong parameters: it should store # caller, i.e. __builtin_return_address(0), not POISON_AFTER in the # object. # # - dump both the object before and after the corrupted one, not just the # one after. # # Example output: # <<< # Slab corruption: start=194e708c, len=2048 # Redzone: 0x5a2cf071/0x5a2cf071. # Last user: [<02399d7c>](dummy_init_module+0x1c/0xb0) # 010: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 7b # 030: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 63 # Prev obj: start=194e6880, len=2048 # Redzone: 0x5a2cf071/0x5a2cf071. # Last user: [<00000000>](0x0) # 000: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b # 010: 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b 6b # <<< # # mm/slab.c # 2004/02/18 22:54:02-08:00 akpm@osdl.org +98 -60 # slab: hexdump for check_poison # # ChangeSet # 2004/02/19 08:37:22-08:00 akpm@osdl.org # [PATCH] prevent ptrace from altering page permissions # # From: Roland McGrath # # Under some circumstances, ptrace PEEK/POKE_TEXT can cause page permissions # to be permanently changed. Thsi causes changes in application behaviour # when run under gdb. # # Fix that by only marking the pte as writeable if the vma is marked for # writing. A write fault thus unshares the page but doesn't necessarily make # it writeable. # # mm/memory.c # 2004/02/18 22:54:01-08:00 akpm@osdl.org +32 -6 # prevent ptrace from altering page permissions # # ChangeSet # 2004/02/19 08:37:12-08:00 akpm@osdl.org # [PATCH] slab: print slab name in kmem_cache_init() # # Print the name of the offending slab if we're going to go BUG in # kmem_cache_init(). # # mm/slab.c # 2004/02/18 22:54:00-08:00 akpm@osdl.org +4 -1 # slab: print slab name in kmem_cache_init() # # ChangeSet # 2004/02/19 08:37:00-08:00 akpm@osdl.org # [PATCH] ramdisk cleanup # # Fairly pointless coding-style cleanups which I've been sitting on for ages. # The ramdisk driver is still buggy: it drops pagecache when unmounted. I # still need to fix this. # # Apparently it also displays data corruption under load even when not # unmounted. # # drivers/block/rd.c # 2004/02/18 22:53:59-08:00 akpm@osdl.org +36 -27 # ramdisk cleanup # # ChangeSet # 2004/02/18 22:15:10-08:00 gerg@snapgear.com # [PATCH] fixes to ColdFire/5407 startup code # # Correct the cache setup bits for the 5407. This enables the write # buffers properly (despite what the previous comment said). This # combined with fixed cache flushing code provides a nice performance # boost on the 5407. # # Also fix the ROMfs setup to only move the ROMfs region if it is actually # configured. # # arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S # 2004/02/18 16:43:18-08:00 gerg@snapgear.com +9 -1 # fixes to ColdFire/5407 startup code # # ChangeSet # 2004/02/18 21:45:08-08:00 gerg@snapgear.com # [PATCH] add m68k elf relocation types to elf.h # # Added ELF relocation type defines. These are needed by the module # loading code for m68knommu. # # include/asm-m68knommu/elf.h # 2004/02/18 16:47:00-08:00 gerg@snapgear.com +27 -0 # add m68k elf relocation types to elf.h # # ChangeSet # 2004/02/18 21:41:28-08:00 gerg@snapgear.com # [PATCH] allow configuration for shared flat binary support # # This adds the configuration option to enable the uClinux shared flat # binary support. The code support is already in the binfmt_load code, # just the config option is missing. # # fs/Kconfig.binfmt # 2004/02/18 16:46:02-08:00 gerg@snapgear.com +6 -0 # allow configuration for shared flat binary support # # ChangeSet # 2004/02/18 21:41:19-08:00 gerg@snapgear.com # [PATCH] fix memory leaks in binfmt_flat loader # # Fix a number of memory leaks in the uClinux binfmt_flat loader. All are # related to not cleaning up properly on failure conditions. # # fs/binfmt_flat.c # 2004/02/18 21:07:37-08:00 gerg@snapgear.com +20 -12 # fix memory leaks in binfmt_flat loader # # ChangeSet # 2004/02/18 21:00:18-08:00 akpm@osdl.org # [PATCH] aio sysctl parms # # From: Janet Morgan # # It looks like aio_nr and aio_max_nr were intended to be sysctl parameters. # # kernel/sysctl.c # 2004/02/18 19:43:21-08:00 akpm@osdl.org +16 -0 # aio sysctl parms # # include/linux/sysctl.h # 2004/02/18 19:43:21-08:00 akpm@osdl.org +2 -0 # aio sysctl parms # # include/linux/aio.h # 2004/02/18 19:43:21-08:00 akpm@osdl.org +2 -1 # aio sysctl parms # # Documentation/sysctl/fs.txt # 2004/02/18 19:43:21-08:00 akpm@osdl.org +10 -0 # aio sysctl parms # # Documentation/filesystems/proc.txt # 2004/02/18 19:43:21-08:00 akpm@osdl.org +9 -0 # aio sysctl parms # # ChangeSet # 2004/02/18 21:00:09-08:00 akpm@osdl.org # [PATCH] mark ftape un-removable # # From: Christoph Hellwig # # I've just grepped over the tree for reamining MOD_INC_USE_COUNT users, and # ftape is a really horrible one, it relies on MOD_{INC,DEV}_USE_COUNT in the # most horrible places + it's own bookkepping and the <= 2.4 may unload # hooks. And although I don't have the hardware I can guarantee it doesn't # work as expected. # # So let's just remove the module_exit handler and mark it unremovable, if # someone wants to fix up ftape later it's fine with me, but it's a really # scary driver.. # # drivers/char/ftape/compressor/zftape-compress.c # 2004/02/18 19:43:21-08:00 akpm@osdl.org +1 -44 # mark ftape un-removable # # ChangeSet # 2004/02/18 21:00:00-08:00 akpm@osdl.org # [PATCH] Add C99 initializers to arch/i386/pci/fixup.c # # From: "Art Haas" # # Here's a small patch that adds C99 initializers to the file. # # arch/i386/pci/fixup.c # 2004/02/18 19:43:20-08:00 akpm@osdl.org +103 -18 # Add C99 initializers to arch/i386/pci/fixup.c # # ChangeSet # 2004/02/18 20:59:51-08:00 akpm@osdl.org # [PATCH] crc32.c copyright fix # # From: Matt Domsch # # Patch below applies to both 2.4.25 and 2.6.3, and replaces the public # domain statement and non-warranty with the GPL, as is permitted by the code # being in the public domain, and is done with legal advice. # # lib/crc32.c # 2004/02/18 19:43:20-08:00 akpm@osdl.org +8 -9 # crc32.c copyright fix # # ChangeSet # 2004/02/18 20:59:42-08:00 akpm@osdl.org # [PATCH] tuner driver fixes # # From: Gerd Knorr # # "options tuner type=2" is just there for historical reasons and should # only be used/needed if the main driver doesn't allow to configure the # tuner type. I'm not sure whenever I can remove that altogether without # breaking anything. There are several users of the tuner module, some # outside the standard kernel tree ... # # > > if (type < TUNERS) { # > > + t->type = type; # > > printk("tuner: type forced to %d (%s) [insmod]\n", # > > t->type,tuners[t->type].name); # > > set_type(client,type); # # That is wrong, it will break in other corner cases, it may cause the # set_type() function not doing the initializations. # # The prink can also be dropped because set_type does that too. The patch # below removes that. It also makes the kernel messages a bit more verbose # and adds support for two new tuners. # # include/media/tuner.h # 2004/02/18 19:43:19-08:00 akpm@osdl.org +3 -1 # tuner driver fixes # # drivers/media/video/tuner.c # 2004/02/18 19:43:19-08:00 akpm@osdl.org +17 -11 # tuner driver fixes # # ChangeSet # 2004/02/18 20:59:33-08:00 akpm@osdl.org # [PATCH] wireless/Kconfig enable/select complete replacement # # From: mcgrof@studorgs.rutgers.edu (Luis R. Rodriguez) # # Complete the migration from Kconfig's undocumented "enable" to "select". # # drivers/net/wireless/Kconfig # 2004/02/18 19:43:19-08:00 akpm@osdl.org +2 -2 # wireless/Kconfig enable/select complete replacement # # ChangeSet # 2004/02/18 20:59:24-08:00 akpm@osdl.org # [PATCH] Fix sprintf modifiers in usr/gen_init_cpio.c for cygwin # # From: Pragnesh Sampat # # The file initramfs_data.cpio is slightly different when generated on # cygwin, compared to linux, which causes the kernel to panic with the # message "no cpio magic" (See Documentation/early-userspace/README). # # The problem in cpio generation is due to the difference in sprintf # modifiers on cygwin. The code uses "%08ZX" for strlen of a device node. # printf man pages discourages "Z" and has 'z' instead. Both of these are # not available on cygwin sprintf (at least some versions of cygwin). The # net result of all of this is that the generated file literally contains # "ZX" and then the strlen after that and messes up that 110 offset etc. The # file is 516 bytes long on the system that I tested and on linux it is 512 # bytes. # # The fix below just uses "%08X" for that field. # # usr/gen_init_cpio.c # 2004/02/18 19:43:18-08:00 akpm@osdl.org +8 -8 # Fix sprintf modifiers in usr/gen_init_cpio.c for cygwin # # ChangeSet # 2004/02/18 20:59:15-08:00 akpm@osdl.org # [PATCH] smbfs: support the loop driver # # From: Urban Widmark # # Add the necessary bits for loop-over-smbfs. # # fs/smbfs/smbiod.c # 2004/02/18 19:43:18-08:00 akpm@osdl.org +3 -0 # smbfs: support the loop driver # # fs/smbfs/request.c # 2004/02/18 19:43:18-08:00 akpm@osdl.org +6 -0 # smbfs: support the loop driver # # fs/smbfs/proc.c # 2004/02/18 19:43:18-08:00 akpm@osdl.org +0 -6 # smbfs: support the loop driver # # fs/smbfs/file.c # 2004/02/18 19:43:18-08:00 akpm@osdl.org +22 -0 # smbfs: support the loop driver # # ChangeSet # 2004/02/18 20:59:06-08:00 akpm@osdl.org # [PATCH] Codingstyle update # # From: Michael Frank # # Documentation/CodingStyle # 2004/02/18 19:43:17-08:00 akpm@osdl.org +215 -58 # Codingstyle update # # ChangeSet # 2004/02/18 20:58:57-08:00 akpm@osdl.org # [PATCH] Remove overenthusiastic BUG in smp_boot_cpus # # From: "Martin J. Bligh" # # There's no real need to BUG and stop the system from booting if the BIOS # spec'ed apicid for the boot CPU isn't correct - we can continue perfectly # well with the real one. # # arch/i386/kernel/smpboot.c # 2004/02/18 19:43:17-08:00 akpm@osdl.org +1 -2 # Remove overenthusiastic BUG in smp_boot_cpus # # ChangeSet # 2004/02/18 20:58:48-08:00 akpm@osdl.org # [PATCH] sf16fmr2 radio card driver # # From: "ZIGLIO, Frediano, VF-IT" # # Add a new driver for the SF16FMR2 Radio card. # # drivers/media/radio/radio-sf16fmr2.c # 2004/02/18 19:43:16-08:00 akpm@osdl.org +447 -0 # sf16fmr2 radio card driver # # drivers/media/radio/Makefile # 2004/02/18 19:43:16-08:00 akpm@osdl.org +1 -0 # sf16fmr2 radio card driver # # drivers/media/radio/Kconfig # 2004/02/18 19:43:16-08:00 akpm@osdl.org +14 -0 # sf16fmr2 radio card driver # # drivers/media/radio/radio-sf16fmr2.c # 2004/02/18 19:43:16-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/drivers/media/radio/radio-sf16fmr2.c # # ChangeSet # 2004/02/18 20:58:38-08:00 akpm@osdl.org # [PATCH] Inefficient TLB flush fix # # From: Martin Hicks # # This is a patch based on one that Jack Steiner sent to the ia64 list in # November. The original thread can be found at: # # http://marc.theaimsgroup.com/?l=linux-ia64&m=106869606922555&w=2 # # I created the little wrapper function that was requested. I think the only # other arch, other than ia64, that doesn't at least include asm-generic/tlb.h # is arm. # # # Something appears broken in TLB flushing on IA64 (& possibly other # architectures). Functionally, it works but performance is bad on systems # with large cpu counts. # # The result is that TLB flushing in exit_mmap() is frequently being done via # IPIs to all cpus rather than with a "ptc" instruction or with a new # context.. # # mm/memory.c # 2004/02/18 19:43:15-08:00 akpm@osdl.org +2 -1 # Inefficient TLB flush fix # # include/asm-ia64/tlb.h # 2004/02/18 19:43:15-08:00 akpm@osdl.org +6 -0 # Inefficient TLB flush fix # # include/asm-generic/tlb.h # 2004/02/18 19:43:15-08:00 akpm@osdl.org +5 -0 # Inefficient TLB flush fix # # include/asm-arm/tlb.h # 2004/02/18 19:43:15-08:00 akpm@osdl.org +6 -0 # Inefficient TLB flush fix # # ChangeSet # 2004/02/18 20:58:29-08:00 akpm@osdl.org # [PATCH] menuconfig: fix the check for ncurses-devel # # From: Sam Ravnborg # # Corrected check for missing ncurses-devel when executing "make menuconfig". # Now tell user to install 'ncurses-devel' if check fails. # # scripts/lxdialog/Makefile # 2004/02/18 19:43:15-08:00 akpm@osdl.org +4 -6 # menuconfig: fix the check for ncurses-devel # # ChangeSet # 2004/02/18 20:58:20-08:00 akpm@osdl.org # [PATCH] Fix make rpm when using RH9 or Fedora.. # # From: Thomas Davis # # Doing a 'make rpm' will fail with the current RH9/Fedora RPM macros. # # The failure message is this: # # Processing files: kernel-debuginfo-2.6.3rc1mm1-12 # error: Could not open %files file /usr/src/redhat/BUILD/kernel-2.6.3rc1mm1/debugfiles.list: No such file or directory # # The fix is this patch: # # scripts/mkspec # 2004/02/18 19:43:14-08:00 akpm@osdl.org +1 -0 # Fix make rpm when using RH9 or Fedora.. # # ChangeSet # 2004/02/18 20:58:11-08:00 akpm@osdl.org # [PATCH] dm-crypt # # From: Christophe Saout # # Adds a crypto module for device-mapper. The intent here is to remove # cryptoloop ASAP, to pull the remapping gunk out of the loops driver and to # migrate people onto dm-crypt. It is on-disk compatible with existing # cryptolop installations. # # See http://www.saout.de/misc/dm-crypt/ for usage details. # # drivers/md/dm-crypt.c # 2004/02/18 19:43:14-08:00 akpm@osdl.org +777 -0 # dm-crypt # # drivers/md/dm-crypt.c # 2004/02/18 19:43:14-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/drivers/md/dm-crypt.c # # drivers/md/Makefile # 2004/02/18 19:43:14-08:00 akpm@osdl.org +1 -0 # dm-crypt # # drivers/md/Kconfig # 2004/02/18 19:43:14-08:00 akpm@osdl.org +18 -0 # dm-crypt # # ChangeSet # 2004/02/18 20:58:01-08:00 akpm@osdl.org # [PATCH] Disable bootmem warning # # From: Andi Kleen # # Make the "hm, page reserved twice" message dependent on CONFIG_DEBUG_BOOTMEM. # # mm/bootmem.c # 2004/02/18 19:43:13-08:00 akpm@osdl.org +4 -1 # Disable bootmem warning # # ChangeSet # 2004/02/18 20:57:52-08:00 akpm@osdl.org # [PATCH] ide-tape: remove obsolete onstream support # # From: Willem Riede # # # The onstream drives, be they scsi, atapi, ieee1394 or usb, are supported by the # osst driver. When the drives were new, code was introduced in ide-tape # independently, but never really maintained since. There are issues with the # drives I found and dealt with in osst, that ide-tape doesn't address. # # So this code in ide-tape is both redundant and imperfect. I assumed from # http://marc.theaimsgroup.com/?l=linux-kernel&m=107550547613846&w=2 that there # was buy in for removing it. # # When this patch is applied, ide-tape will refuse to attach to an onstream DI # drive, and will write to syslog to use ide-scsi + osst instead. # # drivers/ide/ide-tape.c # 2004/02/18 19:43:13-08:00 akpm@osdl.org +31 -1631 # ide-tape: remove obsolete onstream support # # ChangeSet # 2004/02/18 20:57:43-08:00 akpm@osdl.org # [PATCH] do_swap_page() return value fix # # From: BlaisorBlade # # An exhausted do_swap_page() should return VM_FAULT_OOM rather than -ENOMEM. # # mm/memory.c # 2004/02/18 19:43:12-08:00 akpm@osdl.org +1 -1 # do_swap_page() return value fix # # ChangeSet # 2004/02/18 20:57:34-08:00 akpm@osdl.org # [PATCH] slab: remove extraneous printk # # From: "David S. Miller" # # From: YOSHIFUJI Hideaki # # If I create some kmem cache on 64-bit with like 3 u32's in it, it should # silently just work and not warn. # # mm/slab.c # 2004/02/18 20:00:31-08:00 akpm@osdl.org +2 -3 # slab: remove extraneous printk # # ChangeSet # 2004/02/18 20:57:25-08:00 akpm@osdl.org # [PATCH] Fix race in epoll_ctl(EPOLL_CTL_MOD) # # From: Davide Libenzi # # A potential race can happen in epoll_ctl(EPOLL_CTL_MOD) where an event can # happen in between f_op->poll() and the lock on ep->lock (we cannot call # f_op->poll() inside a lock, and the f_op->poll() callback does not carry # any info at the current time - missing wake_up_info() already ;). In that # case the event would be removed. We can easily leave the event inside the # ready list and have the ep_send_events() logic do the job for us at later # time. (Thanks to david.lee@teracruz.com for reporting the thing, since it # shouldn't have been a nice one ;) # # fs/eventpoll.c # 2004/02/18 19:43:11-08:00 akpm@osdl.org +1 -2 # Fix race in epoll_ctl(EPOLL_CTL_MOD) # # ChangeSet # 2004/02/18 20:57:16-08:00 akpm@osdl.org # [PATCH] add clock_was_set() to all architectures # # From: Anton Blanchard # # Add clock_was_set to all architectures. I'm disappointed this wasnt done by # whoever wrote the code. # # (It is a callback which the arch-specific RTC-updating code must make when # someone sets the time). # # arch/v850/kernel/time.c # 2004/02/18 19:43:10-08:00 akpm@osdl.org +1 -0 # add clock_was_set() to all architectures # # arch/um/kernel/time.c # 2004/02/18 19:43:10-08:00 akpm@osdl.org +1 -0 # add clock_was_set() to all architectures # # arch/sparc64/kernel/time.c # 2004/02/18 19:43:10-08:00 akpm@osdl.org +1 -0 # add clock_was_set() to all architectures # # arch/sparc/kernel/time.c # 2004/02/18 19:43:10-08:00 akpm@osdl.org +1 -0 # add clock_was_set() to all architectures # # arch/s390/kernel/time.c # 2004/02/18 19:43:10-08:00 akpm@osdl.org +1 -0 # add clock_was_set() to all architectures # # arch/ppc64/kernel/time.c # 2004/02/18 19:43:10-08:00 akpm@osdl.org +1 -0 # add clock_was_set() to all architectures # # arch/ppc/kernel/time.c # 2004/02/18 19:43:10-08:00 akpm@osdl.org +1 -0 # add clock_was_set() to all architectures # # arch/parisc/kernel/time.c # 2004/02/18 19:43:10-08:00 akpm@osdl.org +1 -0 # add clock_was_set() to all architectures # # arch/mips/kernel/time.c # 2004/02/18 19:43:10-08:00 akpm@osdl.org +1 -1 # add clock_was_set() to all architectures # # arch/m68knommu/kernel/time.c # 2004/02/18 19:43:10-08:00 akpm@osdl.org +1 -0 # add clock_was_set() to all architectures # # arch/m68k/kernel/time.c # 2004/02/18 19:43:10-08:00 akpm@osdl.org +1 -0 # add clock_was_set() to all architectures # # arch/h8300/kernel/time.c # 2004/02/18 19:43:10-08:00 akpm@osdl.org +1 -0 # add clock_was_set() to all architectures # # arch/cris/kernel/time.c # 2004/02/18 19:43:10-08:00 akpm@osdl.org +1 -0 # add clock_was_set() to all architectures # # arch/arm26/kernel/time.c # 2004/02/18 19:43:10-08:00 akpm@osdl.org +1 -0 # add clock_was_set() to all architectures # # arch/alpha/kernel/time.c # 2004/02/18 19:43:10-08:00 akpm@osdl.org +1 -0 # add clock_was_set() to all architectures # # ChangeSet # 2004/02/18 20:57:07-08:00 akpm@osdl.org # [PATCH] Module headers cleanup # # From: Brian Gerst # # Cleans up some leftovers from the old module loader: # # - Remove unused defines from modules.h # # - Remove unused file modsetver.h # # include/asm-parisc/module.h # 2004/02/18 19:43:10-08:00 akpm@osdl.org +0 -5 # Module headers cleanup # # include/asm-h8300/module.h # 2004/02/18 19:43:10-08:00 akpm@osdl.org +0 -5 # Module headers cleanup # # include/asm-arm26/module.h # 2004/02/18 19:43:10-08:00 akpm@osdl.org +0 -5 # Module headers cleanup # # BitKeeper/deleted/.del-modsetver.h~59f44c7fa618daf5 # 2004/02/18 20:57:02-08:00 akpm@osdl.org +0 -0 # Delete: include/linux/modsetver.h # # ChangeSet # 2004/02/18 20:56:58-08:00 akpm@osdl.org # [PATCH] Documentation on how to debug modules # # From: Alex Goddard # # How to debug module loading problems. The wording is a slightly changed # version of what Rusty said. # # Documentation/debugging-modules.txt # 2004/02/18 19:43:09-08:00 akpm@osdl.org +18 -0 # Documentation on how to debug modules # # Documentation/debugging-modules.txt # 2004/02/18 19:43:09-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/Documentation/debugging-modules.txt # # ChangeSet # 2004/02/18 20:56:48-08:00 akpm@osdl.org # [PATCH] Fix __release_region() race # # From: MAEDA Naoaki # # I am testing PCI hot-plug in 2.6.2 kernel, but sometimes a struct resource # tree in kernel/resource.c was broken if multiple hot-plug requests are # issued at the same time. # # The reason is lots of drivers call release_region() on hot removal, and # __release_region(), which is invoked by release_region() macro, changes the # tree without holding a writer lock for resource_lock. # # I think __release_region() must hold a writer lock as well as # __request_region() does. # # A following patch fixes the issue in my environment. # # kernel/resource.c # 2004/02/18 19:43:09-08:00 akpm@osdl.org +6 -0 # Fix __release_region() race # # ChangeSet # 2004/02/18 20:56:39-08:00 akpm@osdl.org # [PATCH] remove max_anon limit # # From: Tim Hockin # # Remove the max_anon via dynamically allocation. We also change the # idr_pre_get() interface to take a gfp mask, which should have always been # there. # # lib/idr.c # 2004/02/18 19:43:08-08:00 akpm@osdl.org +6 -6 # remove max_anon limit # # kernel/posix-timers.c # 2004/02/18 19:43:08-08:00 akpm@osdl.org +1 -1 # remove max_anon limit # # init/main.c # 2004/02/18 19:43:08-08:00 akpm@osdl.org +1 -0 # remove max_anon limit # # include/linux/idr.h # 2004/02/18 19:43:08-08:00 akpm@osdl.org +1 -1 # remove max_anon limit # # include/linux/fs.h # 2004/02/18 19:43:08-08:00 akpm@osdl.org +1 -0 # remove max_anon limit # # fs/super.c # 2004/02/18 19:43:08-08:00 akpm@osdl.org +20 -8 # remove max_anon limit # # ChangeSet # 2004/02/18 20:56:30-08:00 akpm@osdl.org # [PATCH] oprofile: add Pentium Mobile support # # From: Philippe Elie # # From: Will Cohen # # Add oprofile support for Pentium Mobile (P6 core). Pentium Mobile needs to # unmask LVPTC vector, since it doesn't hurt other P6 core based cpus we do # it unconditionally for all these. # # This patch require userspace tools >= 0.8 (only in sourceforge cvs currently) # # arch/i386/oprofile/op_model_ppro.c # 2004/02/18 19:43:07-08:00 akpm@osdl.org +5 -0 # oprofile: add Pentium Mobile support # # arch/i386/oprofile/nmi_int.c # 2004/02/18 19:43:07-08:00 akpm@osdl.org +3 -1 # oprofile: add Pentium Mobile support # # ChangeSet # 2004/02/18 20:56:21-08:00 akpm@osdl.org # [PATCH] oprofile: ARM infrastructure # # From: Philippe Elie # # From: Zwane Mwaikambo # # This patch adds infrastructure code and enables ARM to utilise the timer # int oprofile driver. There is PMU code under development for the XScale # but that is still forthcoming. In the meantime you can use the timer int # driver with an updated Oprofile-CVS userspace (SF is a bit slow, please # allow 24hrs). # # arch/arm/oprofile/Makefile # 2004/02/18 19:43:07-08:00 akpm@osdl.org +9 -0 # oprofile: ARM infrastructure # # arch/arm/oprofile/Kconfig # 2004/02/18 19:43:07-08:00 akpm@osdl.org +23 -0 # oprofile: ARM infrastructure # # drivers/oprofile/timer_int.c # 2004/02/18 19:43:07-08:00 akpm@osdl.org +0 -1 # oprofile: ARM infrastructure # # arch/arm/oprofile/init.c # 2004/02/18 19:43:07-08:00 akpm@osdl.org +22 -0 # oprofile: ARM infrastructure # # arch/arm/oprofile/Makefile # 2004/02/18 19:43:07-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/arch/arm/oprofile/Makefile # # arch/arm/oprofile/Kconfig # 2004/02/18 19:43:07-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/arch/arm/oprofile/Kconfig # # arch/arm/kernel/time.c # 2004/02/18 19:43:07-08:00 akpm@osdl.org +3 -0 # oprofile: ARM infrastructure # # arch/arm/Makefile # 2004/02/18 19:43:07-08:00 akpm@osdl.org +1 -0 # oprofile: ARM infrastructure # # arch/arm/Kconfig # 2004/02/18 19:43:07-08:00 akpm@osdl.org +2 -0 # oprofile: ARM infrastructure # # arch/arm/oprofile/init.c # 2004/02/18 19:43:07-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/arch/arm/oprofile/init.c # # ChangeSet # 2004/02/18 20:56:11-08:00 akpm@osdl.org # [PATCH] Oprofile: fix nmi_timer_int detection # # From: Philippe Elie # # From: Zwane Mwaikambo # # The nmi_timer_int oprofile driver was enabling itself unconditionally if an # SMP kernel was being used on a UP system without an IOAPIC. # # Tested on a P5 using NMI timer int driver and UP system using timer int # driver both running an SMP kernel. # # 2004-02-11 Zwane Mwaikambo # # * arch/i386/kernel/nmi.c: export nmi_active # * arch/i386/oprofile/nmi_timer_int.c: use it to check if owe can use # an nmi interrupt # # arch/x86_64/kernel/nmi.c # 2004/02/18 19:43:06-08:00 akpm@osdl.org +2 -1 # Oprofile: fix nmi_timer_int detection # # arch/i386/oprofile/nmi_timer_int.c # 2004/02/18 19:43:06-08:00 akpm@osdl.org +5 -1 # Oprofile: fix nmi_timer_int detection # # arch/i386/kernel/nmi.c # 2004/02/18 19:43:06-08:00 akpm@osdl.org +2 -1 # Oprofile: fix nmi_timer_int detection # # ChangeSet # 2004/02/18 20:56:02-08:00 akpm@osdl.org # [PATCH] 3c59x: bring back the `enable_wol' option # # Some machines appear to have BIOS problems which are causing 3c59x adapters # to come up in a powered-off state when WOL and PM are enabled. # # So bring back the 2.4 `enable_wol' module option which disables wake-on-lan # unless the user specifically asked for it. # # drivers/net/3c59x.c # 2004/02/18 19:43:06-08:00 akpm@osdl.org +17 -4 # 3c59x: bring back the `enable_wol' option # # Documentation/networking/vortex.txt # 2004/02/18 19:43:06-08:00 akpm@osdl.org +13 -0 # 3c59x: bring back the `enable_wol' option # # ChangeSet # 2004/02/18 20:55:53-08:00 akpm@osdl.org # [PATCH] cleanup patch that prepares for 4Kb stacks # # From: Arjan van de Ven # # I have 4Kb stacks + IRQ stacks working in my tree. The biggest part of the # 4K-stacks work is changing hardcoded 8Kb assumptions to the proper, # pre-existing define for this. That part of the patch is appropriate in # general, even when 4Kb stacks might not be. # # include/asm-i386/thread_info.h # 2004/02/18 19:43:05-08:00 akpm@osdl.org +6 -3 # cleanup patch that prepares for 4Kb stacks # # arch/i386/kernel/traps.c # 2004/02/18 19:43:05-08:00 akpm@osdl.org +1 -1 # cleanup patch that prepares for 4Kb stacks # # arch/i386/kernel/process.c # 2004/02/18 19:43:05-08:00 akpm@osdl.org +4 -2 # cleanup patch that prepares for 4Kb stacks # # arch/i386/kernel/irq.c # 2004/02/18 19:43:05-08:00 akpm@osdl.org +1 -1 # cleanup patch that prepares for 4Kb stacks # # arch/i386/kernel/head.S # 2004/02/18 19:43:05-08:00 akpm@osdl.org +3 -1 # cleanup patch that prepares for 4Kb stacks # # arch/i386/kernel/entry.S # 2004/02/18 19:43:05-08:00 akpm@osdl.org +2 -2 # cleanup patch that prepares for 4Kb stacks # # ChangeSet # 2004/02/18 20:55:44-08:00 akpm@osdl.org # [PATCH] fix display of NBD in /proc/partitions # # The recent change to /proc/partitions which prevents it from displaying # removeable media accidentally caused 128 NBD and 16 ramdisk partitions to # appear in /proc/partitions instead. # # So add a specific gendisk flag which says "don't show me in /proc/partitions" # and use that. # # include/linux/genhd.h # 2004/02/18 19:43:04-08:00 akpm@osdl.org +5 -4 # fix display of NBD in /proc/partitions # # drivers/block/rd.c # 2004/02/18 19:43:04-08:00 akpm@osdl.org +1 -0 # fix display of NBD in /proc/partitions # # drivers/block/nbd.c # 2004/02/18 19:43:04-08:00 akpm@osdl.org +1 -0 # fix display of NBD in /proc/partitions # # drivers/block/genhd.c # 2004/02/18 19:43:04-08:00 akpm@osdl.org +3 -2 # fix display of NBD in /proc/partitions # # ChangeSet # 2004/02/18 20:55:35-08:00 akpm@osdl.org # [PATCH] skip offline CPUs in show_free_areas # # From: Christoph Hellwig # # Don't try to display the per-cpu information for CPUs which aren't there. # # mm/page_alloc.c # 2004/02/18 19:43:04-08:00 akpm@osdl.org +7 -1 # skip offline CPUs in show_free_areas # # ChangeSet # 2004/02/18 20:55:26-08:00 akpm@osdl.org # [PATCH] off_t in nfsd_commit needs to be loff_t # # From: Neil Brown , # # From: Miquel van Smoorenburg # # While I was stress-testing NFS/XFS on 2.6.1/2.6.2-rc, I found that # sometimes my "dd" would exit with: # # # dd if=/dev/zero bs=4096 > /mnt/file # dd: writing `standard output': Invalid argument # 1100753+0 records in # 1100752+0 records out # # After adding some debug printk's to the server and client code and some # tcpdump-ing, I found that the NFSERR_INVAL was returned by nfsd_commit on # the server. # # Turns out that the "offset" argument is off_t instead of loff_t. It isn't # used at all (unfortunately), but it _is_ checked for sanity, so that's # where the error came from. # # include/linux/nfsd/nfsd.h # 2004/02/18 19:43:03-08:00 akpm@osdl.org +1 -1 # off_t in nfsd_commit needs to be loff_t # # fs/nfsd/vfs.c # 2004/02/18 19:43:03-08:00 akpm@osdl.org +1 -1 # off_t in nfsd_commit needs to be loff_t # # fs/nfsd/nfs3proc.c # 2004/02/18 19:43:03-08:00 akpm@osdl.org +2 -2 # off_t in nfsd_commit needs to be loff_t # # ChangeSet # 2004/02/18 20:55:17-08:00 akpm@osdl.org # [PATCH] drivers/char/vt possible race # # From: Benjamin Herrenschmidt # # I falled again on the crash in con_do_write() with driver->data beeing # NULL. It happens during boot, when userland is playing open/close games # with tty's, I was intentionally typing keys like mad during boot trying to # trigger another problem when this one poped up. # # Looking at the code, I'm not sure how protected we are by the above (tty) # layer, paulus told me to not rely on anything like locking coming from # there, so I decided to extend the scope of the console semaphore one more # bit to cover races between calls to con_open, con_close and con_write. # Note that in con_do_write, I intentionally drop the semaphore to avoid # keeping it held when waiting on the local buffer, and I added some sanity # checks on tty->driver_data with some printk's in case we still have an open # race by the tty layer. At least, now, the couple vc_allocated & # tty->driver_data should be protected though. # # drivers/char/vt.c # 2004/02/18 19:43:03-08:00 akpm@osdl.org +29 -5 # drivers/char/vt possible race # # ChangeSet # 2004/02/18 20:55:08-08:00 akpm@osdl.org # [PATCH] /proc thread visibility fixes # # From: Kingsley Cheung # # Is is possible to examine the data of tasks currently existing in the system # which are not threads of the same thread group. # # For example, the only task in the group where init is group leader is itself: # # gen2 02:50:44 ~: ls /proc/1/task # 1 # # However, I can then read the contents of 'stat' for any other task in the # system: # # gen2 02:49:45 ~: cat /proc/1/task/$$/stat # 1669 (bash) S 1668 1669 1669 34816 1730 256 1480 6479 12 4 8 5 5 17 15 0 1 0 # +8065 3252224 451 4294967295 134512640 134955932 3221225104 3221222840 # +4294960144 0 65536 3686404 1266761467 3222442959 0 0 17 0 0 0 # # I had a look at fs/proc/base.c and found that the 'lookup' functions for # these directories were checking that the task in question existed, but # overlooked the following: # # 1. In the function proc_pid_lookup, a check is required to ensure that # the task in question is a thread group leader. Without the check, any # task can have its data retrieved accordingly. Consider the following. # There is a multithreaded process 1777. # # gen2 23:22:47 /proc/1777: ls task # 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 # # However, I can read the stat file for its thread 1778 as follows: # # gen2 23:22:50 /proc/1777: cat /proc/1778/stat # 1778 (multithreadtest) T 1777 1777 1672 34816 1672 64 0 0 0 0 14 17 0 0 15 0 12 0 8871 24727552 104 4294967295 134512640 134515104 3221222496 1077365276 4294960144 0 0 0 0 3222479248 0 0 -1 1 0 0 # # But 1778 is not meant to show up in /proc/, as intended right?: # # gen2 23:22:56 /proc/1777: ls /proc/ # 1 1365 1661 1793 881 dma kcore scsi # 10 1371 1662 18 9 driver kmsg self # 1014 1372 1663 2 909 execdomains loadavg slabinfo # 1032 14 1664 3 963 fb locks stat # 1062 15 1665 4 966 filesystems mdstat swaps # 1066 16 1666 5 buddyinfo fs meminfo sys # 1067 1605 1669 6 bus ide misc sysrq-trigger # 1087 1610 1670 7 cmdline interrupts modules sysvipc # 1095 1611 1671 736 cpuinfo iomem mounts tty # 11 1641 1672 8 crypto ioports mtrr uptime # 12 1658 17 807 devices irq net version # 13 1660 1777 810 diskstats kallsyms partitions vmstat # # 2. The other part of the bug is in the function proc_task_lookup. Here # there needs to be a check that the task X is indeed a thread of the # thread group Y when we read /proc//task/. # # Right now, this check does not exist, which allows for any existing # task to have its data read from another thread group directory. The # following reads the stat directory of my bash shell from the thread # group 1. # # gen2 23:28:07 ~: cd /proc/1 # gen2 23:28:10 /proc/1: ls # auxv cwd exe maps mounts stat status wchan # cmdline environ fd mem root statm task # gen2 23:28:11 /proc/1: ls task # 1 # gen2 23:28:27 /proc/1: cat task/$$/stat # 1671 (bash) S 1670 1671 1671 34817 1802 256 1953 8101 12 4 10 6 9 26 15 0 1 0 5789 3252224 454 4294967295 134512640 134955932 3221225104 3221222840 4294960144 0 65536 3686404 1266761467 3222442959 0 0 17 0 0 0 # # fs/proc/base.c # 2004/02/18 19:43:02-08:00 akpm@osdl.org +13 -9 # /proc thread visibility fixes # # ChangeSet # 2004/02/18 20:54:59-08:00 akpm@osdl.org # [PATCH] Minor cross-compile issues # # From: Pratik Solanki # # - Fix include path for build.c so that it finds asm/boot.h. # /usr/include/asm/boot.h may not be present when cross-compiling on a # non-Linux machine. # # - $(CONFIG_SHELL) instead of sh. # # init/Makefile # 2004/02/18 19:43:02-08:00 akpm@osdl.org +1 -1 # Minor cross-compile issues # # arch/i386/boot/Makefile # 2004/02/18 19:43:02-08:00 akpm@osdl.org +2 -0 # Minor cross-compile issues # # ChangeSet # 2004/02/18 20:54:50-08:00 akpm@osdl.org # [PATCH] cpufreq_scale() fixes # # From: Dominik Brodowski # # Use do_div on 32-bit archs in cpufreq_scale, and native "/" on 64-bit # archs. # # include/linux/cpufreq.h # 2004/02/18 19:43:01-08:00 akpm@osdl.org +11 -11 # cpufreq_scale() fixes # # ChangeSet # 2004/02/18 20:54:41-08:00 akpm@osdl.org # [PATCH] defer panic for too many items in boot parameter line # # From: Werner Almesberger # # When passing too many unrecognized boot command line options (which become # arguments or environment variables), the 2.6 kernel panics (unlike 2.4, # which just ignores the extra items). Unfortunately, this happens before # the console is initialized, so all you get is a kernel that dies quickly, # for no apparent reason. # # This is particularly irritating if using UML with # init=something wi th a lot of ar gu men t s # # The patch below delays the panic until after console_init. # # (akpm: I mainly added this in because we have other places where the # panic-later-on machinery is needed). # # init/main.c # 2004/02/18 19:43:01-08:00 akpm@osdl.org +14 -4 # defer panic for too many items in boot parameter line # # ChangeSet # 2004/02/18 20:54:32-08:00 akpm@osdl.org # [PATCH] adfs: remove a kernel 2.2 #ifdef # # From: Adrian Bunk # # The patch below removes a kernel 2.2 #ifdef from fs/adfs/adfs.h . # # Note that this #ifdef was only present in the header, the implementation # of adfs_bmap was already removed. # # fs/adfs/adfs.h # 2004/02/18 19:43:00-08:00 akpm@osdl.org +0 -4 # adfs: remove a kernel 2.2 #ifdef # # ChangeSet # 2004/02/18 20:54:23-08:00 akpm@osdl.org # [PATCH] kbuild documentation fix # # From: Ryan Boder # # Explains how to compile external modules in # Documentation/kbuild/modules.txt. # # Documentation/kbuild/modules.txt # 2004/02/18 19:43:00-08:00 akpm@osdl.org +44 -4 # kbuild documentation fix # # ChangeSet # 2004/02/18 20:54:14-08:00 akpm@osdl.org # [PATCH] remove kernel 2.2 #ifdef's from {i,}stallion.h # # From: Adrian Bunk # # The patch below removeskernel 2.2 #ifdef's from {i,}stallion.h . # # include/linux/stallion.h # 2004/02/18 19:42:59-08:00 akpm@osdl.org +0 -5 # remove kernel 2.2 #ifdef's from {i,}stallion.h # # include/linux/istallion.h # 2004/02/18 19:42:59-08:00 akpm@osdl.org +0 -6 # remove kernel 2.2 #ifdef's from {i,}stallion.h # # ChangeSet # 2004/02/18 20:54:05-08:00 akpm@osdl.org # [PATCH] OSS: remove #ifdef's for kernel 2.0 # # From: Adrian Bunk # # The patch below removes two #ifdef's for kernel 2.0 from OSS. # # sound/oss/os.h # 2004/02/18 19:42:59-08:00 akpm@osdl.org +0 -4 # OSS: remove #ifdef's for kernel 2.0 # # sound/oss/msnd.c # 2004/02/18 19:42:59-08:00 akpm@osdl.org +4 -15 # OSS: remove #ifdef's for kernel 2.0 # # ChangeSet # 2004/02/18 20:53:55-08:00 akpm@osdl.org # [PATCH] Rename bitmap_snprintf() and cpumask_snprintf() to *_scnprintf() # # From: Joe Korty # # Rename bitmap_snprintf() to bitmap_scnprintf() and cpumask_snprintf() to # cpumask_scnprintf(), as these functions now belong to the scnprintf family # of functions. # # lib/bitmap.c # 2004/02/18 19:42:58-08:00 akpm@osdl.org +3 -3 # Rename bitmap_snprintf() and cpumask_snprintf() to *_scnprintf() # # include/linux/cpumask.h # 2004/02/18 19:42:58-08:00 akpm@osdl.org +2 -2 # Rename bitmap_snprintf() and cpumask_snprintf() to *_scnprintf() # # include/linux/bitmap.h # 2004/02/18 19:42:58-08:00 akpm@osdl.org +1 -1 # Rename bitmap_snprintf() and cpumask_snprintf() to *_scnprintf() # # drivers/pci/probe.c # 2004/02/18 19:42:58-08:00 akpm@osdl.org +1 -1 # Rename bitmap_snprintf() and cpumask_snprintf() to *_scnprintf() # # drivers/base/node.c # 2004/02/18 19:42:58-08:00 akpm@osdl.org +1 -1 # Rename bitmap_snprintf() and cpumask_snprintf() to *_scnprintf() # # arch/x86_64/kernel/irq.c # 2004/02/18 19:42:58-08:00 akpm@osdl.org +2 -2 # Rename bitmap_snprintf() and cpumask_snprintf() to *_scnprintf() # # arch/um/kernel/irq.c # 2004/02/18 19:42:58-08:00 akpm@osdl.org +2 -2 # Rename bitmap_snprintf() and cpumask_snprintf() to *_scnprintf() # # arch/sparc64/kernel/irq.c # 2004/02/18 19:42:58-08:00 akpm@osdl.org +1 -1 # Rename bitmap_snprintf() and cpumask_snprintf() to *_scnprintf() # # arch/ppc64/kernel/irq.c # 2004/02/18 19:42:58-08:00 akpm@osdl.org +2 -2 # Rename bitmap_snprintf() and cpumask_snprintf() to *_scnprintf() # # arch/ppc/kernel/irq.c # 2004/02/18 19:42:58-08:00 akpm@osdl.org +2 -2 # Rename bitmap_snprintf() and cpumask_snprintf() to *_scnprintf() # # arch/mips/kernel/irq.c # 2004/02/18 19:42:58-08:00 akpm@osdl.org +2 -2 # Rename bitmap_snprintf() and cpumask_snprintf() to *_scnprintf() # # arch/ia64/kernel/irq.c # 2004/02/18 19:42:58-08:00 akpm@osdl.org +2 -2 # Rename bitmap_snprintf() and cpumask_snprintf() to *_scnprintf() # # arch/i386/kernel/irq.c # 2004/02/18 19:42:58-08:00 akpm@osdl.org +2 -2 # Rename bitmap_snprintf() and cpumask_snprintf() to *_scnprintf() # # arch/alpha/kernel/irq.c # 2004/02/18 19:42:58-08:00 akpm@osdl.org +2 -2 # Rename bitmap_snprintf() and cpumask_snprintf() to *_scnprintf() # # ChangeSet # 2004/02/18 20:53:46-08:00 akpm@osdl.org # [PATCH] MCE fixes and cleanups # # Andi notes that the # # smp_call_function(foo); # foo(); # # in there is incorrect on preemptible kernels. # # Fix that by using on_each_cpu(), which takes care of such things. # # Also, remove the open-coded timer from here. We have # schedule_delayed_work(). # # And remove the `timerset' variable, which doesn't do anything. # # arch/i386/kernel/cpu/mcheck/non-fatal.c # 2004/02/18 19:42:57-08:00 akpm@osdl.org +11 -30 # MCE fixes and cleanups # # ChangeSet # 2004/02/18 20:53:37-08:00 akpm@osdl.org # [PATCH] Fix printk level on non fatal MCEs # # From: Andi Kleen # # For various reasons non fatal Machine Checks can happen on Athlons (e.g. # we have reports that laptops like to trigger them on suspend/resume) # # They are not necessarily fatal and often only minor hardware glitches. # # But what's annoying is that they're KERN_EMERG and pollute your console and # scare the user into writing confused kernel bug reports. # # This patch just replaces the KERN_EMERGs with KERN_INFO for now. Longer # term I think it would be better to log this stuff into a separate log. # # arch/i386/kernel/cpu/mcheck/non-fatal.c # 2004/02/18 19:42:57-08:00 akpm@osdl.org +4 -2 # Fix printk level on non fatal MCEs # # ChangeSet # 2004/02/18 20:53:28-08:00 akpm@osdl.org # [PATCH] 8259 timer ack fix # # From: "Maciej W. Rozycki" # # Fix up the 8259 ack handling for buggy SMM firmware. # # See http://www.ussg.iu.edu/hypermail/linux/kernel/0203.2/0956.html # # Apparently the embedded 8259A-compatible core is not fully functional. # This patch lets the I/O APIC-driven NMI watchdog to function correctly. # Credit to Ross Dickson for discovering this. # # arch/i386/kernel/io_apic.c # 2004/02/18 19:42:56-08:00 akpm@osdl.org +16 -4 # 8259 timer ack fix # # ChangeSet # 2004/02/18 20:53:19-08:00 akpm@osdl.org # [PATCH] dm: drop BIO_SEG_VALID bit # # From: Joe Thornber # # I just noticed that bio_clone copies the BIO_SEG_VALID bit from the original # bio when it was set. When we modify bi_idx or bi_vcnt afterwards the segment # counts are invalid and the bit must be dropped (though it is fairly unlikely # that it has already been set). [Christophe Saout] # # drivers/md/dm.c # 2004/02/18 19:42:56-08:00 akpm@osdl.org +1 -0 # dm: drop BIO_SEG_VALID bit # # ChangeSet # 2004/02/18 20:53:10-08:00 akpm@osdl.org # [PATCH] dm: Remove redundant spin lock in dec_pending() # # From: Joe Thornber # # Remove redundant spin lock in dec_pending() # # drivers/md/dm.c # 2004/02/18 19:42:55-08:00 akpm@osdl.org +1 -7 # dm: Remove redundant spin lock in dec_pending() # # ChangeSet # 2004/02/18 20:53:01-08:00 akpm@osdl.org # [PATCH] dm: Zero size target sanity check # # From: Joe Thornber # # Add sanity check to dm_table_add_target() against zero length targets. # [Christophe Saout] # # drivers/md/dm-table.c # 2004/02/18 19:42:55-08:00 akpm@osdl.org +5 -0 # dm: Zero size target sanity check # # ChangeSet # 2004/02/18 20:52:52-08:00 akpm@osdl.org # [PATCH] dm: Correct GFP flag in dm_table_create() # # From: Joe Thornber # # For some reason dm_table_create() was allocating GFP_NOIO rather than # GFP_KERNEL. # # drivers/md/dm-table.c # 2004/02/18 19:42:54-08:00 akpm@osdl.org +1 -1 # dm: Correct GFP flag in dm_table_create() # # ChangeSet # 2004/02/18 20:52:43-08:00 akpm@osdl.org # [PATCH] dm: Tidy up the error path for alloc_dev() # # From: Joe Thornber # # Tidy up the error path for alloc_dev() # # drivers/md/dm.c # 2004/02/18 19:42:54-08:00 akpm@osdl.org +18 -21 # dm: Tidy up the error path for alloc_dev() # # ChangeSet # 2004/02/18 20:52:34-08:00 akpm@osdl.org # [PATCH] dm: Maintain ordering when deferring bios # # From: Joe Thornber # # Make sure that we maintain ordering when deferring bios. # # drivers/md/dm-bio-list.h # 2004/02/18 19:42:53-08:00 akpm@osdl.org +68 -0 # dm: Maintain ordering when deferring bios # # drivers/md/dm.c # 2004/02/18 19:42:53-08:00 akpm@osdl.org +4 -5 # dm: Maintain ordering when deferring bios # # drivers/md/dm-bio-list.h # 2004/02/18 19:42:53-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/drivers/md/dm-bio-list.h # # ChangeSet # 2004/02/18 20:52:25-08:00 akpm@osdl.org # [PATCH] dm: Get rid of struct dm_deferred_io in dm.c # # From: Joe Thornber # # Remove struct dm_deferred_io from dm.c. [Christophe Saout] # # drivers/md/dm.c # 2004/02/18 19:42:53-08:00 akpm@osdl.org +9 -32 # dm: Get rid of struct dm_deferred_io in dm.c # # ChangeSet # 2004/02/18 20:52:16-08:00 akpm@osdl.org # [PATCH] dm: Move to_bytes() and to_sectors() into dm.h # # From: Joe Thornber # # Move to_bytes() and to_sectors() into dm.h # # drivers/md/dm.h # 2004/02/18 19:42:52-08:00 akpm@osdl.org +10 -0 # dm: Move to_bytes() and to_sectors() into dm.h # # drivers/md/dm.c # 2004/02/18 19:42:52-08:00 akpm@osdl.org +0 -9 # dm: Move to_bytes() and to_sectors() into dm.h # # ChangeSet # 2004/02/18 20:52:07-08:00 akpm@osdl.org # [PATCH] dm: Export dm_vcalloc() # # From: Joe Thornber # # Export dm_vcalloc() # # drivers/md/dm.h # 2004/02/18 19:42:52-08:00 akpm@osdl.org +2 -0 # dm: Export dm_vcalloc() # # drivers/md/dm-table.c # 2004/02/18 19:42:52-08:00 akpm@osdl.org +2 -1 # dm: Export dm_vcalloc() # # ChangeSet # 2004/02/18 20:51:58-08:00 akpm@osdl.org # [PATCH] md: Allow partitioning of MD devices. # # From: NeilBrown # # With this patch, md used two major numbers for arrays. # # One Major is number 9 with name 'md' have unpartitioned md arrays, one per # minor number. # # The other Major is allocated dynamically with name 'mdp' and had on array for # every 64 minors, allowing for upto 63 partitions. # # The arrays under one major are completely separate from the arrays under the # other. # # The preferred name for devices with the new major are of the form: # # /dev/md/d1p3 # partion 3 of device 1 - minor 67 # # When a paritioned md device is assembled, the partitions are not recognised # until after the whole-array device is opened again. A future version of # mdadm will perform this open so that the need will be transparent. # # include/linux/raid/md_k.h # 2004/02/18 19:42:51-08:00 akpm@osdl.org +3 -10 # md: Allow partitioning of MD devices. # # drivers/md/raid6main.c # 2004/02/18 19:42:51-08:00 akpm@osdl.org +1 -1 # md: Allow partitioning of MD devices. # # drivers/md/raid5.c # 2004/02/18 19:42:51-08:00 akpm@osdl.org +1 -1 # md: Allow partitioning of MD devices. # # drivers/md/md.c # 2004/02/18 19:42:51-08:00 akpm@osdl.org +75 -30 # md: Allow partitioning of MD devices. # # ChangeSet # 2004/02/18 20:51:49-08:00 akpm@osdl.org # [PATCH] md: Dynamically limit size of bio requests used for raid1 resync # # From: NeilBrown # # Currently raid1 uses PAGE_SIZE read/write requests for resync, as it doesn't # know how to honour per-device restrictions. This patch uses to bio_add_page # to honour those restrictions and ups the limit on request size to 64K. This # has a measurable impact on rebuild speed (25M/s -> 60M/s) # # drivers/md/raid1.c # 2004/02/18 19:42:51-08:00 akpm@osdl.org +96 -87 # md: Dynamically limit size of bio requests used for raid1 resync # # ChangeSet # 2004/02/18 20:51:40-08:00 akpm@osdl.org # [PATCH] md: Avoid unnecessary bio allocation during raid1 resync # # From: NeilBrown # # For each resync request, we allocate a "r1_bio" which has a bio "master_bio" # attached that goes largely unused. We also allocate a read_bio which is # used. This patch removes the read_bio and just uses the master_bio instead. # # This fixes a bug wherein bi_bdev of the master_bio wasn't being set, but was # being used. # # We also introduce a new "sectors" field into the r1_bio as we can no-longer # rely in master_bio->bi_sectors. # # include/linux/raid/raid1.h # 2004/02/18 19:42:50-08:00 akpm@osdl.org +1 -0 # md: Avoid unnecessary bio allocation during raid1 resync # # drivers/md/raid1.c # 2004/02/18 19:42:50-08:00 akpm@osdl.org +18 -19 # md: Avoid unnecessary bio allocation during raid1 resync # # ChangeSet # 2004/02/18 20:51:31-08:00 akpm@osdl.org # [PATCH] md: Remove some un-needed fields from r1bio_s # # From: NeilBrown # # next_r1 is never used, so it can just go. # # read_bio isn't needed as we can easily use one of the pointers in the # write_bios array - write_bios[->read_disk]. So rename "write_bios" to "bios" # and store the pointer to the read bio in there. # # include/linux/raid/raid1.h # 2004/02/18 19:42:50-08:00 akpm@osdl.org +2 -4 # md: Remove some un-needed fields from r1bio_s # # drivers/md/raid1.c # 2004/02/18 19:42:50-08:00 akpm@osdl.org +19 -36 # md: Remove some un-needed fields from r1bio_s # # ChangeSet # 2004/02/18 20:51:22-08:00 akpm@osdl.org # [PATCH] md: Discard the cmd field from r1_bio structure # # From: NeilBrown # # The only time it is really needed is to differentiate a retry-on-fail from a # write-after-read-for-resync request to raid1d. So we use a bit in 'state' # for that. # # include/linux/raid/raid1.h # 2004/02/18 19:42:49-08:00 akpm@osdl.org +2 -3 # md: Discard the cmd field from r1_bio structure # # drivers/md/raid1.c # 2004/02/18 19:42:49-08:00 akpm@osdl.org +19 -24 # md: Discard the cmd field from r1_bio structure # # ChangeSet # 2004/02/18 20:51:13-08:00 akpm@osdl.org # [PATCH] md: Split read and write end_request handlers # # From: NeilBrown # # Instead of having a single end_request handler that must determine whether it # was a read or a write request, we have two separate handlers, which makes # each of them easier to follow. # # drivers/md/raid1.c # 2004/02/18 19:42:49-08:00 akpm@osdl.org +65 -35 # md: Split read and write end_request handlers # # ChangeSet # 2004/02/18 20:51:04-08:00 akpm@osdl.org # [PATCH] md: Print "deprecated" warning when START_ARRAY is used. # # From: NeilBrown # # The "START_ARRAY" ioctl depends on major/minor numbers (as stored in the raid # superblock) are stable over reboots, which is increasingly untrue. # # There are better ways to start an array (e.g. with mdadm) so we mark the # ioctl as deprecated for 2.6, and will remove it in 2.7. # # drivers/md/md.c # 2004/02/18 19:42:48-08:00 akpm@osdl.org +8 -0 # md: Print "deprecated" warning when START_ARRAY is used. # # ChangeSet # 2004/02/18 20:50:55-08:00 akpm@osdl.org # [PATCH] kNFSd:fix build problems in nfs w/o proc_fs on 2.6.0-test5 # # From: NeilBrown # # From: Stephen Hemminger # Date: Fri, 12 Sep 2003 11:31:06 -0700 # # NFS won't build w/o CONFIG_PROC_FS. Looks like typo's (or a C++ # programmer) in stats.h # # include/linux/sunrpc/stats.h # 2004/02/18 19:42:48-08:00 akpm@osdl.org +4 -3 # kNFSd:fix build problems in nfs w/o proc_fs on 2.6.0-test5 # # ChangeSet # 2004/02/18 20:50:46-08:00 akpm@osdl.org # [PATCH] kNFSd: convert NFS /proc interfaces to seq_file # # From: NeilBrown # # From: shemminger@osdl.org Sat Sep 6 09:19:50 2003 # Date: Fri, 5 Sep 2003 16:19:30 -0700 # # Converts /proc/net/rpc/nfs and /proc/net/rpc/nfsd to use the simpler # seq_file interface. # # net/sunrpc/sunrpc_syms.c # 2004/02/18 19:42:47-08:00 akpm@osdl.org +1 -2 # kNFSd: convert NFS /proc interfaces to seq_file # # net/sunrpc/stats.c # 2004/02/18 19:42:47-08:00 akpm@osdl.org +49 -57 # kNFSd: convert NFS /proc interfaces to seq_file # # include/linux/sunrpc/stats.h # 2004/02/18 19:42:47-08:00 akpm@osdl.org +9 -10 # kNFSd: convert NFS /proc interfaces to seq_file # # fs/nfsd/stats.c # 2004/02/18 19:42:47-08:00 akpm@osdl.org +25 -42 # kNFSd: convert NFS /proc interfaces to seq_file # # ChangeSet # 2004/02/18 20:50:37-08:00 akpm@osdl.org # [PATCH] kNFSd: ip_map_init does a kmalloc which isn't checked... # # From: NeilBrown # # There is no way to return an error from a cache init routine, so instead we # make sure to pre-allocate the memory needed, and free it after the lookup # if the lookup failed. # # net/sunrpc/svcauth_unix.c # 2004/02/18 19:42:46-08:00 akpm@osdl.org +10 -3 # kNFSd: ip_map_init does a kmalloc which isn't checked... # # ChangeSet # 2004/02/18 20:50:28-08:00 akpm@osdl.org # [PATCH] kNFSd: Allow sunrpc/svc cache init function to modify the "key" # # From: NeilBrown # # When adding a item to a sunrpc/svc cache that contains kmalloced data it is # usefully to move the malloced data out of the key object into the new cache # object rather than copying (as then we would need to cope with kmalloc # failure and such). This means modifying the original. # # If the kmalloced data forms part of the key, then we must not move the data # out until after the key isn't needed any more. So this patch moves the # call to "INIT" on a new item (which fills in the key) to *after* the item # has been found (or not), and also makes sure we only call the HASH function # once. # # Thanks to "J. Bruce Fields" # # also # # 1/ remove unnecessary assignment # 2/ fix comments that lag behind implementation. # # net/sunrpc/svcauth.c # 2004/02/18 19:42:46-08:00 akpm@osdl.org +7 -1 # kNFSd: Allow sunrpc/svc cache init function to modify the "key" # # include/linux/sunrpc/cache.h # 2004/02/18 19:42:46-08:00 akpm@osdl.org +8 -5 # kNFSd: Allow sunrpc/svc cache init function to modify the "key" # # ChangeSet # 2004/02/18 20:50:19-08:00 akpm@osdl.org # [PATCH] kNFSd: Fix possible scheduling_while_atomic in cache.c # # From: NeilBrown # # We currently call cache_put, which can schedule(), under a spin_lock. This # patch moves that call outside the spinlock. # # net/sunrpc/cache.c # 2004/02/18 19:42:45-08:00 akpm@osdl.org +8 -5 # kNFSd: Fix possible scheduling_while_atomic in cache.c # # ChangeSet # 2004/02/18 20:50:10-08:00 akpm@osdl.org # [PATCH] #if versus #ifdef cleanup # # From: Valdis.Kletnieks@vt.edu # # 15 changes of #if to #ifdef and 2 places CONFIG_FOO should be # defined(CONFIG_FOO). This gets rid of spurious warnings if you build with # "-Wundef" so you get a warning if you have a preprocessor command like: # # #if CONFIG_ETRAX_DS1302_RSTBIT == 27 # # and you'll be told if it's substituting a zero rather than silent # weirdness and unexpected code generation. # # net/ipv6/af_inet6.c # 2004/02/18 19:42:45-08:00 akpm@osdl.org +1 -1 # #if versus #ifdef cleanup # # lib/crc32.c # 2004/02/18 19:42:45-08:00 akpm@osdl.org +1 -1 # #if versus #ifdef cleanup # # include/asm-sh/kmap_types.h # 2004/02/18 19:42:45-08:00 akpm@osdl.org +1 -1 # #if versus #ifdef cleanup # # include/asm-sh/hardirq.h # 2004/02/18 19:42:45-08:00 akpm@osdl.org +1 -1 # #if versus #ifdef cleanup # # include/asm-mips/topology.h # 2004/02/18 19:42:45-08:00 akpm@osdl.org +1 -1 # #if versus #ifdef cleanup # # include/asm-mips/pgtable-32.h # 2004/02/18 19:42:45-08:00 akpm@osdl.org +1 -1 # #if versus #ifdef cleanup # # include/asm-mips/hardirq.h # 2004/02/18 19:42:45-08:00 akpm@osdl.org +1 -1 # #if versus #ifdef cleanup # # include/asm-i386/module.h # 2004/02/18 19:42:45-08:00 akpm@osdl.org +1 -1 # #if versus #ifdef cleanup # # drivers/net/tulip/de4x5.c # 2004/02/18 19:42:45-08:00 akpm@osdl.org +2 -2 # #if versus #ifdef cleanup # # drivers/net/depca.c # 2004/02/18 19:42:45-08:00 akpm@osdl.org +2 -2 # #if versus #ifdef cleanup # # drivers/mtd/maps/solutionengine.c # 2004/02/18 19:42:45-08:00 akpm@osdl.org +1 -1 # #if versus #ifdef cleanup # # drivers/char/mem.c # 2004/02/18 19:42:45-08:00 akpm@osdl.org +0 -2 # #if versus #ifdef cleanup # # arch/ia64/sn/kernel/irq.c # 2004/02/18 19:42:45-08:00 akpm@osdl.org +1 -1 # #if versus #ifdef cleanup # # ChangeSet # 2004/02/18 20:50:01-08:00 akpm@osdl.org # [PATCH] MIPS: New 2.6 serial drivers # # From: Ralf Baechle # # Three new MIPS-specific serial drivers. ip22.c is derived from the sparc # zilog driver; guess we should write a generic Zilog driver somewhen ... # # drivers/serial/ip22zilog.h # 2004/02/18 19:42:44-08:00 akpm@osdl.org +281 -0 # MIPS: New 2.6 serial drivers # # drivers/serial/ip22zilog.c # 2004/02/18 19:42:44-08:00 akpm@osdl.org +1307 -0 # MIPS: New 2.6 serial drivers # # drivers/serial/dz.h # 2004/02/18 19:42:44-08:00 akpm@osdl.org +118 -0 # MIPS: New 2.6 serial drivers # # drivers/serial/dz.c # 2004/02/18 19:42:44-08:00 akpm@osdl.org +827 -0 # MIPS: New 2.6 serial drivers # # drivers/serial/au1x00_uart.c # 2004/02/18 19:42:44-08:00 akpm@osdl.org +1393 -0 # MIPS: New 2.6 serial drivers # # drivers/serial/ip22zilog.h # 2004/02/18 19:42:44-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/drivers/serial/ip22zilog.h # # drivers/serial/ip22zilog.c # 2004/02/18 19:42:44-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/drivers/serial/ip22zilog.c # # drivers/serial/dz.h # 2004/02/18 19:42:44-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/drivers/serial/dz.h # # drivers/serial/dz.c # 2004/02/18 19:42:44-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/drivers/serial/dz.c # # drivers/serial/au1x00_uart.c # 2004/02/18 19:42:44-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/drivers/serial/au1x00_uart.c # # drivers/serial/Makefile # 2004/02/18 19:42:44-08:00 akpm@osdl.org +3 -0 # MIPS: New 2.6 serial drivers # # drivers/serial/Kconfig # 2004/02/18 19:42:44-08:00 akpm@osdl.org +51 -0 # MIPS: New 2.6 serial drivers # # ChangeSet # 2004/02/18 20:49:52-08:00 akpm@osdl.org # [PATCH] Enable coredumps > 2GB # # From: Andi Kleen # # Some x86-64 users were complaining that coredumps >2GB don't work. # # This will enable large coredump for everybody. Apparently the 32bit # gdb/binutils cannot handle them, but I hear the binutils people are working # on fixing that. I doubt it will harm people - unreadable coredumps are not # worse than no coredump and it won't make any difference in space usage if # you get a 1.99GB or a 2.5GB coredump. So just enable it unconditionally. # If it should be really a problem for 32bit the rlimit defaults in # resource.h could be changed. # # For file systems that don't support O_LARGEFILE you should just get an # truncated coredumps for big address spaces. # # fs/exec.c # 2004/02/18 19:42:43-08:00 akpm@osdl.org +1 -1 # Enable coredumps > 2GB # # ChangeSet # 2004/02/18 20:49:43-08:00 akpm@osdl.org # [PATCH] devfs: race fixes and cleanup # # From: Andrey Borzenkov # # - use struct nameidata in devfs_d_revalidate_wait to detect when it is # called without i_sem hold; take i_sem on parent in this case. This # prevents both deadlock with devfs_lookup by allowing it to drop i_sem # consistently and oops in d_instantiate by ensuring that it always runs # protected # # - remove dead code that deals with major number allocation. The only # remaining user was devfs itself and patch changes it to # # - use register_chardev to get device number for internal /dev/.devfsd and # /dev/.statd. # # - remove dead auto allocation flag as well # # - remove code that does module get on dev open - it is handled by fops_get. # Use init_special_inode consistently # # - get rid of struct cdev_type and bdev_type - both have just single dev_t # now # # fs/devfs/util.c # 2004/02/18 19:42:43-08:00 akpm@osdl.org +0 -159 # devfs: race fixes and cleanup # # fs/devfs/base.c # 2004/02/18 19:42:43-08:00 akpm@osdl.org +198 -206 # devfs: race fixes and cleanup # # BitKeeper/deleted/.del-internal.h~68afd32bc49d8c13 # 2004/02/18 20:49:38-08:00 akpm@osdl.org +0 -0 # Delete: fs/devfs/internal.h # # ChangeSet # 2004/02/18 20:49:34-08:00 akpm@osdl.org # [PATCH] snprintf fixes # # From: Juergen Quade # # Lots of places in the kernel are using [v]snprintf wrongly: they assume it # returns the number of characters copied. It doesn't. It returns the # number of characters which _would_ have been copied had the buffer not been # filled up. # # So create new functions vscnprintf() and scnprintf() which have the # expected (sane) semaptics, and migrate callers over to using them. # # sound/core/info.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +1 -1 # snprintf fixes # # security/selinux/selinuxfs.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +3 -3 # snprintf fixes # # net/atm/clip.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +1 -1 # snprintf fixes # # lib/vsprintf.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +74 -13 # snprintf fixes # # lib/bitmap.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +1 -1 # snprintf fixes # # kernel/printk.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +1 -1 # snprintf fixes # # include/linux/kernel.h # 2004/02/18 19:42:41-08:00 akpm@osdl.org +3 -0 # snprintf fixes # # drivers/usb/misc/speedtch.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +1 -1 # snprintf fixes # # drivers/usb/host/ohci-dbg.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +13 -13 # snprintf fixes # # drivers/usb/host/ehci-dbg.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +26 -26 # snprintf fixes # # drivers/usb/gadget/pxa2xx_udc.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +12 -12 # snprintf fixes # # drivers/usb/gadget/net2280.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +16 -16 # snprintf fixes # # drivers/usb/gadget/goku_udc.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +8 -8 # snprintf fixes # # drivers/scsi/scsi_debug.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +9 -10 # snprintf fixes # # drivers/s390/cio/device.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +4 -4 # snprintf fixes # # drivers/s390/char/tape_core.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +7 -7 # snprintf fixes # # drivers/pci/hotplug.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +4 -4 # snprintf fixes # # drivers/parisc/dino.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +1 -1 # snprintf fixes # # drivers/net/wan/comx-hw-munich.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +53 -53 # snprintf fixes # # drivers/media/video/videocodec.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +4 -4 # snprintf fixes # # drivers/md/dm-stripe.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +2 -2 # snprintf fixes # # drivers/cpufreq/proc_intf.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +1 -1 # snprintf fixes # # drivers/cpufreq/cpufreq.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +3 -3 # snprintf fixes # # drivers/char/viocons.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +1 -1 # snprintf fixes # # drivers/char/sn_serial.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +1 -1 # snprintf fixes # # drivers/base/dmapool.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +2 -2 # snprintf fixes # # arch/x86_64/kernel/early_printk.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +1 -1 # snprintf fixes # # arch/sparc64/prom/printf.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +1 -1 # snprintf fixes # # arch/sparc/prom/printf.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +1 -1 # snprintf fixes # # arch/ppc64/kernel/rtas-proc.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +8 -7 # snprintf fixes # # arch/ppc64/kernel/lparcfg.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +34 -34 # snprintf fixes # # arch/i386/kernel/edd.c # 2004/02/18 19:42:41-08:00 akpm@osdl.org +36 -36 # snprintf fixes # # ChangeSet # 2004/02/18 20:49:23-08:00 akpm@osdl.org # [PATCH] bd_set_size i_size handling # # We need to hold i_sem while running i_size_write(). But that seems like a # lot of fuss and deadlock potential. So just write the dang thing. # # fs/block_dev.c # 2004/02/18 19:42:40-08:00 akpm@osdl.org +2 -1 # bd_set_size i_size handling # # ChangeSet # 2004/02/18 20:49:14-08:00 akpm@osdl.org # [PATCH] Mark intermezzo as broken # # The NGROUPS changes broke it, and we're not sure how to fixit, and nobody # appears to be working on or testing intermezzo. # # fs/Kconfig # 2004/02/18 19:42:40-08:00 akpm@osdl.org +4 -1 # Mark intermezzo as broken # # ChangeSet # 2004/02/18 20:49:05-08:00 akpm@osdl.org # [PATCH] NGROUPS 2.6.2rc2 + fixups # # From: Tim Hockin , # Neil Brown , # me # # New groups infrastructure. task->groups and task->ngroups are replaced by # task->group_info. Group)info is a refcounted, dynamic struct with an array # of pages. This allows for large numbers of groups. The current limit of # 32 groups has been raised to 64k groups. It can be raised more by changing # the NGROUPS_MAX constant in limits.h # # security/selinux/hooks.c # 2004/02/18 19:42:38-08:00 akpm@osdl.org +1 -1 # NGROUPS 2.6.2rc2 + fixups # # security/dummy.c # 2004/02/18 19:42:38-08:00 akpm@osdl.org +1 -1 # NGROUPS 2.6.2rc2 + fixups # # net/sunrpc/svcauth_unix.c # 2004/02/18 19:42:38-08:00 akpm@osdl.org +2 -2 # NGROUPS 2.6.2rc2 + fixups # # net/sunrpc/auth_unix.c # 2004/02/18 19:42:38-08:00 akpm@osdl.org +4 -4 # NGROUPS 2.6.2rc2 + fixups # # net/sunrpc/auth.c # 2004/02/18 19:42:38-08:00 akpm@osdl.org +21 -14 # NGROUPS 2.6.2rc2 + fixups # # kernel/uid16.c # 2004/02/18 19:42:38-08:00 akpm@osdl.org +61 -23 # NGROUPS 2.6.2rc2 + fixups # # kernel/sys.c # 2004/02/18 19:42:38-08:00 akpm@osdl.org +207 -35 # NGROUPS 2.6.2rc2 + fixups # # kernel/fork.c # 2004/02/18 19:42:38-08:00 akpm@osdl.org +3 -0 # NGROUPS 2.6.2rc2 + fixups # # include/linux/sunrpc/svcauth.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +2 -1 # NGROUPS 2.6.2rc2 + fixups # # include/linux/sunrpc/auth.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +1 -2 # NGROUPS 2.6.2rc2 + fixups # # include/linux/security.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +6 -7 # NGROUPS 2.6.2rc2 + fixups # # include/linux/sched.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +28 -2 # NGROUPS 2.6.2rc2 + fixups # # include/linux/nfsd/auth.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +1 -1 # NGROUPS 2.6.2rc2 + fixups # # include/linux/limits.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +1 -1 # NGROUPS 2.6.2rc2 + fixups # # include/linux/init_task.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +3 -0 # NGROUPS 2.6.2rc2 + fixups # # include/asm-x86_64/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-v850/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-um/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-sparc64/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-sparc/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-sh/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-s390/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-ppc64/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-ppc/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-parisc/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-mips/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-m68knommu/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-m68k/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-ia64/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-i386/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-h8300/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-cris/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-arm26/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-arm/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # include/asm-alpha/param.h # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -4 # NGROUPS 2.6.2rc2 + fixups # # fs/proc/array.c # 2004/02/18 19:42:38-08:00 akpm@osdl.org +4 -2 # NGROUPS 2.6.2rc2 + fixups # # fs/nfsd/nfs4state.c # 2004/02/18 19:42:38-08:00 akpm@osdl.org +1 -1 # NGROUPS 2.6.2rc2 + fixups # # fs/nfsd/auth.c # 2004/02/18 19:42:38-08:00 akpm@osdl.org +32 -12 # NGROUPS 2.6.2rc2 + fixups # # arch/sparc64/kernel/sys_sparc32.c # 2004/02/18 19:42:38-08:00 akpm@osdl.org +59 -18 # NGROUPS 2.6.2rc2 + fixups # # arch/s390/kernel/compat_linux.c # 2004/02/18 19:42:38-08:00 akpm@osdl.org +59 -18 # NGROUPS 2.6.2rc2 + fixups # # arch/mips/kernel/sysirix.c # 2004/02/18 19:42:38-08:00 akpm@osdl.org +1 -1 # NGROUPS 2.6.2rc2 + fixups # # arch/ia64/ia32/sys_ia32.c # 2004/02/18 19:42:38-08:00 akpm@osdl.org +68 -27 # NGROUPS 2.6.2rc2 + fixups # # ChangeSet # 2004/02/18 20:48:54-08:00 akpm@osdl.org # [PATCH] bonding alias revert and documentation fix # # From: Rusty Russell # # Jeff Garzik disliked the bonding driver knowing it was called "bond0". # Remove that alias, and revert documentation. # # drivers/net/bonding/bond_main.c # 2004/02/18 19:42:38-08:00 akpm@osdl.org +0 -1 # bonding alias revert and documentation fix # # Documentation/networking/bonding.txt # 2004/02/18 19:42:38-08:00 akpm@osdl.org +7 -2 # bonding alias revert and documentation fix # # ChangeSet # 2004/02/18 20:48:45-08:00 akpm@osdl.org # [PATCH] add some more MODULE_ALIASes # # From: Rusty Russell # # New MODULE_ALIASes in: # 1) arch/i386/kernel/microcode.c # 2) drivers/char/genrtc.c # 3) drivers/ide/ide-tape.c # 4) drivers/net/bonding/bond_main.c # 5) drivers/net/bsd_comp.c # 6) drivers/net/ppp_deflate.c # 7) drivers/net/ppp_generic.c # # drivers/net/ppp_generic.c # 2004/02/18 19:42:37-08:00 akpm@osdl.org +1 -0 # add some more MODULE_ALIASes # # drivers/net/ppp_deflate.c # 2004/02/18 19:42:37-08:00 akpm@osdl.org +2 -0 # add some more MODULE_ALIASes # # drivers/net/bsd_comp.c # 2004/02/18 19:42:37-08:00 akpm@osdl.org +1 -0 # add some more MODULE_ALIASes # # drivers/net/bonding/bond_main.c # 2004/02/18 19:42:37-08:00 akpm@osdl.org +1 -0 # add some more MODULE_ALIASes # # drivers/ide/ide-tape.c # 2004/02/18 19:42:37-08:00 akpm@osdl.org +1 -0 # add some more MODULE_ALIASes # # drivers/char/genrtc.c # 2004/02/18 19:42:37-08:00 akpm@osdl.org +1 -1 # add some more MODULE_ALIASes # # arch/i386/kernel/microcode.c # 2004/02/18 19:42:37-08:00 akpm@osdl.org +1 -0 # add some more MODULE_ALIASes # # ChangeSet # 2004/02/18 20:48:35-08:00 akpm@osdl.org # [PATCH] Documentation: remove /etc/modules.conf refs # # From: Rusty Russell # # Someone complained about the number of references to /etc/modules.conf in # the documentation. While fixing them up (and examples where changed), # removed those which are redundant due to MODULE_ALIAS. # # sound/core/seq/seq_dummy.c # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # net/Kconfig # 2004/02/18 19:42:35-08:00 akpm@osdl.org +4 -10 # Documentation: remove /etc/modules.conf refs # # drivers/scsi/scsi.c # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # drivers/scsi/qla2xxx/qla_os.c # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # drivers/scsi/aic7xxx/aic7xxx_osm.c # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # drivers/scsi/aic7xxx/aic79xx_osm.c # 2004/02/18 19:42:35-08:00 akpm@osdl.org +2 -2 # Documentation: remove /etc/modules.conf refs # # drivers/net/wan/Kconfig # 2004/02/18 19:42:35-08:00 akpm@osdl.org +2 -1 # Documentation: remove /etc/modules.conf refs # # drivers/media/dvb/Kconfig # 2004/02/18 19:42:35-08:00 akpm@osdl.org +3 -2 # Documentation: remove /etc/modules.conf refs # # drivers/char/isicom.c # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # drivers/char/ip2/ip2.h # 2004/02/18 19:42:35-08:00 akpm@osdl.org +2 -2 # Documentation: remove /etc/modules.conf refs # # drivers/char/Kconfig # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -2 # Documentation: remove /etc/modules.conf refs # # Documentation/video4linux/meye.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +2 -2 # Documentation: remove /etc/modules.conf refs # # Documentation/video4linux/bttv/README # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # Documentation/video4linux/bttv/Modules.conf # 2004/02/18 19:42:35-08:00 akpm@osdl.org +3 -0 # Documentation: remove /etc/modules.conf refs # # Documentation/video4linux/bttv/Modprobe.conf # 2004/02/18 19:42:35-08:00 akpm@osdl.org +11 -0 # Documentation: remove /etc/modules.conf refs # # Documentation/video4linux/Zoran # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # Documentation/video4linux/CQcam.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +4 -4 # Documentation: remove /etc/modules.conf refs # # Documentation/usb/scanner.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +2 -2 # Documentation: remove /etc/modules.conf refs # # Documentation/sound/oss/Wavefront # 2004/02/18 19:42:35-08:00 akpm@osdl.org +3 -4 # Documentation: remove /etc/modules.conf refs # # Documentation/sound/oss/README.modules # 2004/02/18 19:42:35-08:00 akpm@osdl.org +8 -8 # Documentation: remove /etc/modules.conf refs # # Documentation/sound/oss/PAS16 # 2004/02/18 19:42:35-08:00 akpm@osdl.org +2 -2 # Documentation: remove /etc/modules.conf refs # # Documentation/sound/oss/Opti # 2004/02/18 19:42:35-08:00 akpm@osdl.org +4 -4 # Documentation: remove /etc/modules.conf refs # # Documentation/sound/oss/OPL3-SA2 # 2004/02/18 19:42:35-08:00 akpm@osdl.org +2 -2 # Documentation: remove /etc/modules.conf refs # # Documentation/sound/oss/Maestro3 # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # Documentation/sound/oss/MAD16 # 2004/02/18 19:42:35-08:00 akpm@osdl.org +4 -3 # Documentation: remove /etc/modules.conf refs # # Documentation/sound/oss/Introduction # 2004/02/18 19:42:35-08:00 akpm@osdl.org +4 -4 # Documentation: remove /etc/modules.conf refs # # Documentation/sound/oss/CMI8330 # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # Documentation/sound/oss/AudioExcelDSP16 # 2004/02/18 19:42:35-08:00 akpm@osdl.org +4 -4 # Documentation: remove /etc/modules.conf refs # # Documentation/sound/oss/AWE32 # 2004/02/18 19:42:35-08:00 akpm@osdl.org +2 -2 # Documentation: remove /etc/modules.conf refs # # Documentation/sonypi.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +2 -2 # Documentation: remove /etc/modules.conf refs # # Documentation/scsi/osst.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # Documentation/scsi/aic7xxx.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # Documentation/scsi/aic79xx.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # Documentation/s390/3270.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +4 -4 # Documentation: remove /etc/modules.conf refs # # Documentation/rocket.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # Documentation/parport.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # Documentation/networking/vortex.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +5 -5 # Documentation: remove /etc/modules.conf refs # # Documentation/networking/tuntap.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +3 -6 # Documentation: remove /etc/modules.conf refs # # Documentation/networking/sk98lin.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # Documentation/networking/ltpc.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # Documentation/networking/dl2k.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +5 -5 # Documentation: remove /etc/modules.conf refs # # Documentation/networking/bonding.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +7 -15 # Documentation: remove /etc/modules.conf refs # # Documentation/networking/baycom.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +2 -2 # Documentation: remove /etc/modules.conf refs # # Documentation/ide.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +2 -3 # Documentation: remove /etc/modules.conf refs # # Documentation/hayes-esp.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # arch/m68k/Kconfig # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -2 # Documentation: remove /etc/modules.conf refs # # arch/i386/Kconfig # 2004/02/18 19:42:35-08:00 akpm@osdl.org +0 -2 # Documentation: remove /etc/modules.conf refs # # Documentation/video4linux/bttv/Modprobe.conf # 2004/02/18 19:42:35-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/Documentation/video4linux/bttv/Modprobe.conf # # Documentation/ftape.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +4 -4 # Documentation: remove /etc/modules.conf refs # # Documentation/fb/intel810.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # Documentation/digiboard.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +4 -4 # Documentation: remove /etc/modules.conf refs # # Documentation/crypto/api-intro.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +1 -1 # Documentation: remove /etc/modules.conf refs # # Documentation/computone.txt # 2004/02/18 19:42:35-08:00 akpm@osdl.org +6 -6 # Documentation: remove /etc/modules.conf refs # # Documentation/Changes # 2004/02/18 19:42:35-08:00 akpm@osdl.org +0 -18 # Documentation: remove /etc/modules.conf refs # # ChangeSet # 2004/02/18 20:48:24-08:00 akpm@osdl.org # [PATCH] AMD Elan is a different subarch # # From: Adrian Bunk # # - AMD Elan is a different subarch, you can't configure a kernel that runs # on both the AMD Elan and other i386 CPUs # # - added optimizing CFLAGS for the AMD Elan # # include/asm-i386/timex.h # 2004/02/18 19:42:34-08:00 akpm@osdl.org +1 -1 # AMD Elan is a different subarch # # arch/i386/kernel/cpu/cpufreq/Kconfig # 2004/02/18 19:42:34-08:00 akpm@osdl.org +1 -1 # AMD Elan is a different subarch # # arch/i386/boot/setup.S # 2004/02/18 19:42:34-08:00 akpm@osdl.org +1 -1 # AMD Elan is a different subarch # # arch/i386/Makefile # 2004/02/18 19:42:34-08:00 akpm@osdl.org +3 -0 # AMD Elan is a different subarch # # arch/i386/Kconfig # 2004/02/18 19:42:34-08:00 akpm@osdl.org +15 -2 # AMD Elan is a different subarch # # ChangeSet # 2004/02/18 20:48:15-08:00 akpm@osdl.org # [PATCH] gcc 2.95 supports -march=k6 (no need for check_gcc) # # From: Adrian Bunk # # gcc 2.95 supports -march=k6 (no need for check_gcc) # # arch/i386/Makefile # 2004/02/18 19:42:33-08:00 akpm@osdl.org +1 -1 # gcc 2.95 supports -march=k6 (no need for check_gcc) # # ChangeSet # 2004/02/18 20:48:05-08:00 akpm@osdl.org # [PATCH] add Pentium M and Pentium-4 M options # # From: Adrian Bunk # # add Pentium M and Pentium-4 M options: # # - add MPENTIUMM (equivalent to PENTIUMIII except for a bigger # X86_L1_CACHE_SHIFT) # # - document that MPENTIUM4 is the right choice for a Pentium-4 M # # include/asm-i386/module.h # 2004/02/18 19:42:33-08:00 akpm@osdl.org +2 -0 # add Pentium M and Pentium-4 M options # # arch/i386/Makefile # 2004/02/18 19:42:33-08:00 akpm@osdl.org +1 -0 # add Pentium M and Pentium-4 M options # # arch/i386/Kconfig # 2004/02/18 19:42:33-08:00 akpm@osdl.org +17 -11 # add Pentium M and Pentium-4 M options # # ChangeSet # 2004/02/18 20:47:56-08:00 akpm@osdl.org # [PATCH] Limit hashtable sizes # # From: "Chen, Kenneth W" # # The issue of exceedingly large hash tables has been discussed on the # mailing list a while back, but seems to slip through the cracks. # # What we found is it's not a problem for x86 (and most other # architectures) because __get_free_pages won't be able to get anything # beyond order MAX_ORDER-1 (10) which means at most those hash tables are # 4MB each (assume 4K page size). However, on ia64, in order to support # larger hugeTLB page size, the MAX_ORDER is bumped up to 18, which now # means a 2GB upper limits enforced by the page allocator (assume 16K page # size). PPC64 is another example that bumps up MAX_ORDER. # # Last time I checked, the tcp ehash table is taking a whooping (insane!) # 2GB on one of our large machine. dentry and inode hash tables also take # considerable amount of memory. # # Setting the size of these tables is difficult: they need to be constrained on # many-zone ia64 machines, but this could cause significant performance # problems when there are (for example) 100 million dentries in cache. # Large-memory machines which do not slice that memory up into huge numbers of # zones do not need to run the risk of this slowdown. # # So the sizing algorithms remain essentially unchanged, and boot-time options # are provided which permit the tables to be scaled down. # # net/ipv4/tcp.c # 2004/02/18 19:42:32-08:00 akpm@osdl.org +14 -0 # Limit hashtable sizes # # net/ipv4/route.c # 2004/02/18 19:42:32-08:00 akpm@osdl.org +14 -1 # Limit hashtable sizes # # fs/inode.c # 2004/02/18 19:42:32-08:00 akpm@osdl.org +17 -3 # Limit hashtable sizes # # fs/dcache.c # 2004/02/18 19:42:32-08:00 akpm@osdl.org +17 -5 # Limit hashtable sizes # # Documentation/kernel-parameters.txt # 2004/02/18 19:42:32-08:00 akpm@osdl.org +12 -0 # Limit hashtable sizes # # ChangeSet # 2004/02/18 20:47:47-08:00 akpm@osdl.org # [PATCH] Use CPU_UP_PREPARE properly # # From: Rusty Russell # # The cpu hotplug code actually provides two notifiers: CPU_UP_PREPARE # which preceeds the online and can fail, and CPU_ONLINE which can't. # # Current usage is only done at boot, so this distinction doesn't # matter, but it's a bad example to set. This also means that the # migration threads do not have to be higher priority than the # others, since they are ready to go before any CPU_ONLINE callbacks # are done. # # This patch is experimental but fairly straight foward: I haven't been # able to test it since extracting it from the hotplug cpu code, so it's # possible I screwed something up. # # kernel/softirq.c # 2004/02/18 19:42:32-08:00 akpm@osdl.org +12 -3 # Use CPU_UP_PREPARE properly # # kernel/sched.c # 2004/02/18 19:42:32-08:00 akpm@osdl.org +16 -10 # Use CPU_UP_PREPARE properly # # ChangeSet # 2004/02/18 20:47:38-08:00 akpm@osdl.org # [PATCH] Remove More Unneccessary CPU Notifiers # # From: Rusty Russell # # Three more removed CPU notifiers extracted from the hotplug CPU patch. # # kernel/softirq.c: the tasklet cpu prepration callback is useless: # the vectors are already initialized to NULL. Even with the hotplug # CPU patches, they're of little or no use. # # fs/buffer.c: once again, they are already initialized to zero. # # mm/page_alloc.c: once again, already initialized to zero. # # mm/page_alloc.c # 2004/02/18 19:42:31-08:00 akpm@osdl.org +0 -25 # Remove More Unneccessary CPU Notifiers # # kernel/softirq.c # 2004/02/18 19:42:31-08:00 akpm@osdl.org +0 -28 # Remove More Unneccessary CPU Notifiers # # fs/buffer.c # 2004/02/18 19:42:31-08:00 akpm@osdl.org +0 -30 # Remove More Unneccessary CPU Notifiers # # ChangeSet # 2004/02/18 20:47:29-08:00 akpm@osdl.org # [PATCH] Minor workqueue.c cleanup # # From: Rusty Russell # # Move duplicated code to __queue_work(), and don't set the CPU for # queue_delayed_work() until the timer goes off. The second one only has an # effect on CONFIG_HOTPLUG_CPU where the CPU goes down and the timer goes off # on a different CPU than it was scheduled on. # # kernel/workqueue.c # 2004/02/18 19:42:30-08:00 akpm@osdl.org +20 -24 # Minor workqueue.c cleanup # # ChangeSet # 2004/02/18 20:47:20-08:00 akpm@osdl.org # [PATCH] Remove kstat cpu notifiers # # From: Rusty Russell # # Some well-meaning person put a notifier in for CPUs to update the kstat # structures in sched.c. However, it does nothing, and even with the full # hotplug CPU patch, it still does nothing. # # Simple counters very rarely need anything done when CPUs come up or go # down. If you have per-cpu caches, or per-cpu threads, you need to do # something. But very rarely for stats. # # kernel/sched.c # 2004/02/18 19:42:30-08:00 akpm@osdl.org +0 -34 # Remove kstat cpu notifiers # # ChangeSet # 2004/02/18 20:47:11-08:00 akpm@osdl.org # [PATCH] kthread primitive # # From: Rusty Russell # # These two patches provide the framework for stopping kernel threads to # allow hotplug CPU. This one just adds kthread.c and kthread.h, next # one uses it. # # Most importantly, adds a Monty Python quote to the kernel. # # Details: # # The hotplug CPU code introduces two major problems: # # 1) Threads which previously never stopped (migration thread, # ksoftirqd, keventd) have to be stopped cleanly as CPUs go offline. # 2) Threads which previously never had to be created now have # to be created when a CPU goes online. # # Unfortunately, stopping a thread is fairly baroque, involving memory # barriers, a completion and spinning until the task is actually dead # (for example, complete_and_exit() must be used if inside a module). # # There are also three problems in starting a thread: # 1) Doing it from a random process context risks environment contamination: # better to do it from keventd to guarantee a clean environment, a-la # call_usermodehelper. # 2) Getting the task struct without races is a hard: see kernel/sched.c # migration_call(), kernel/workqueue.c create_workqueue_thread(). # 3) There are races in starting a thread for a CPU which is not yet # online: migration thread does a complex dance at the moment for # a similar reason (there may be no migration thread to migrate us). # # Place all this logic in some primitives to make life easier: # kthread_create() and kthread_stop(). These primitives require no # extra data-structures in the caller: they operate on normal "struct # task_struct"s. # # Other changes: # # - Expose keventd_up(), as keventd and migration threads will use kthread to # launch, and kthread normally uses workqueues and must recognize this case. # # - Kthreads created at boot before "keventd" are spawned directly. However, # this means that they don't have all signals blocked, and hence can be # killed. The simplest solution is to always explicitly block all signals in # the kthread. # # - Change over the migration threads, the workqueue threads and the # ksoftirqd threads to use kthread. # # - module.c currently spawns threads directly to stop the machine, so a # module can be atomically tested for removal. # # - Unfortunately, this means that the current task is manipulated (which # races with set_cpus_allowed, for example), and it can't set its priority # artificially high. Using a kernel thread can solve this cleanly, and with # kthread_run, it's simple. # # - kthreads use keventd, so they inherit its cpus_allowed mask. Unset it. # All current users set it explicity anyway, but it's nice to fix. # # - call_usermode_helper uses keventd, so the process created inherits its # cpus_allowed mask. Unset it. # # - Prevent errors in boot when cpus_possible() contains a cpu which is not # online (ie. a cpu didn't come up). This doesn't happen on x86, since a # boot failure makes that CPU no longer possible (hacky, but it works). # # - When the cpu fails to come up, some callbacks do kthread_stop(), which # doesn't work without keventd (which hasn't started yet). Call it directly, # and take care that it restores signal state (note: do_sigaction does a # flush on blocked signals, so we don't need to repeat it). # # kernel/kthread.c # 2004/02/18 19:42:29-08:00 akpm@osdl.org +163 -0 # kthread primitive # # include/linux/kthread.h # 2004/02/18 19:42:29-08:00 akpm@osdl.org +81 -0 # kthread primitive # # kernel/workqueue.c # 2004/02/18 19:42:29-08:00 akpm@osdl.org +26 -39 # kthread primitive # # kernel/softirq.c # 2004/02/18 19:42:29-08:00 akpm@osdl.org +10 -12 # kthread primitive # # kernel/sched.c # 2004/02/18 19:42:29-08:00 akpm@osdl.org +18 -42 # kthread primitive # # kernel/module.c # 2004/02/18 19:42:29-08:00 akpm@osdl.org +88 -71 # kthread primitive # # kernel/kthread.c # 2004/02/18 19:42:29-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/kernel/kthread.c # # kernel/kmod.c # 2004/02/18 19:42:29-08:00 akpm@osdl.org +4 -0 # kthread primitive # # kernel/Makefile # 2004/02/18 19:42:29-08:00 akpm@osdl.org +2 -1 # kthread primitive # # include/linux/workqueue.h # 2004/02/18 19:42:29-08:00 akpm@osdl.org +1 -0 # kthread primitive # # include/linux/sched.h # 2004/02/18 19:42:29-08:00 akpm@osdl.org +2 -0 # kthread primitive # # include/linux/kthread.h # 2004/02/18 19:42:29-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/include/linux/kthread.h # # ChangeSet # 2004/02/18 20:47:01-08:00 akpm@osdl.org # [PATCH] ACPI PM timer # # From: Dominik Brodowski , # John Stultz , # Dmitry Torokhov # # Add the ACPI Powermanagement Timer as x86 kernel timing source. Unlike the # Time Stamp Counter, it is a reliable timing source which does not get # affected by aggressive powermanagement features like CPU frequency scaling. # # Some ideas and some code are based on Arjan van de Ven's implementation for # 2.4, and on R. Byron Moore's drivers/acpi/hardware/hwtimer.c. # # # We also replace the loop based delay_pmtmr with a TSC based delay_pmtmr, # which resolves a number of issues caused by the loop based delay. Unsynced # TSCs as well frequency changing TSCs will effect the length of __delay(), but # it seems this method works best. # # arch/i386/kernel/timers/timer_pm.c # 2004/02/18 19:42:28-08:00 akpm@osdl.org +217 -0 # ACPI PM timer # # include/asm-i386/timer.h # 2004/02/18 19:42:28-08:00 akpm@osdl.org +4 -0 # ACPI PM timer # # drivers/acpi/Kconfig # 2004/02/18 19:42:28-08:00 akpm@osdl.org +18 -0 # ACPI PM timer # # arch/i386/kernel/timers/timer_pm.c # 2004/02/18 19:42:28-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/arch/i386/kernel/timers/timer_pm.c # # arch/i386/kernel/timers/timer_cyclone.c # 2004/02/18 19:42:28-08:00 akpm@osdl.org +1 -20 # ACPI PM timer # # arch/i386/kernel/timers/timer.c # 2004/02/18 19:42:28-08:00 akpm@osdl.org +3 -0 # ACPI PM timer # # arch/i386/kernel/timers/common.c # 2004/02/18 19:42:28-08:00 akpm@osdl.org +20 -0 # ACPI PM timer # # arch/i386/kernel/timers/Makefile # 2004/02/18 19:42:28-08:00 akpm@osdl.org +1 -0 # ACPI PM timer # # arch/i386/kernel/acpi/boot.c # 2004/02/18 19:42:28-08:00 akpm@osdl.org +35 -0 # ACPI PM timer # # Documentation/kernel-parameters.txt # 2004/02/18 19:42:28-08:00 akpm@osdl.org +1 -1 # ACPI PM timer # # ChangeSet # 2004/02/18 20:46:52-08:00 akpm@osdl.org # [PATCH] loop: remove redundant initialisation # # From: "Yury V. Umanets" # # This removes a redundant assignment in loop. # # drivers/block/loop.c # 2004/02/18 19:42:28-08:00 akpm@osdl.org +0 -1 # loop: remove redundant initialisation # # ChangeSet # 2004/02/18 20:46:43-08:00 akpm@osdl.org # [PATCH] loop.c doesn't fail init gracefully # # From: BlaisorBlade # # loop_init doesn't fail gracefully for two reasons: # # 1) If initialization of loop driver fails, we have an call to # devfs_add("loop") without any devfs_remove; I add that. # # 2) On lwn.net 2.6 kernel docs, Jonathan Corbet says: "If you are calling # add_disk() in your driver initialization routine, you should not fail # the initialization process after the first call." # # So I make loop.c conform to this request by moving add_disk after all # memory allocations. # # drivers/block/loop.c # 2004/02/18 19:42:27-08:00 akpm@osdl.org +5 -1 # loop.c doesn't fail init gracefully # # ChangeSet # 2004/02/18 20:46:34-08:00 akpm@osdl.org # [PATCH] loop: BIO handling fix # # From: Ben Slusky # # One more patch --- this fixes a minor bio handling bug in the filebacked # code path. I'd fixed it incidentally in the loop-recycle patch. # # I don't think you could actually see damage from this bug unless you # run device mapper on top of loop devices, but still this is the correct # behavior. # # drivers/block/loop.c # 2004/02/18 19:42:27-08:00 akpm@osdl.org +6 -10 # loop: BIO handling fix # # ChangeSet # 2004/02/18 20:46:25-08:00 akpm@osdl.org # [PATCH] remove useless highmem bounce from loop/cryptoloop # # From: Ben Slusky # # The attached patch changes the loop device transfer functions (including # cryptoloop transfers) to accept page/offset pairs instead of virtual # addresses, and removes the redundant kmaps in do_lo_send, do_lo_receive, # and loop_transfer_bio. Per Andrew Morton's request a while back. # # include/linux/loop.h # 2004/02/18 19:42:26-08:00 akpm@osdl.org +7 -4 # remove useless highmem bounce from loop/cryptoloop # # drivers/block/loop.c # 2004/02/18 19:42:26-08:00 akpm@osdl.org +50 -35 # remove useless highmem bounce from loop/cryptoloop # # drivers/block/cryptoloop.c # 2004/02/18 19:42:26-08:00 akpm@osdl.org +48 -32 # remove useless highmem bounce from loop/cryptoloop # # ChangeSet # 2004/02/18 20:46:16-08:00 akpm@osdl.org # [PATCH] loop: remove the bio remapping capability # # This patch removes the loop feature wherein we remap BIOs for block-backed # loop. So file-backed and block-backed loop are handled identically. # # It cleans up the code a lot and fixes the low-on-memory lockups which # block-backed loop currently suffers. # # What we lose is the journalling ordering guarantees which # exts-on-loop-on-blockdev had. But dm-crypt provides that. # # include/linux/loop.h # 2004/02/18 19:42:26-08:00 akpm@osdl.org +1 -2 # loop: remove the bio remapping capability # # drivers/block/loop.c # 2004/02/18 19:42:26-08:00 akpm@osdl.org +8 -201 # loop: remove the bio remapping capability # # ChangeSet # 2004/02/18 20:46:08-08:00 akpm@osdl.org # [PATCH] ppc64: iseries IRQ fix # # From: Stephen Rothwell # # This patch lets 2.6.3-rc4 build and boot on an PPC64 iSeries box (at least # for my configuration). The veth.o bit in the networking Makefile got there # by accident and should be removed anyway ... # # There is more to make it work properly (note the "Temporary hack"), but # this gets us closer. # # drivers/net/Makefile # 2004/02/18 19:42:25-08:00 akpm@osdl.org +0 -1 # ppc64: iseries IRQ fix # # arch/ppc64/kernel/iSeries_setup.c # 2004/02/18 19:42:25-08:00 akpm@osdl.org +0 -1 # ppc64: iseries IRQ fix # # arch/ppc64/kernel/iSeries_pci.c # 2004/02/18 19:42:25-08:00 akpm@osdl.org +0 -1 # ppc64: iseries IRQ fix # # arch/ppc64/kernel/iSeries_irq.c # 2004/02/18 19:42:25-08:00 akpm@osdl.org +6 -16 # ppc64: iseries IRQ fix # # ChangeSet # 2004/02/18 20:45:59-08:00 akpm@osdl.org # [PATCH] ppc64: fix debugger() warnings # # From: Anton Blanchard # # Fix compile warnings and add some type safety to debugger macros. # # include/asm-ppc64/system.h # 2004/02/18 19:42:25-08:00 akpm@osdl.org +6 -6 # ppc64: fix debugger() warnings # # ChangeSet # 2004/02/18 20:45:50-08:00 akpm@osdl.org # [PATCH] ppc64: fix saved_command_line/cmd_line lengths # # From: Anton Blanchard # # cmd_line was twice the size of saved_command_line but we did a strcpy from # the larger into the smaller. Create COMMAND_LINE_SIZE and use it. # # include/asm-ppc64/machdep.h # 2004/02/18 19:42:24-08:00 akpm@osdl.org +2 -1 # ppc64: fix saved_command_line/cmd_line lengths # # include/asm-ppc/machdep.h # 2004/02/18 19:42:24-08:00 akpm@osdl.org +2 -1 # ppc64: fix saved_command_line/cmd_line lengths # # arch/ppc64/kernel/setup.c # 2004/02/18 19:42:24-08:00 akpm@osdl.org +3 -3 # ppc64: fix saved_command_line/cmd_line lengths # # arch/ppc/kernel/setup.c # 2004/02/18 19:42:24-08:00 akpm@osdl.org +4 -4 # ppc64: fix saved_command_line/cmd_line lengths # # ChangeSet # 2004/02/18 20:45:41-08:00 akpm@osdl.org # [PATCH] ppc64: Fix prom.c warnings # # arch/ppc64/kernel/prom.c:200: warning: missing braces around initializer # arch/ppc64/kernel/prom.c:200: warning: (near initialization for `hmt_thread_data[0]') # arch/ppc64/kernel/prom.c: In function `prom_hold_cpus': # arch/ppc64/kernel/prom.c:1090: warning: implicit declaration of function `_get_PIR' # # arch/ppc64/kernel/prom.c # 2004/02/18 19:42:24-08:00 akpm@osdl.org +2 -1 # ppc64: Fix prom.c warnings # # ChangeSet # 2004/02/18 20:45:32-08:00 akpm@osdl.org # [PATCH] msg.h needs list.h # # msg.h uses list_head. (I'm not sure what config actually required this, but # it is legit). # # include/linux/msg.h # 2004/02/18 19:42:23-08:00 akpm@osdl.org +1 -0 # msg.h needs list.h # # ChangeSet # 2004/02/18 20:45:23-08:00 akpm@osdl.org # [PATCH] Remove BDEV_RAW and friends # # These no longer do anything. # # This patch changes modules API. It was acked by Arjan@RH and Hubert@Suse. # # kernel/power/swsusp.c # 2004/02/18 19:42:22-08:00 akpm@osdl.org +2 -2 # Remove BDEV_RAW and friends # # kernel/power/pmdisk.c # 2004/02/18 19:42:22-08:00 akpm@osdl.org +2 -2 # Remove BDEV_RAW and friends # # include/linux/fs.h # 2004/02/18 19:42:22-08:00 akpm@osdl.org +5 -6 # Remove BDEV_RAW and friends # # fs/xfs/linux/xfs_super.c # 2004/02/18 19:42:22-08:00 akpm@osdl.org +2 -2 # Remove BDEV_RAW and friends # # fs/super.c # 2004/02/18 19:42:22-08:00 akpm@osdl.org +3 -3 # Remove BDEV_RAW and friends # # fs/reiserfs/journal.c # 2004/02/18 19:42:22-08:00 akpm@osdl.org +2 -2 # Remove BDEV_RAW and friends # # fs/partitions/check.c # 2004/02/18 19:42:22-08:00 akpm@osdl.org +2 -2 # Remove BDEV_RAW and friends # # fs/jfs/jfs_logmgr.c # 2004/02/18 19:42:22-08:00 akpm@osdl.org +3 -4 # Remove BDEV_RAW and friends # # fs/ext3/super.c # 2004/02/18 19:42:22-08:00 akpm@osdl.org +3 -3 # Remove BDEV_RAW and friends # # fs/block_dev.c # 2004/02/18 19:42:22-08:00 akpm@osdl.org +15 -18 # Remove BDEV_RAW and friends # # drivers/s390/block/dasd_genhd.c # 2004/02/18 19:42:22-08:00 akpm@osdl.org +2 -2 # Remove BDEV_RAW and friends # # drivers/mtd/devices/blkmtd.c # 2004/02/18 19:42:22-08:00 akpm@osdl.org +5 -5 # Remove BDEV_RAW and friends # # drivers/md/md.c # 2004/02/18 19:42:22-08:00 akpm@osdl.org +3 -3 # Remove BDEV_RAW and friends # # drivers/md/dm-table.c # 2004/02/18 19:42:22-08:00 akpm@osdl.org +3 -3 # Remove BDEV_RAW and friends # # drivers/char/raw.c # 2004/02/18 19:42:22-08:00 akpm@osdl.org +3 -3 # Remove BDEV_RAW and friends # # drivers/block/rd.c # 2004/02/18 19:42:22-08:00 akpm@osdl.org +1 -1 # Remove BDEV_RAW and friends # # ChangeSet # 2004/02/18 20:45:13-08:00 akpm@osdl.org # [PATCH] early printk tweaks # # - Use __pa() around the VGA base address: more friendly for the 4g/4g split. # # - Use cpu_relax() rather than open-coding rep_nop(). # # - Default to 9600 baud # # - Move documentation to Documentation/kernel-parameters.txt # # - Make CONFIG_EARLY_PRINTK disableable if CONFIG_EMBEDDED # # arch/x86_64/kernel/head64.c # 2004/02/18 19:42:21-08:00 akpm@osdl.org +2 -2 # early printk tweaks # # arch/x86_64/kernel/early_printk.c # 2004/02/18 19:42:21-08:00 akpm@osdl.org +30 -30 # early printk tweaks # # arch/x86_64/Kconfig # 2004/02/18 19:42:21-08:00 akpm@osdl.org +8 -6 # early printk tweaks # # arch/i386/kernel/setup.c # 2004/02/18 19:42:21-08:00 akpm@osdl.org +2 -1 # early printk tweaks # # arch/i386/Kconfig # 2004/02/18 19:42:21-08:00 akpm@osdl.org +11 -1 # early printk tweaks # # Documentation/kernel-parameters.txt # 2004/02/18 19:42:21-08:00 akpm@osdl.org +2 -2 # early printk tweaks # # ChangeSet # 2004/02/18 20:45:04-08:00 akpm@osdl.org # [PATCH] ia32 early printk # # From: Andi Kleen # # Implement VGA and serial early printk on x86. We just include the x86_64 # version. # # arch/i386/kernel/early_printk.c # 2004/02/18 19:42:21-08:00 akpm@osdl.org +2 -0 # ia32 early printk # # arch/x86_64/kernel/early_printk.c # 2004/02/18 19:42:21-08:00 akpm@osdl.org +4 -0 # ia32 early printk # # arch/i386/kernel/setup.c # 2004/02/18 19:42:21-08:00 akpm@osdl.org +12 -0 # ia32 early printk # # arch/i386/kernel/early_printk.c # 2004/02/18 19:42:21-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/arch/i386/kernel/early_printk.c # # arch/i386/kernel/Makefile # 2004/02/18 19:42:21-08:00 akpm@osdl.org +1 -0 # ia32 early printk # # arch/i386/Kconfig # 2004/02/18 19:42:21-08:00 akpm@osdl.org +3 -0 # ia32 early printk # # Documentation/kernel-parameters.txt # 2004/02/18 19:42:21-08:00 akpm@osdl.org +17 -0 # ia32 early printk # # ChangeSet # 2004/02/18 20:44:55-08:00 akpm@osdl.org # [PATCH] Fix for PPP activ/passiv filter # # From: Karsten Keil # # I found a bug in the PPPIOCSPASS PPPIOCSACTIVE IOCTL implementation in # kernel 2.5/2.6. # # The current pppd code use a empty filter (uprog.len=0) to detach the filter # in the kernel, but this code was removed in 2.5.71 while fixing a compiler # warning. # # Here the new patch, also with better limit checking. # # The second patch check for flen == 0 in the filter check too, since later # in this code a filter[flen - 1] access is done, which is not so funny with # flen 0. Maybe it's not really needed anymore, since with the first patch # it would not longer called with flen=0. # # paulus says: # # It looks correct. Previously we had (and in 2.4 we still have) # # if (uprog.len > 0 && uprog.len < 65536) { # ... # # which gave warnings since uprog.len is unsigned short. So someone # decided that both parts of the condition were redundant. # # net/core/filter.c # 2004/02/18 19:42:20-08:00 akpm@osdl.org +1 -1 # Fix for PPP activ/passiv filter # # drivers/net/ppp_generic.c # 2004/02/18 19:42:20-08:00 akpm@osdl.org +18 -13 # Fix for PPP activ/passiv filter # # ChangeSet # 2004/02/18 20:44:45-08:00 akpm@osdl.org # [PATCH] i4l: hisax deadlock fix # # From: Karsten Keil # # This patch fix a deadlock in HiSax (reported from David Woodhouse # ). upper layer was called back while holding the card # lock fix is to move the wakeup call into BH handler to avoid direct # callbacks. # # drivers/isdn/hisax/w6692.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +10 -5 # i4l: hisax deadlock fix # # drivers/isdn/hisax/netjet.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +10 -5 # i4l: hisax deadlock fix # # drivers/isdn/hisax/jade_irq.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +9 -4 # i4l: hisax deadlock fix # # drivers/isdn/hisax/isdnl2.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +4 -4 # i4l: hisax deadlock fix # # drivers/isdn/hisax/isdnl1.h # 2004/02/18 19:42:19-08:00 akpm@osdl.org +4 -3 # i4l: hisax deadlock fix # # drivers/isdn/hisax/isdnl1.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +19 -2 # i4l: hisax deadlock fix # # drivers/isdn/hisax/isar.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +9 -4 # i4l: hisax deadlock fix # # drivers/isdn/hisax/ipacx.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +27 -24 # i4l: hisax deadlock fix # # drivers/isdn/hisax/hscx_irq.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +9 -4 # i4l: hisax deadlock fix # # drivers/isdn/hisax/hisax.h # 2004/02/18 19:42:19-08:00 akpm@osdl.org +7 -3 # i4l: hisax deadlock fix # # drivers/isdn/hisax/hfc_sx.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +10 -5 # i4l: hisax deadlock fix # # drivers/isdn/hisax/hfc_pci.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +20 -10 # i4l: hisax deadlock fix # # drivers/isdn/hisax/hfc_2bs0.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +9 -3 # i4l: hisax deadlock fix # # drivers/isdn/hisax/hfc_2bds0.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +9 -4 # i4l: hisax deadlock fix # # drivers/isdn/hisax/elsa_ser.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +9 -5 # i4l: hisax deadlock fix # # drivers/isdn/hisax/diva.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +10 -5 # i4l: hisax deadlock fix # # drivers/isdn/hisax/config.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +8 -3 # i4l: hisax deadlock fix # # drivers/isdn/hisax/callc.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +8 -8 # i4l: hisax deadlock fix # # drivers/isdn/hisax/avm_pci.c # 2004/02/18 19:42:19-08:00 akpm@osdl.org +10 -5 # i4l: hisax deadlock fix # # ChangeSet # 2004/02/18 20:44:35-08:00 akpm@osdl.org # [PATCH] ISDN udpate # # From: Karsten Keil # # - new port of 2.4 I4L core to 2.6 # # - new port of 2.4 I4L HiSax to 2.6 # # - fixes for I4L CAPI subsystem to make it stable in 2.6 # # - fix parameter handling of AVM ISA cards (calle) # # - cleanup ISDN config variables # # - SMP in act2000 and pcbit driver # # - remove check_region in act2000 # # - mark hysdn, isdnloop and divert as BROKEN_ON_SMP # # include/linux/isdnif.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +23 -1 # ISDN udpate # # include/linux/isdn_ppp.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +166 -50 # ISDN udpate # # include/linux/isdn/capilli.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +17 -1 # ISDN udpate # # include/linux/isdn.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +300 -68 # ISDN udpate # # include/linux/concap.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +2 -1 # ISDN udpate # # drivers/isdn/tpam/Kconfig # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -1 # ISDN udpate # # drivers/isdn/sc/timer.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +25 -24 # ISDN udpate # # drivers/isdn/sc/shmem.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +31 -29 # ISDN udpate # # drivers/isdn/sc/packet.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +60 -47 # ISDN udpate # # drivers/isdn/sc/message.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +36 -35 # ISDN udpate # # drivers/isdn/sc/ioctl.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +78 -57 # ISDN udpate # # drivers/isdn/sc/interrupt.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +41 -29 # ISDN udpate # # drivers/isdn/sc/init.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +55 -47 # ISDN udpate # # drivers/isdn/sc/hardware.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -1 # ISDN udpate # # drivers/isdn/sc/event.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +5 -5 # ISDN udpate # # drivers/isdn/sc/command.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +41 -40 # ISDN udpate # # drivers/isdn/sc/Kconfig # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -1 # ISDN udpate # # drivers/isdn/pcbit/pcbit.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -1 # ISDN udpate # # drivers/isdn/pcbit/layer2.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +15 -28 # ISDN udpate # # drivers/isdn/pcbit/edss1.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +3 -5 # ISDN udpate # # drivers/isdn/pcbit/drv.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -0 # ISDN udpate # # drivers/isdn/pcbit/Kconfig # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -1 # ISDN udpate # # drivers/isdn/icn/Kconfig # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -1 # ISDN udpate # # drivers/isdn/i4l/isdn_x25iface.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +7 -4 # ISDN udpate # # drivers/isdn/i4l/isdn_x25iface.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +13 -18 # ISDN udpate # # drivers/isdn/i4l/isdn_v110.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +8 -14 # ISDN udpate # # drivers/isdn/i4l/isdn_v110.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +100 -88 # ISDN udpate # # drivers/isdn/i4l/isdn_ttyfax.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +4 -1 # ISDN udpate # # drivers/isdn/i4l/isdn_ttyfax.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +68 -24 # ISDN udpate # # drivers/isdn/i4l/isdn_tty.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +17 -23 # ISDN udpate # # drivers/isdn/i4l/isdn_tty.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +575 -586 # ISDN udpate # # drivers/isdn/i4l/isdn_ppp.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +32 -46 # ISDN udpate # # drivers/isdn/i4l/isdn_ppp.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +2570 -932 # ISDN udpate # # drivers/isdn/i4l/isdn_net.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +182 -8 # ISDN udpate # # drivers/isdn/i4l/isdn_net.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +3163 -90 # ISDN udpate # # drivers/isdn/i4l/isdn_concap.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +5 -3 # ISDN udpate # # drivers/isdn/i4l/isdn_concap.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +10 -153 # ISDN udpate # # drivers/isdn/i4l/isdn_common.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +19 -121 # ISDN udpate # # drivers/isdn/i4l/isdn_common.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1792 -1924 # ISDN udpate # # drivers/isdn/i4l/isdn_audio.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +4 -1 # ISDN udpate # # drivers/isdn/i4l/isdn_audio.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +93 -71 # ISDN udpate # # drivers/isdn/i4l/Makefile # 2004/02/18 19:42:12-08:00 akpm@osdl.org +8 -9 # ISDN udpate # # drivers/isdn/i4l/Kconfig # 2004/02/18 19:42:12-08:00 akpm@osdl.org +27 -21 # ISDN udpate # # drivers/isdn/hysdn/hysdn_proclog.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +3 -3 # ISDN udpate # # drivers/isdn/hysdn/Kconfig # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -1 # ISDN udpate # # drivers/isdn/hisax/w6692.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +4 -1 # ISDN udpate # # drivers/isdn/hisax/w6692.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +607 -264 # ISDN udpate # # drivers/isdn/hisax/telespci.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +219 -153 # ISDN udpate # # drivers/isdn/hisax/teles_cs.c # 2004/02/18 20:44:27-08:00 akpm@osdl.org +549 -0 # # drivers/isdn/hisax/teles3.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +320 -236 # ISDN udpate # # drivers/isdn/hisax/teles0.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +244 -135 # ISDN udpate # # drivers/isdn/hisax/teleint.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +127 -120 # ISDN udpate # # drivers/isdn/hisax/tei.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +17 -33 # ISDN udpate # # drivers/isdn/hisax/st5481_usb.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +5 -5 # ISDN udpate # # drivers/isdn/hisax/st5481_init.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +4 -5 # ISDN udpate # # drivers/isdn/hisax/st5481_d.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +14 -14 # ISDN udpate # # drivers/isdn/hisax/st5481_b.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +26 -17 # ISDN udpate # # drivers/isdn/hisax/st5481.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +15 -15 # ISDN udpate # # drivers/isdn/hisax/sportster.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +136 -109 # ISDN udpate # # drivers/isdn/hisax/sedlbauer_cs.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +24 -7 # ISDN udpate # # drivers/isdn/hisax/sedlbauer.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +541 -531 # ISDN udpate # # drivers/isdn/hisax/saphir.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +161 -112 # ISDN udpate # # drivers/isdn/hisax/s0box.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +147 -95 # ISDN udpate # # drivers/isdn/hisax/q931.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +35 -36 # ISDN udpate # # drivers/isdn/hisax/nj_u.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +151 -102 # ISDN udpate # # drivers/isdn/hisax/nj_s.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +182 -121 # ISDN udpate # # drivers/isdn/hisax/niccy.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +216 -159 # ISDN udpate # # drivers/isdn/hisax/netjet.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +6 -8 # ISDN udpate # # drivers/isdn/hisax/netjet.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +110 -118 # ISDN udpate # # drivers/isdn/hisax/mic.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +155 -92 # ISDN udpate # # drivers/isdn/hisax/l3ni1.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +201 -211 # ISDN udpate # # drivers/isdn/hisax/l3dss1.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +214 -224 # ISDN udpate # # drivers/isdn/hisax/l3_1tr6.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +77 -81 # ISDN udpate # # drivers/isdn/hisax/jade_irq.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +131 -36 # ISDN udpate # # drivers/isdn/hisax/jade.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +3 -4 # ISDN udpate # # drivers/isdn/hisax/jade.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +144 -106 # ISDN udpate # # drivers/isdn/hisax/ix1_micro.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +178 -127 # ISDN udpate # # drivers/isdn/hisax/isurf.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +155 -127 # ISDN udpate # # drivers/isdn/hisax/isdnl3.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +19 -19 # ISDN udpate # # drivers/isdn/hisax/isdnl2.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +114 -103 # ISDN udpate # # drivers/isdn/hisax/isdnl1.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +4 -570 # ISDN udpate # # drivers/isdn/hisax/isdnl1.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +31 -51 # ISDN udpate # # drivers/isdn/hisax/isdnhdlc.h # 2004/02/18 20:44:27-08:00 akpm@osdl.org +72 -0 # # drivers/isdn/hisax/isdnhdlc.c # 2004/02/18 20:44:27-08:00 akpm@osdl.org +669 -0 # # drivers/isdn/hisax/isar.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +10 -2 # ISDN udpate # # drivers/isdn/hisax/isar.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +361 -212 # ISDN udpate # # drivers/isdn/hisax/isac.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +6 -4 # ISDN udpate # # drivers/isdn/hisax/isac.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +255 -140 # ISDN udpate # # drivers/isdn/hisax/ipacx.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +3 -5 # ISDN udpate # # drivers/isdn/hisax/ipacx.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +497 -237 # ISDN udpate # # drivers/isdn/hisax/ipac.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -76 # ISDN udpate # # drivers/isdn/hisax/icc.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +5 -3 # ISDN udpate # # drivers/isdn/hisax/hisax_cfg.h # 2004/02/18 20:44:27-08:00 akpm@osdl.org +64 -0 # # drivers/isdn/hisax/hfc_usb.c # 2004/02/18 20:44:27-08:00 akpm@osdl.org +1667 -0 # # drivers/isdn/hisax/Makefile # 2004/02/18 19:42:12-08:00 akpm@osdl.org +15 -13 # ISDN udpate # # drivers/isdn/hisax/Kconfig # 2004/02/18 19:42:12-08:00 akpm@osdl.org +30 -17 # ISDN udpate # # drivers/isdn/Makefile # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -1 # ISDN udpate # # drivers/isdn/Kconfig # 2004/02/18 19:42:12-08:00 akpm@osdl.org +7 -7 # ISDN udpate # # drivers/Makefile # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -1 # ISDN udpate # # drivers/isdn/hisax/teles_cs.c # 2004/02/18 20:44:27-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/drivers/isdn/hisax/teles_cs.c # # drivers/isdn/hisax/isdnhdlc.h # 2004/02/18 20:44:27-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/drivers/isdn/hisax/isdnhdlc.h # # drivers/isdn/hisax/isdnhdlc.c # 2004/02/18 20:44:27-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/drivers/isdn/hisax/isdnhdlc.c # # drivers/isdn/hisax/icc.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +259 -142 # ISDN udpate # # drivers/isdn/hisax/hscx_irq.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +164 -103 # ISDN udpate # # drivers/isdn/hisax/hscx.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +5 -9 # ISDN udpate # # drivers/isdn/hisax/hscx.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +148 -121 # ISDN udpate # # drivers/isdn/hisax/hisax_isac.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +8 -8 # ISDN udpate # # drivers/isdn/hisax/hisax_isac.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +4 -4 # ISDN udpate # # drivers/isdn/hisax/hisax_fcpcipnp.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +11 -10 # ISDN udpate # # drivers/isdn/hisax/hisax_fcpcipnp.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +118 -99 # ISDN udpate # # drivers/isdn/hisax/hisax_debug.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -1 # ISDN udpate # # drivers/isdn/hisax/hisax_cfg.h # 2004/02/18 20:44:27-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/drivers/isdn/hisax/hisax_cfg.h # # drivers/isdn/hisax/hisax.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +442 -329 # ISDN udpate # # drivers/isdn/hisax/hfcscard.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +132 -136 # ISDN udpate # # drivers/isdn/hisax/hfc_usb.c # 2004/02/18 20:44:27-08:00 akpm@osdl.org +0 -0 # BitKeeper file /home/torvalds/v2.5/linux/drivers/isdn/hisax/hfc_usb.c # # drivers/isdn/hisax/hfc_sx.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +420 -203 # ISDN udpate # # drivers/isdn/hisax/hfc_pci.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +23 -25 # ISDN udpate # # drivers/isdn/hisax/hfc_pci.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +507 -240 # ISDN udpate # # drivers/isdn/hisax/hfc_2bs0.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -2 # ISDN udpate # # drivers/isdn/hisax/hfc_2bs0.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +92 -86 # ISDN udpate # # drivers/isdn/hisax/hfc_2bds0.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +2 -2 # ISDN udpate # # drivers/isdn/hisax/hfc_2bds0.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +274 -95 # ISDN udpate # # drivers/isdn/hisax/gazel.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +513 -364 # ISDN udpate # # drivers/isdn/hisax/enternow_pci.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +205 -158 # ISDN udpate # # drivers/isdn/hisax/enternow.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +9 -0 # ISDN udpate # # drivers/isdn/hisax/elsa_ser.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +65 -77 # ISDN udpate # # drivers/isdn/hisax/elsa_cs.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +25 -7 # ISDN udpate # # drivers/isdn/hisax/elsa.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +640 -570 # ISDN udpate # # drivers/isdn/hisax/diva.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +854 -474 # ISDN udpate # # drivers/isdn/hisax/config.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +336 -566 # ISDN udpate # # drivers/isdn/hisax/callc.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +100 -135 # ISDN udpate # # drivers/isdn/hisax/bkm_a8.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +256 -103 # ISDN udpate # # drivers/isdn/hisax/bkm_a4t.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +192 -173 # ISDN udpate # # drivers/isdn/hisax/avma1_cs.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +51 -50 # ISDN udpate # # drivers/isdn/hisax/avm_pci.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +391 -274 # ISDN udpate # # drivers/isdn/hisax/avm_a1p.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +130 -125 # ISDN udpate # # drivers/isdn/hisax/avm_a1.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +189 -114 # ISDN udpate # # drivers/isdn/hisax/asuscom.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +270 -201 # ISDN udpate # # drivers/isdn/hisax/arcofi.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +6 -19 # ISDN udpate # # drivers/isdn/hisax/amd7930_fn.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +17 -4 # ISDN udpate # # drivers/isdn/hisax/amd7930_fn.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +113 -132 # ISDN udpate # # drivers/isdn/hardware/eicon/Kconfig # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -1 # ISDN udpate # # drivers/isdn/hardware/avm/t1pci.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +27 -2 # ISDN udpate # # drivers/isdn/hardware/avm/t1isa.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +73 -22 # ISDN udpate # # drivers/isdn/hardware/avm/c4.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +67 -17 # ISDN udpate # # drivers/isdn/hardware/avm/b1pcmcia.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +38 -1 # ISDN udpate # # drivers/isdn/hardware/avm/b1pci.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +43 -2 # ISDN udpate # # drivers/isdn/hardware/avm/b1isa.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +47 -9 # ISDN udpate # # drivers/isdn/hardware/avm/b1dma.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +34 -16 # ISDN udpate # # drivers/isdn/hardware/avm/b1.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +31 -20 # ISDN udpate # # drivers/isdn/hardware/avm/Kconfig # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -1 # ISDN udpate # # drivers/isdn/hardware/Kconfig # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -24 # ISDN udpate # # drivers/isdn/capi/kcapi_proc.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +69 -2 # ISDN udpate # # drivers/isdn/capi/kcapi.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +5 -2 # ISDN udpate # # drivers/isdn/capi/kcapi.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +120 -7 # ISDN udpate # # drivers/isdn/capi/capifs.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +3 -3 # ISDN udpate # # drivers/isdn/capi/capifs.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +81 -128 # ISDN udpate # # drivers/isdn/capi/capidrv.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +14 -4 # ISDN udpate # # drivers/isdn/capi/capi.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +22 -18 # ISDN udpate # # drivers/isdn/capi/Kconfig # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -1 # ISDN udpate # # drivers/isdn/act2000/module.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +24 -28 # ISDN udpate # # drivers/isdn/act2000/capi.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +2 -3 # ISDN udpate # # drivers/isdn/act2000/capi.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +4 -6 # ISDN udpate # # drivers/isdn/act2000/act2000_isa.c # 2004/02/18 19:42:12-08:00 akpm@osdl.org +10 -13 # ISDN udpate # # drivers/isdn/act2000/act2000.h # 2004/02/18 19:42:12-08:00 akpm@osdl.org +26 -24 # ISDN udpate # # drivers/isdn/act2000/Kconfig # 2004/02/18 19:42:12-08:00 akpm@osdl.org +1 -1 # ISDN udpate # # BitKeeper/deleted/.del-isdn_ppp_vj.h~b6a2bb5de2c0ea97 # 2004/02/18 20:44:27-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/i4l/isdn_ppp_vj.h # # BitKeeper/deleted/.del-isdn_ppp_vj.c~16e30fdbc5007821 # 2004/02/18 20:44:27-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/i4l/isdn_ppp_vj.c # # BitKeeper/deleted/.del-isdn_ppp_mp.h~9d5f9a2592c3030f # 2004/02/18 20:44:27-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/i4l/isdn_ppp_mp.h # # BitKeeper/deleted/.del-fsm.h~df80c0c3a20f6309 # 2004/02/18 20:44:27-08:00 akpm@osdl.org +0 -0 # Delete: include/linux/isdn/fsm.h # # BitKeeper/deleted/.del-rawhdlc.h~1afc6d34b2872e # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/hisax/rawhdlc.h # # BitKeeper/deleted/.del-rawhdlc.c~159110ae54202095 # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/hisax/rawhdlc.c # # BitKeeper/deleted/.del-md5sums.asc~e89f19eb5296dcf3 # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/hisax/md5sums.asc # # BitKeeper/deleted/.del-isdn_ppp_mp.c~295bd265c90f0a1 # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/i4l/isdn_ppp_mp.c # # BitKeeper/deleted/.del-isdn_ppp_ccp.h~1b7eab15b8385d67 # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/i4l/isdn_ppp_ccp.h # # BitKeeper/deleted/.del-isdn_ppp_ccp.c~87883bb074ad6fc0 # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/i4l/isdn_ppp_ccp.c # # BitKeeper/deleted/.del-isdn_net_lib.h~872c970d7316cd8b # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/i4l/isdn_net_lib.h # # BitKeeper/deleted/.del-isdn_net_lib.c~d7285ba4ce9ae41c # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/i4l/isdn_net_lib.c # # BitKeeper/deleted/.del-isdn_fsm.c~bca6817be24d7b18 # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/i4l/isdn_fsm.c # # BitKeeper/deleted/.del-isdn_ciscohdlck.h~f78e4e1efb048809 # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/i4l/isdn_ciscohdlck.h # # BitKeeper/deleted/.del-isdn_ciscohdlck.c~8a401ce52b9a03fd # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/i4l/isdn_ciscohdlck.c # # BitKeeper/deleted/.del-ipac.c~eeac457c2f6ccccb # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/hisax/ipac.c # # BitKeeper/deleted/.del-hisax_hscx.h~9c7d02ee53b5de77 # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/hisax/hisax_hscx.h # # BitKeeper/deleted/.del-hisax_hscx.c~ad12a2a2f72c749a # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/hisax/hisax_hscx.c # # BitKeeper/deleted/.del-hisax_hfcpci.h~348482271a5520c1 # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/hisax/hisax_hfcpci.h # # BitKeeper/deleted/.del-hisax_hfcpci.c~d92ab2a91deafaf8 # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/hisax/hisax_hfcpci.c # # BitKeeper/deleted/.del-hisax_fcclassic.h~d32aaf5a11100487 # 2004/02/18 20:44:26-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/hisax/hisax_fcclassic.h # # BitKeeper/deleted/.del-hisax_fcclassic.c~4d7163f18e8eab2a # 2004/02/18 20:44:25-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/hisax/hisax_fcclassic.c # # BitKeeper/deleted/.del-cert.c~5efb3f80e4e90681 # 2004/02/18 20:44:25-08:00 akpm@osdl.org +0 -0 # Delete: drivers/isdn/hisax/cert.c # # ChangeSet # 2004/02/19 02:48:43+00:00 davej@redhat.com # [CPUFREQ] Add extra __init markers to longrun driver. # Caught by Randy Dunlap. # longrun_cpu_init() only gets called during startup, and calls # other __init routines. # # arch/i386/kernel/cpu/cpufreq/longrun.c # 2004/02/19 02:48:38+00:00 davej@redhat.com +1 -1 # [CPUFREQ] Add extra __init markers to longrun driver. # Caught by Randy Dunlap. # longrun_cpu_init() only gets called during startup, and calls # other __init routines. # # ChangeSet # 2004/02/19 02:46:52+00:00 davej@redhat.com # [CPUFREQ] Add extra __init markers to longhaul driver. # Caught by Randy Dunlap. # longhaul_cpu_init only gets called during startup, and calls # other __init routines. # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/02/19 02:46:47+00:00 davej@redhat.com +2 -2 # [CPUFREQ] Add extra __init marker to longhaul driver. # Caught by Randy Dunlap. # longhaul_cpu_init only gets called during startup, and calls # other __init routines. # # ChangeSet # 2004/02/18 19:52:03-05:00 akpm@osdl.org # [PATCH] tulip printk warning fix # # Don't assume the size of a dma_addr_t # # drivers/net/tulip/interrupt.c # 2004/02/18 10:43:06-05:00 akpm@osdl.org +2 -2 # tulip printk warning fix # # ChangeSet # 2004/02/18 19:34:42-05:00 romieu@fr.zoreil.com # [PATCH] 2.6.3 - drivers/net/sis190.c - Tx desc overflow # # Tx descriptor overflow - take II. # # Assume tp->dirty_tx = NUM_TX_DESC/2, tp->cur_tx = NUM_TX_DESC - 1, # watch "entry" go beyond NUM_TX_DESC. Actually this is where the same # bug in r8169 driver comes from. # # drivers/net/sis190.c # 2004/02/18 18:52:32-05:00 romieu@fr.zoreil.com +3 -3 # 2.6.3 - drivers/net/sis190.c - Tx desc overflow # # ChangeSet # 2004/02/18 19:29:38-05:00 rddunlap@osdl.org # [PATCH] tr/3c359: handle kmalloc failures during init # # From: Pablo Menichini # and maximilian attems # # # while looking at kj mails from 200212 and 200301 # this patch slept through # originally from: Pablo Menichini # rediffed and compile tested # patch applies on plain 2.6.0 # # maximilian attems # # handle kmalloc failures during init # # diff -puN drivers/net/tokenring/3c359.c~tr3c_kmalloc drivers/net/tokenring/3c359.c # # # linux-261-bk4-kj1-rddunlap/drivers/net/tokenring/3c359.c | 13 +++++++++++++ # 1 files changed, 13 insertions(+) # # drivers/net/tokenring/3c359.c # 2004/01/16 19:03:29-05:00 rddunlap@osdl.org +13 -0 # tr/3c359: handle kmalloc failures during init # # ChangeSet # 2004/02/18 19:29:31-05:00 brazilnut@us.ibm.com # [PATCH] 2.6.3 pcnet32.c transmit hang fix # # The transmit routine will stop interrupting and hang, causing the # tx_timeout routine to attempt to restart the device when the 32-bit # cur_tx counter wraps below dirty_tx. If the device had called # netif_stop_queue it will never call netif_wake_queue in the interrupt # routine (at least on an IA32 system) due to 32-bit wrap around arithmetic. # # On my IA32 system 'dirty_tx > lp->cur_tx - TX_RING_SIZE + 2' would # always evaluate to false when dirty and cur_tx were less than 15, # preventing netif_wake_queue to be called. # # By starting dirty_tx and cur_tx at 0xfffffff0 (to reduce test time) I # found that once cur_tx wrapped to zero, that transmitted buffers would # never be unmapped or freed because 'while (dirty_tx < lp->cur_tx) {' # was not true. cur_tx would keep incrementing (in start_xmit) but dirty_tx # would not (in pcnet32_interrupt), thus leaking skb's and pci map entries. # On PPC machines, the system would quickly run out of pci maps. # # Fix tested on PPC and IA32. # # drivers/net/pcnet32.c # 2004/02/18 10:36:59-05:00 brazilnut@us.ibm.com +12 -8 # 2.6.3 pcnet32.c transmit hang fix # # ChangeSet # 2004/02/18 19:29:24-05:00 rddunlap@osdl.org # [PATCH] depca: remove double semi-colon # # description: remove double semi-colon typo; # # drivers/net/depca.c # 2004/01/25 19:48:45-05:00 rddunlap@osdl.org +1 -1 # [PATCH[ depca: remove double semi-colon # # ChangeSet # 2004/02/18 16:27:29-08:00 davem@nuts.davemloft.net # [SELINUX]: Forgot to add these in previous commit. # # security/selinux/netlink.c # 2004/02/18 16:27:12-08:00 davem@nuts.davemloft.net +113 -0 # [SELINUX]: Forgot to add these in previous commit. # # security/selinux/netlink.c # 2004/02/18 16:27:12-08:00 davem@nuts.davemloft.net +0 -0 # BitKeeper file /disk1/BK/net-2.6/security/selinux/netlink.c # # include/linux/selinux_netlink.h # 2004/02/18 16:27:11-08:00 davem@nuts.davemloft.net +37 -0 # [SELINUX]: Forgot to add these in previous commit. # # include/linux/selinux_netlink.h # 2004/02/18 16:27:11-08:00 davem@nuts.davemloft.net +0 -0 # BitKeeper file /disk1/BK/net-2.6/include/linux/selinux_netlink.h # # ChangeSet # 2004/02/18 16:23:41-08:00 jmorris@redhat.com # [SELINUX]: Event notifications via netlink. # # security/selinux/ss/services.c # 2004/02/18 16:23:22-08:00 jmorris@redhat.com +3 -0 # [SELINUX]: Event notifications via netlink. # # security/selinux/selinuxfs.c # 2004/02/18 16:23:22-08:00 jmorris@redhat.com +3 -0 # [SELINUX]: Event notifications via netlink. # # security/selinux/Makefile # 2004/02/18 16:23:22-08:00 jmorris@redhat.com +1 -1 # [SELINUX]: Event notifications via netlink. # # include/linux/netlink.h # 2004/02/18 16:23:22-08:00 jmorris@redhat.com +1 -0 # [SELINUX]: Event notifications via netlink. # # ChangeSet # 2004/02/18 19:12:30-05:00 jhf@rivenstone.net # [netdrvr sis900] fix multicast bug # # drivers/net/sis900.c # 2004/02/18 19:12:26-05:00 jhf@rivenstone.net +1 -1 # [netdrvr sis900] fix multicast bug # # ChangeSet # 2004/02/18 18:59:35-05:00 shmulik.hen@intel.com # [PATCH] Add VLAN support in ALB mode # # Add capability to tag self generated ARP packets that are required # for receive load balancing in bonding. VLAN Id's are saved and used # each time a new IP connection is established since 8021q currently # supports IP binding. # # Update module version and comment blocks. # # drivers/net/bonding/bonding.h # 2004/01/21 11:56:28-05:00 shmulik.hen@intel.com +2 -2 # Add VLAN support in ALB mode # # drivers/net/bonding/bond_main.c # 2004/01/21 11:56:28-05:00 shmulik.hen@intel.com +9 -1 # Add VLAN support in ALB mode # # drivers/net/bonding/bond_alb.h # 2004/01/21 11:56:28-05:00 shmulik.hen@intel.com +2 -0 # Add VLAN support in ALB mode # # drivers/net/bonding/bond_alb.c # 2004/01/21 11:56:28-05:00 shmulik.hen@intel.com +81 -10 # Add VLAN support in ALB mode # # ChangeSet # 2004/02/18 18:59:27-05:00 shmulik.hen@intel.com # [PATCH] Add VLAN support in TLB mode # # Add capability to tag self generated learning packets that are # required to speed up port selection in the switch after a fail # over in bonding since some switches will only update their MAC # tables from tagged packets when VLAN support is turned on. All # VLAN Id's that have been configured on top of the bond interface # will be used in cyclic order. # # drivers/net/bonding/bonding.h # 2004/01/21 11:56:24-05:00 shmulik.hen@intel.com +1 -0 # Add VLAN support in TLB mode # # drivers/net/bonding/bond_main.c # 2004/01/21 11:56:24-05:00 shmulik.hen@intel.com +41 -0 # Add VLAN support in TLB mode # # drivers/net/bonding/bond_alb.h # 2004/01/21 11:56:24-05:00 shmulik.hen@intel.com +2 -1 # Add VLAN support in TLB mode # # drivers/net/bonding/bond_alb.c # 2004/01/21 11:56:24-05:00 shmulik.hen@intel.com +32 -2 # Add VLAN support in TLB mode # # ChangeSet # 2004/02/18 18:59:20-05:00 shmulik.hen@intel.com # [PATCH] Add support for HW accel. slaves # # Now that David Miller accepted the first half of this set into 2.6, # I'm resending the last half to you for inclusion in netdev-2.6. # # Tested against latest netdev-2.6. Summary: # # Change the bond interface to publish full VLAN hardware acceleration # offloading capabilities, and add capability in all xmit functions to # take special care for VLAN HW accel. tagged skb's that are going out # through a slave that is not offloading capable. # # Add a mechanism to collect and save the VLAN Id's that have been # added on top of a bond interface, and propagate the register/add/kill # operations to the slaves. # # Add blocking mechanism to prevent adding VLAN interfaces on top of a # bond that contains VLAN challenged slaves and to prevent adding VLAN # challenged slaves to a bond that already has VLAN interfaces on top # of it. # # Add a section about VLAN to Documentation/networking/bonding.txt and # also correct some minor spelling/grammer errors. # # drivers/net/bonding/bonding.h # 2004/01/21 11:56:19-05:00 shmulik.hen@intel.com +9 -0 # Add support for HW accel. slaves # # drivers/net/bonding/bond_main.c # 2004/01/21 11:56:19-05:00 shmulik.hen@intel.com +474 -62 # Add support for HW accel. slaves # # drivers/net/bonding/bond_alb.c # 2004/01/21 11:56:19-05:00 shmulik.hen@intel.com +8 -9 # Add support for HW accel. slaves # # drivers/net/bonding/bond_3ad.c # 2004/01/21 11:56:19-05:00 shmulik.hen@intel.com +12 -16 # Add support for HW accel. slaves # # Documentation/networking/bonding.txt # 2004/01/21 11:56:19-05:00 shmulik.hen@intel.com +40 -16 # Add support for HW accel. slaves # # ChangeSet # 2004/02/18 18:49:32-05:00 pe1rxq@amsat.org # [PATCH] 6pack reinit bug # # This patch is the same as to mkiss a while ago, the current code triggers a # bug when reattaching a network device. # # drivers/net/hamradio/6pack.c # 2004/02/06 13:32:46-05:00 pe1rxq@amsat.org +10 -10 # 6pack reinit bug # # ChangeSet # 2004/02/18 18:49:25-05:00 mlindner@syskonnect.de # [PATCH] [kernel 2.6] sk98lin: Insert revision version and date # # to uniquely identify the files, it's necessary to add the version of # each file. Please, don't remove the revision infos. It's really # important for us. # # Patch 2/2 # [SK98LIN]: Insert revision version and date [back] into the files # # drivers/net/sk98lin/skxmac2.c # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/skvpd.c # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/sktimer.c # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +3 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/skrlmt.c # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/skqueue.c # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +3 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/skproc.c # 2004/02/13 03:55:53-05:00 mlindner@syskonnect.de +2 -1 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/sklm80.c # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/ski2c.c # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/skgesirq.c # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/skgepnmi.c # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +3 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/skgemib.c # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/skgeinit.c # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -1 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/skgehwt.c # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/skdim.c # 2004/02/13 03:55:53-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/skcsum.c # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/skaddr.c # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/xmac_ii.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/skvpd.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/sktypes.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/sktimer.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/skrlmt.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/skqueue.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +6 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/ski2c.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/skgesirq.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/skgepnmi.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/skgepnm2.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/skgeinit.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/skgei2c.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/skgehwt.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/skgehw.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/skgedrv.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/skerror.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/skdrv1st.h # 2004/02/13 03:55:53-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/skdebug.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/skcsum.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/skaddr.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # drivers/net/sk98lin/h/lm80.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +2 -0 # [kernel 2.6] sk98lin: Insert revision version and date # # ChangeSet # 2004/02/18 18:49:16-05:00 mlindner@syskonnect.de # [PATCH] sk98lin: Added Support for Belkin adapter # # Patch 1/2 # [SK98LIN]: Added Support for Belkin adapter # [SK98LIN]: Don't handle Yukon2 cards at the moment # # drivers/net/sk98lin/skge.c # 2004/02/13 03:55:53-05:00 mlindner@syskonnect.de +8 -1 # [kernel 2.6] sk98lin: Added Support for Belkin adapter # # drivers/net/sk98lin/h/skversion.h # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +6 -4 # [kernel 2.6] sk98lin: Added Support for Belkin adapter # # drivers/net/sk98lin/h/skdrv2nd.h # 2004/02/13 03:55:53-05:00 mlindner@syskonnect.de +9 -1 # [kernel 2.6] sk98lin: Added Support for Belkin adapter # # drivers/net/Kconfig # 2004/02/13 03:55:51-05:00 mlindner@syskonnect.de +3 -0 # [kernel 2.6] sk98lin: Added Support for Belkin adapter # # Documentation/networking/sk98lin.txt # 2004/02/13 03:55:50-05:00 mlindner@syskonnect.de +3 -3 # [kernel 2.6] sk98lin: Added Support for Belkin adapter # # ChangeSet # 2004/02/18 18:49:09-05:00 brazilnut@us.ibm.com # [PATCH] 2.6.3 pcnet32.c SLAB_DEBUG length error fix # # The pcnet32 driver uses the incorrect length (of zero) in # pci_[un]map_single for receive buffers. This is seen with SLAB_DEBUG # enabled. # # Tested in IA32 system. If this patch is not applied after my previous # one hunks #1, #3, and #5 will have an offset of -2 lines. # # drivers/net/pcnet32.c # 2004/02/18 10:14:33-05:00 brazilnut@us.ibm.com +10 -7 # 2.6.3 pcnet32.c SLAB_DEBUG length error fix # # ChangeSet # 2004/02/18 18:49:02-05:00 shemminger@osdl.org # [PATCH] hp100 pci probe problem # # Jean discovered problem with my hp100 PCI changes. # This should fix the problem... The multi-bus probe logic error handling was # botched. # # He validated it; so please apply # # drivers/net/hp100.c # 2004/02/18 07:39:41-05:00 shemminger@osdl.org +16 -3 # hp100 pci probe problem # # ChangeSet # 2004/02/18 18:48:55-05:00 brazilnut@us.ibm.com # [PATCH] 2.6.3 pcnet32.c bus master arbitration failure fix # # Here is the first of several individual patches to 2.6.3 for the pcnet32 # driver. # # The driver did not properly serialize accesses to chip registers, resulting # in reading/writing the wrong register. This patch eliminates this problem # and gets rid of the cause of the symptom of 'bus master arbitration failure'. # # It was easier to use generic_mii_ioctl than modify the current pcnet32_ioctl # routine with the necessary locks. This has been re-tested on an IA32 system. # # drivers/net/pcnet32.c # 2004/02/18 07:35:33-05:00 brazilnut@us.ibm.com +24 -24 # 2.6.3 pcnet32.c bus master arbitration failure fix # # ChangeSet # 2004/02/18 15:26:52-08:00 johnstul@us.ibm.com # [PATCH] ia64: add support for time-interpolation via IBM EXA Cyclone timer # # This patch provides access to the cyclone time source found on IBM EXA # based systems (x450 and x455). This is needed on multi-node systems # where the CPU ITCs are not synchronized, causing possible time # inconsistencies. # # This release fixes one last minor think-o and ran overnight without any # time inconsistencies (when used in conjunction w/ the # time-interpolator-fix_A0 patch). # # include/asm-ia64/cyclone.h # 2004/02/18 07:10:58-08:00 johnstul@us.ibm.com +15 -0 # ia64: add support for time-interpolation via IBM EXA Cyclone timer # # include/asm-ia64/cyclone.h # 2004/02/18 07:10:58-08:00 johnstul@us.ibm.com +0 -0 # BitKeeper file /data1/bk/lia64/to-linus-2.5/include/asm-ia64/cyclone.h # # arch/ia64/kernel/acpi.c # 2004/02/18 07:10:58-08:00 johnstul@us.ibm.com +22 -0 # ia64: add support for time-interpolation via IBM EXA Cyclone timer # # arch/ia64/kernel/Makefile # 2004/02/18 07:10:58-08:00 johnstul@us.ibm.com +1 -0 # ia64: add support for time-interpolation via IBM EXA Cyclone timer # # arch/ia64/Kconfig # 2004/02/18 07:10:58-08:00 johnstul@us.ibm.com +6 -0 # ia64: add support for time-interpolation via IBM EXA Cyclone timer # # arch/ia64/kernel/cyclone.c # 2004/02/18 07:10:58-08:00 johnstul@us.ibm.com +158 -0 # ia64: add support for time-interpolation via IBM EXA Cyclone timer # # arch/ia64/kernel/cyclone.c # 2004/02/18 07:10:58-08:00 johnstul@us.ibm.com +0 -0 # BitKeeper file /data1/bk/lia64/to-linus-2.5/arch/ia64/kernel/cyclone.c # # ChangeSet # 2004/02/18 15:23:41-08:00 torvalds@home.osdl.org # Fix up the microcode update on regular 32-bit x86. Our wrmsr() # is a bit unforgiving and really doesn't like 64-bit values. # # We should possibly make wrmsr() automatically truncate the # arguments, but regardless we should just fix microcode.c. # # arch/i386/kernel/microcode.c # 2004/02/18 15:23:36-08:00 torvalds@home.osdl.org +3 -2 # Fix up the microcode update on regular 32-bit x86. Our wrmsr() # is a bit unforgiving and really doesn't like 64-bit values. # # We should possibly make wrmsr() automatically truncate the # arguments, but regardless we should just fix microcode.c. # # ChangeSet # 2004/02/18 15:05:21-08:00 stern@rowland.harvard.edu # [PATCH] USB: More UHCI root hub code improvements # # This adds some minor improvements to the UHCI root hub code. The only # important change is that it handles the overcurrent indicator bits on VIA # controllers properly; they are reported using the opposite sense from # Intel controllers. # # # # Report the OverCurrent status bits in the /proc debugging file # and spontaneously change the use of whitespace. # # Remove unused variable in uhci_hub_status_data(). # # Report OverCurrent status for VIA controllers properly (the # meaning of the status bit is inverted with respect to Intel # controllers). # # Save the port status I/O address in a variable rather than # recalculating it many times. # # Merge code for handling SetHubFeature and ClearHubFeature since # we don't implement either one. # # Remove some unnecessary comments. # # Remove redundant min_t calculation. # # drivers/usb/host/uhci-hub.c # 2004/02/18 06:50:31-08:00 stern@rowland.harvard.edu +26 -28 # USB: More UHCI root hub code improvements # # drivers/usb/host/uhci-debug.c # 2004/02/18 06:50:31-08:00 stern@rowland.harvard.edu +12 -10 # USB: More UHCI root hub code improvements # # ChangeSet # 2004/02/18 15:05:01-08:00 stern@rowland.harvard.edu # [PATCH] USB: Improve UHCI root hub code: descriptor, OC bits, etc. # # This patch is from David Brownell. # # UHCI root hub updates ... minor bugfixes and cleanups, improving # conformance with the USB hub specification. # # - UHCI doesn't support any kind of power switching; so modify the # hub descriptor to stop claiming it does! Likewise fail attempts # to disable power on any port. # # - Intel defined both overcurrent status overcurrent-change bits, but # the current code only knows about one. Modify hub descriptor to # report per-port overcurrent protection; and use both bits. # # - Modify the port status set/clear macros to know about the bits # that must always be written as zero, and the write-to-clear bits. # Update callers which wrote "set" instead of "clear". # # - Rewrote code returning port status; magic numbers are gone. # # - Driver can't really support 8 root hub ports; don't try. # # Also moves the #define DEBUG earlier so that it can kick in any of # the various debug macros ... like pr_debug() and dev_dbg(). # # drivers/usb/host/uhci-hub.c # 2004/02/18 05:56:23-08:00 stern@rowland.harvard.edu +62 -32 # USB: Improve UHCI root hub code: descriptor, OC bits, etc. # # drivers/usb/host/uhci-hcd.h # 2004/02/18 05:56:23-08:00 stern@rowland.harvard.edu +8 -1 # USB: Improve UHCI root hub code: descriptor, OC bits, etc. # # drivers/usb/host/uhci-hcd.c # 2004/02/18 05:56:23-08:00 stern@rowland.harvard.edu +6 -6 # USB: Improve UHCI root hub code: descriptor, OC bits, etc. # # ChangeSet # 2004/02/18 13:18:53-08:00 kaber@trash.net # [PKTSCHED]: Use queue limit of 1 when tx_queue_len is zero. # # net/sched/sch_gred.c # 2004/02/18 13:18:40-08:00 kaber@trash.net +1 -1 # [PKTSCHED]: Use queue limit of 1 when tx_queue_len is zero. # # net/sched/sch_fifo.c # 2004/02/18 13:18:40-08:00 kaber@trash.net +4 -2 # [PKTSCHED]: Use queue limit of 1 when tx_queue_len is zero. # # ChangeSet # 2004/02/18 13:17:51-08:00 david-b@pacbell.net # [PATCH] USB: ehci-hcd, scheduler handles TT collisions (3/3) # # [USB] ehci-hcd detects microframe transaction scheduling collisions # # This detects TT schedule collisions for split periodic transactions # on USB 2.0 hubs, handling both isochronous and interrupt transfers # but not supporting the "wrap around to the next frame" modes for # either transfer type. # # The ISO scheduler is modified to use that support for full speed # transfers ... though nothing will yet ask it to do that. # # It also tracks schedule depth, to help avoid accepting ISO URBs # which need more time than currently remains unscheduled. # # drivers/usb/host/ehci.h # 2004/02/16 07:09:31-08:00 david-b@pacbell.net +5 -1 # USB: ehci-hcd, scheduler handles TT collisions (3/3) # # drivers/usb/host/ehci-sched.c # 2004/02/16 07:09:32-08:00 david-b@pacbell.net +262 -52 # USB: ehci-hcd, scheduler handles TT collisions (3/3) # # ChangeSet # 2004/02/18 13:17:29-08:00 david-b@pacbell.net # [PATCH] USB: ehci-hcd, fullspeed iso data structures (2/3) # # [USB] ehci, rename some iso data structures # # Rename some data and functions used by EHCI to manage ISO transactions, # since they currently assume only high speed transfers. Much of the same # infrastructure will be used for full speed ISO, with split transactions. # # drivers/usb/host/ehci-sched.c # 2004/02/13 09:47:20-08:00 david-b@pacbell.net +70 -66 # USB: ehci-hcd, fullspeed iso data structures (2/3) # # drivers/usb/host/ehci.h # 2004/02/13 09:42:00-08:00 david-b@pacbell.net +14 -11 # USB: ehci-hcd, fullspeed iso data structures (2/3) # # ChangeSet # 2004/02/18 13:17:05-08:00 david-b@pacbell.net # [PATCH] USB: ehci-hcd, fullspeed iso data structures (1/3) # # [USB] start ehci split transaction support # # Updates split ISO transaction descriptor structure, add bitmask #defines; # it's groundwork for full speed ISO support in EHCI. Updates periodic # schedule scanning, and bandwidth calculations accordingly. # # Fixes bandwidth calculation to behave when the periodic schedule has # entries of multiple types ... as will be more common as ISO support # starts to be used here. # # drivers/usb/host/ehci.h # 2004/02/12 12:40:15-08:00 david-b@pacbell.net +26 -13 # USB: ehci-hcd, fullspeed iso data structures (1/3) # # drivers/usb/host/ehci-sched.c # 2004/02/12 12:32:50-08:00 david-b@pacbell.net +27 -15 # USB: ehci-hcd, fullspeed iso data structures (1/3) # # ChangeSet # 2004/02/18 13:16:10-08:00 davem@nuts.davemloft.net # [DECNET]: Make second arg to dn_alloc_send_skb a size_t pointer. # # net/decnet/dn_nsp_out.c # 2004/02/18 13:15:52-08:00 davem@nuts.davemloft.net +1 -1 # [DECNET]: Make second arg to dn_alloc_send_skb a size_t pointer. # # include/net/dn_nsp.h # 2004/02/18 13:15:52-08:00 davem@nuts.davemloft.net +1 -1 # [DECNET]: Make second arg to dn_alloc_send_skb a size_t pointer. # # ChangeSet # 2004/02/18 13:13:22-08:00 davem@nuts.davemloft.net # [BLUETOOTH]: Use min_t to avoid warning in rfcomm sock.c # # net/bluetooth/rfcomm/sock.c # 2004/02/18 13:13:06-08:00 davem@nuts.davemloft.net +1 -1 # [BLUETOOTH]: Use min_t to avoid warning in rfcomm sock.c # # ChangeSet # 2004/02/18 13:13:04-08:00 david-b@pacbell.net # [PATCH] USB: usbtest, two more protocol cases # # [USB] usbtest, two more control queueing subtests # # From Alan Stern. This adds two more "short control read" test cases, # both padding the "expected" transfer to end-of-packet. We need both # hosts and devices/gadgets to behave correctly here. # # drivers/usb/misc/usbtest.c # 2004/02/15 04:37:32-08:00 david-b@pacbell.net +18 -1 # USB: usbtest, two more protocol cases # # ChangeSet # 2004/02/18 13:12:46-08:00 david-b@pacbell.net # [PATCH] USB: usbcore, avoid RNDIS configs # # [USB] usbcore avoids RNDIS configuration. # # Modifies the "choose a configuration" heuristic to recognize the other # case that 2.4 handled: RNDIS, a MSFT protocol that's sometimes used as # the first/default configuration (as specified by MSFT) on cable modems. # CDC Ethernet is vendor-neutral, and preferred (except by MSFT). # # The initial version didn't catch RNDIS because it cloaks its ethernet # links as a kind of CDC ACM (modem) device. # # drivers/usb/core/usb.c # 2004/02/18 02:55:27-08:00 david-b@pacbell.net +10 -3 # USB: usbcore, avoid RNDIS configs # # ChangeSet # 2004/02/18 13:12:22-08:00 david-b@pacbell.net # [PATCH] USB: usbcore, hub driver enables TT-per-port mode # # [USB] hub driver turns on multi-TT mode # # This turns on the multi-tt mode in hubs that support it; the Cypress # "TetraHub" products are appearing at retail now, complete with some # of the first Mini-B connectors I've seen shipping. # # This will be important for hooking up lots of full speed isochronous # devices (audio, video, etc). # # drivers/usb/core/hub.c # 2004/02/18 03:00:29-08:00 david-b@pacbell.net +7 -2 # USB: usbcore, hub driver enables TT-per-port mode # # ChangeSet # 2004/02/18 13:11:47-08:00 david-b@pacbell.net # [PATCH] USB: usbcore, scatterlist cleanups # # [USB] minor usb_sg_wait() cleanups # # - count urb completions correctly when there's a non-recoverable # fault during scatterlist submission ... prevents a hang (seen # only with already-faulty usb-storage devices). # # - don't local_irq_{save,restore}() when not needed # # ChangeSet # 2004/02/18 13:11:42-08:00 davem@nuts.davemloft.net # [APPLETALK]: Use '%Z' for size_t. # # drivers/usb/core/message.c # 2004/01/12 05:05:56-08:00 david-b@pacbell.net +16 -10 # USB: usbcore, scatterlist cleanups # # net/appletalk/ddp.c # 2004/02/18 13:11:23-08:00 davem@nuts.davemloft.net +2 -2 # [APPLETALK]: Use '%Z' for size_t. # # ChangeSet # 2004/02/18 13:06:55-08:00 wensong@linux-vs.org # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_xmit.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +0 -3 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_wrr.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +0 -4 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_wlc.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +0 -4 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_sync.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +0 -5 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_sh.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +0 -4 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_sed.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +0 -4 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_sched.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +0 -3 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_rr.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +0 -4 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_proto_tcp.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +1 -2 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_proto_icmp.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +0 -5 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_proto_esp.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +0 -5 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_proto_ah.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +0 -5 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_proto.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +0 -4 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_nq.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +0 -4 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_lc.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +0 -4 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_lblcr.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +2 -6 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_lblc.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +2 -6 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_ftp.c # 2004/02/18 13:03:53-08:00 wensong@linux-vs.org +0 -4 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_dh.c # 2004/02/18 13:03:52-08:00 wensong@linux-vs.org +0 -4 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_ctl.c # 2004/02/18 13:03:52-08:00 wensong@linux-vs.org +0 -3 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_core.c # 2004/02/18 13:03:52-08:00 wensong@linux-vs.org +0 -4 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_conn.c # 2004/02/18 13:03:52-08:00 wensong@linux-vs.org +0 -3 # [IPVS] tidy up the header files to include # # net/ipv4/ipvs/ip_vs_app.c # 2004/02/18 13:03:52-08:00 wensong@linux-vs.org +0 -6 # [IPVS] tidy up the header files to include # # ChangeSet # 2004/02/18 11:54:48-08:00 pfg@sgi.com # [PATCH] ia64: add "platform_data" to struct pci_controller, update SN2 accordingly # # Here's a small mod for Altix. It breaks up our 'pci fixup' function and # has some other smallish clean ups. # # For the ia64 crowd I've added 'platform_data' to struct pci_controller. # # include/asm-ia64/sn/pci/pci_bus_cvlink.h # 2004/02/05 02:17:40-08:00 pfg@sgi.com +9 -5 # ia64: add "platform_data" to struct pci_controller, update SN2 accordingly # # include/asm-ia64/pci.h # 2004/02/05 02:17:40-08:00 pfg@sgi.com +2 -0 # ia64: add "platform_data" to struct pci_controller, update SN2 accordingly # # arch/ia64/sn/io/sn2/pic.c # 2004/02/05 02:17:40-08:00 pfg@sgi.com +8 -0 # ia64: add "platform_data" to struct pci_controller, update SN2 accordingly # # arch/ia64/sn/io/machvec/pci_dma.c # 2004/02/05 02:17:40-08:00 pfg@sgi.com +3 -3 # ia64: add "platform_data" to struct pci_controller, update SN2 accordingly # # arch/ia64/sn/io/machvec/pci_bus_cvlink.c # 2004/02/05 02:17:40-08:00 pfg@sgi.com +248 -163 # ia64: add "platform_data" to struct pci_controller, update SN2 accordingly # # ChangeSet # 2004/02/18 11:47:46-08:00 maeda.naoaki@jp.fujitsu.com # [PATCH] ia64: fix possible memory leak in PCI alloc_resource() # # # arch/ia64/pci/pci.c # 2004/02/17 23:36:14-08:00 maeda.naoaki@jp.fujitsu.com +3 -1 # ia64: fix possible memory leak in PCI alloc_resource() # # ChangeSet # 2004/02/18 11:44:46-08:00 ak@suse.de # [PATCH] Allow P4 oprofile code for x86-64 # # P4 support was previously ifdefed out for x86-64, remove that. # # arch/i386/oprofile/nmi_int.c # 2004/02/17 18:14:37-08:00 ak@suse.de +0 -7 # Allow P4 oprofile code for x86-64 # # ChangeSet # 2004/02/18 11:44:38-08:00 ak@suse.de # [PATCH] Enable Intel AGP on x86-64 # # Enable the Intel AGP driver for x86-64 too. # # drivers/char/agp/Kconfig # 2004/02/17 18:14:37-08:00 ak@suse.de +1 -1 # Enable Intel AGP on x86-64 # # ChangeSet # 2004/02/18 11:44:30-08:00 ak@suse.de # [PATCH] Update i386 microcode driver for x86-64 # # The microcode driver needs to support 64bit physical addresses too. # # arch/i386/kernel/microcode.c # 2004/02/17 18:14:37-08:00 ak@suse.de +2 -1 # Update i386 microcode driver for x86-64 # # ChangeSet # 2004/02/18 11:44:21-08:00 ak@suse.de # [PATCH] Intel x86-64 support merge # # This has all the x86-64 specific changes for Intel Prescott/Nocona # support. # # It requires a few minor changes outside arch/x86_64, which I am sending # separately. # # This patch is needed to boot an 64bit kernel on a 64-bit capable # Prescott machine. # # The ugliest part is probably the swiotlb code. In fact the code for # that is not even included, but just reused from IA64. swiotlb # implements the PCI DMA API using bounce buffering. I don't like this at # all, but there was no other way to support non DAC capable hardware # (like IDE or USB) on machines with >3GB. Please redirect all flames for # that to the Intel chipset designers. # # ChangeLog: # - Add Kconfig options for PSC # - Add support to reuse microcode driver from i386 (Suresh B Siddha) # - Try to optimize for the selected CPU # - Fix early CPUID check for Intel CPUs (Suresh B Siddha) # - Fix GDT to use the configured cache line size for padding # - Support monitor/mwait idle loop # - Support HyperThreading # - Support Intel CPUID flags # - Remove all 3dnow prefetches # - Add alternative() for the prefetchw prefetch inline. # - Include P4 driver in oprofile # - Support Intel NOPs in alternative # # include/asm-x86_64/system.h # 2004/02/17 18:14:37-08:00 ak@suse.de +50 -0 # Intel x86-64 support merge # # include/asm-x86_64/smp.h # 2004/02/17 18:14:37-08:00 ak@suse.de +2 -1 # Intel x86-64 support merge # # include/asm-x86_64/segment.h # 2004/02/17 18:14:37-08:00 ak@suse.de +3 -1 # Intel x86-64 support merge # # include/asm-x86_64/proto.h # 2004/02/17 18:14:37-08:00 ak@suse.de +5 -0 # Intel x86-64 support merge # # include/asm-x86_64/processor.h # 2004/02/17 18:14:37-08:00 ak@suse.de +86 -35 # Intel x86-64 support merge # # include/asm-x86_64/pci.h # 2004/02/17 18:14:37-08:00 ak@suse.de +32 -0 # Intel x86-64 support merge # # include/asm-x86_64/msr.h # 2004/02/17 18:14:37-08:00 ak@suse.de +122 -0 # Intel x86-64 support merge # # include/asm-x86_64/cpufeature.h # 2004/02/17 18:14:37-08:00 ak@suse.de +7 -2 # Intel x86-64 support merge # # arch/x86_64/oprofile/Makefile # 2004/02/17 18:14:37-08:00 ak@suse.de +3 -3 # Intel x86-64 support merge # # arch/x86_64/mm/init.c # 2004/02/17 18:14:37-08:00 ak@suse.de +7 -0 # Intel x86-64 support merge # # arch/x86_64/lib/csum-copy.S # 2004/02/17 18:14:37-08:00 ak@suse.de +1 -12 # Intel x86-64 support merge # # arch/x86_64/lib/copy_page.S # 2004/02/17 18:14:37-08:00 ak@suse.de +1 -8 # Intel x86-64 support merge # # arch/x86_64/kernel/x8664_ksyms.c # 2004/02/17 18:14:37-08:00 ak@suse.de +2 -0 # Intel x86-64 support merge # # arch/x86_64/kernel/smpboot.c # 2004/02/17 18:14:37-08:00 ak@suse.de +34 -0 # Intel x86-64 support merge # # arch/x86_64/kernel/setup.c # 2004/02/17 18:14:37-08:00 ak@suse.de +212 -5 # Intel x86-64 support merge # # arch/x86_64/kernel/process.c # 2004/02/17 18:14:37-08:00 ak@suse.de +46 -0 # Intel x86-64 support merge # # arch/x86_64/kernel/pci-gart.c # 2004/02/17 18:14:37-08:00 ak@suse.de +30 -2 # Intel x86-64 support merge # # arch/x86_64/kernel/head.S # 2004/02/17 18:14:37-08:00 ak@suse.de +7 -12 # Intel x86-64 support merge # # arch/x86_64/kernel/aperture.c # 2004/02/17 18:14:37-08:00 ak@suse.de +4 -0 # Intel x86-64 support merge # # arch/x86_64/kernel/Makefile # 2004/02/17 18:14:37-08:00 ak@suse.de +4 -1 # Intel x86-64 support merge # # arch/x86_64/boot/setup.S # 2004/02/17 18:14:37-08:00 ak@suse.de +16 -6 # Intel x86-64 support merge # # arch/x86_64/Makefile # 2004/02/17 19:42:21-08:00 ak@suse.de +4 -0 # Intel x86-64 support merge # # arch/x86_64/Kconfig # 2004/02/17 18:14:37-08:00 ak@suse.de +34 -3 # Intel x86-64 support merge # # ChangeSet # 2004/02/18 08:56:10-08:00 torvalds@home.osdl.org # Merge bk://kernel.bkbits.net/davem/net-2.6 # into home.osdl.org:/home/torvalds/v2.5/linux # # net/ipv6/ip6_tunnel.c # 2004/02/18 08:56:08-08:00 torvalds@home.osdl.org +0 -0 # Auto merged # # ChangeSet # 2004/02/17 23:01:27-08:00 mbligh@aracnet.com # [NET]: Ditch TSO in loopback driver, it's had enough testing. # # drivers/net/loopback.c # 2004/02/17 22:58:03-08:00 mbligh@aracnet.com +1 -1 # [NET]: Ditch TSO in loopback driver, it's had enough testing. # # ChangeSet # 2004/02/17 19:16:03-08:00 davem@nuts.davemloft.net # Merge http://linux-lksctp.bkbits.net/lksctp-2.5.work # into nuts.davemloft.net:/disk1/BK/net-2.6 # # net/sctp/Kconfig # 2004/02/17 19:15:56-08:00 davem@nuts.davemloft.net +0 -0 # Auto merged # # ChangeSet # 2004/02/17 19:06:26-08:00 ja@ssi.bg # [IPV4]: Add sophisticated ARP reply control via arp_ignore sysctl. # # net/ipv4/devinet.c # 2004/02/17 19:03:26-08:00 ja@ssi.bg +87 -1 # [IPV4]: Add sophisticated ARP reply control via arp_ignore sysctl. # # net/ipv4/arp.c # 2004/02/17 19:03:26-08:00 ja@ssi.bg +42 -2 # [IPV4]: Add sophisticated ARP reply control via arp_ignore sysctl. # # include/linux/sysctl.h # 2004/02/17 19:03:26-08:00 ja@ssi.bg +1 -0 # [IPV4]: Add sophisticated ARP reply control via arp_ignore sysctl. # # include/linux/inetdevice.h # 2004/02/17 19:03:26-08:00 ja@ssi.bg +3 -0 # [IPV4]: Add sophisticated ARP reply control via arp_ignore sysctl. # # Documentation/networking/ip-sysctl.txt # 2004/02/17 19:03:26-08:00 ja@ssi.bg +18 -0 # [IPV4]: Add sophisticated ARP reply control via arp_ignore sysctl. # # ChangeSet # 2004/02/17 17:37:27-08:00 sri@us.ibm.com # [SCTP] Force enable Crypto options that are needed by SCTP config. # # net/sctp/Kconfig # 2004/02/17 17:37:13-08:00 sri@us.ibm.com +8 -2 # [SCTP] Force enable Crypto options that are needed by SCTP config. # # ChangeSet # 2004/02/17 17:16:30-08:00 dsaxena@plexity.net # [PATCH] USB: Fix USB host code to use generic DMA API # # drivers/usb/host/uhci-hcd.h # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +2 -2 # USB: Fix USB host code to use generic DMA API # # drivers/usb/host/uhci-hcd.c # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +25 -20 # USB: Fix USB host code to use generic DMA API # # drivers/usb/host/ohci.h # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +6 -6 # USB: Fix USB host code to use generic DMA API # # drivers/usb/host/ohci-sa1111.c # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +6 -10 # USB: Fix USB host code to use generic DMA API # # drivers/usb/host/ohci-q.c # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +2 -2 # USB: Fix USB host code to use generic DMA API # # drivers/usb/host/ohci-pci.c # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +24 -21 # USB: Fix USB host code to use generic DMA API # # drivers/usb/host/ohci-omap.c # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +4 -8 # USB: Fix USB host code to use generic DMA API # # drivers/usb/host/ohci-mem.c # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +10 -10 # USB: Fix USB host code to use generic DMA API # # drivers/usb/host/ohci-hcd.c # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +6 -2 # USB: Fix USB host code to use generic DMA API # # drivers/usb/host/ehci.h # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +5 -5 # USB: Fix USB host code to use generic DMA API # # drivers/usb/host/ehci-sched.c # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +2 -2 # USB: Fix USB host code to use generic DMA API # # drivers/usb/host/ehci-q.c # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +1 -1 # USB: Fix USB host code to use generic DMA API # # drivers/usb/host/ehci-mem.c # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +22 -18 # USB: Fix USB host code to use generic DMA API # # drivers/usb/host/ehci-hcd.c # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +10 -8 # USB: Fix USB host code to use generic DMA API # # drivers/usb/host/ehci-dbg.c # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +5 -5 # USB: Fix USB host code to use generic DMA API # # drivers/usb/core/hcd.h # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +2 -5 # USB: Fix USB host code to use generic DMA API # # drivers/usb/core/hcd.c # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +20 -18 # USB: Fix USB host code to use generic DMA API # # drivers/usb/core/hcd-pci.c # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +16 -15 # USB: Fix USB host code to use generic DMA API # # drivers/usb/core/buffer.c # 2004/02/11 03:42:39-08:00 dsaxena@plexity.net +14 -9 # USB: Fix USB host code to use generic DMA API # # ChangeSet # 2004/02/17 20:06:21-05:00 jgarzik@redhat.com # Merge redhat.com:/spare/repo/netdev-2.6/netdev-alloc-6 # into redhat.com:/spare/repo/netdev-2.6/netdev-alloc-7 # # net/ipv6/sit.c # 2004/02/17 20:06:10-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # net/ipv4/ipip.c # 2004/02/17 20:06:10-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # net/ipv4/ip_gre.c # 2004/02/17 20:06:10-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/usb/net/usbnet.c # 2004/02/17 20:06:10-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/02/17 20:03:31-05:00 jgarzik@redhat.com # Hand-merge pc300_tty.c conflicts with netdev. # # drivers/net/wan/pc300_tty.c # 2004/02/17 20:03:26-05:00 jgarzik@redhat.com +2 -4 # Hand-merge pc300_tty.c conflicts with netdev. # # ChangeSet # 2004/02/17 16:47:56-08:00 stern@rowland.harvard.edu # [PATCH] USB Storage: unusual_devs.h fixup # # On 15 Feb 2004, Frank D. Cringle wrote: # # > Hi, # > # > my syslog requests that I send this message. See below regarding # > usb-storage: This device ... has an unneeded SubClass entry in unusual_devs.h # # > Feb 15 00:11:16 dagger usb-storage: This device (07cf,1001,1000 S 05 P 00) has an unneeded SubClass entry in unusual_devs.h # > Feb 15 00:11:16 dagger Please send a copy of this message to # # Thank you for sending this in. # # Greg, it looks like an earlier patch changed too much. Here is the fix. # Also included in this patch: # # Moved several entries that were in the wrong positions. # # Removed an entry (0x08ca, 0x2011) that could never be used # because the preceding entry always would take precedence. # # drivers/usb/storage/unusual_devs.h # 2004/02/17 08:45:59-08:00 stern@rowland.harvard.edu +32 -32 # USB Storage: unusual_devs.h fixup # # ChangeSet # 2004/02/17 16:45:15-08:00 mdharm-usb@one-eyed-alien.net # [PATCH] USB Storage: Fix small endian-ness bug # # This patch fixes up a small endian-ness bug from mid-January. # # drivers/usb/storage/sddr09.c # 2004/02/16 06:42:57-08:00 mdharm-usb@one-eyed-alien.net +1 -1 # USB Storage: Fix small endian-ness bug # # ChangeSet # 2004/02/17 16:45:00-08:00 mdharm-usb@one-eyed-alien.net # [PATCH] USB Storage: Reduce unsolicited auto-sense # # This patch (a regeneration of as185) reduces the amount of auto-sensing we # do even further. It also zeros-out the sense buffer in those cases where # we do auto-sense and get back no error. # # drivers/usb/storage/transport.c # 2004/02/14 13:38:17-08:00 mdharm-usb@one-eyed-alien.net +12 -22 # USB Storage: Reduce unsolicited auto-sense # # ChangeSet # 2004/02/17 16:44:43-08:00 mdharm-usb@one-eyed-alien.net # [PATCH] USB Storage: Save the SCSI residue value when auto-sensing # # This patch (a regeneration of as173) saves the residue value of a command # when doing an auto-sense. # # Not that it really matters much -- almost nobody looks at that value. But # it's definately incorrect the way it is, and this fixes it. # # drivers/usb/storage/transport.c # 2004/02/14 13:28:40-08:00 mdharm-usb@one-eyed-alien.net +4 -0 # USB Storage: Save the SCSI residue value when auto-sensing # # ChangeSet # 2004/02/17 16:44:27-08:00 stern@rowland.harvard.edu # [PATCH] USB Storage: Reduce auto-sensing for CB transport # # This patch addresses a problem common among digital cameras that use the # CB transport. Namely, too much auto-sensing confuses them; particularly # auto-sensing after INQUIRY. # # I've made some traces of a Windows 2000 driver to see what it does (data # sent to Andries Brouwer for inclusion on his web site; I'll announce # when it's ready for viewing). Basically, it almost never sends REQUEST # SENSE unless it received a STALL from the device. # # That's a pretty bogus way to operate, because it means that Windows has no # way to tell when the device has finished executing a command if the # command doesn't involve an IN transfer. Even after a lengthy WRITE, # Windows continues to transmit more commands without regard for whether or # not they will get overwritten in the device's internal buffer (and hence # not executed). Indeed, exactly that happened with some of the commands in # one of my traces. # # To be safe, we must follow every non-IN transfer with an auto-sense, but # IN transfers that don't stall can be considered to have succeeded. # That's what this patch does. It reduces auto-sensing by a considerable # factor, probably close to half. It also fixes the problem with INQUIRY, # since INQUIRY involves an IN data transfer. # # drivers/usb/storage/transport.c # 2004/01/12 06:48:57-08:00 stern@rowland.harvard.edu +5 -14 # USB Storage: Reduce auto-sensing for CB transport # # ChangeSet # 2004/02/17 16:44:14-08:00 stern@rowland.harvard.edu # [PATCH] USB Storage: Treat STALL as failure for CB[I] # # I recall something like this had to be changed a while ago, but it looks # like it's still not right. A STALL during either the command or data # phase of a CB[I] command should indicate a failure. # # drivers/usb/storage/transport.c # 2003/12/17 02:34:28-08:00 stern@rowland.harvard.edu +8 -0 # USB Storage: Treat STALL as failure for CB[I] # # ChangeSet # 2004/02/17 16:43:54-08:00 stern@rowland.harvard.edu # [PATCH] USB Storage: Handle excess 0-length data packets # # This patch is an attempt to cope with Genesys Logic's, shall we say, # creative approach to implementing the USB protocols. Their high-speed # mass storage devices sometimes add an excess 0-length packet to the end of # a data phase transmission. Of course we don't read that packet as part of # the data phase; we see it as a 0-length CSW message. The real CSW follows # immediately after. (Or sometimes a STALL follows immediately after, with # the real CSW coming after that!) # # The patch checks the results of the first attempt to read the CSW. If it # sees a normal packet (not a STALL) with length 0, it retries the read. # Reports from two users indicate that it improves the performance of their # USB-2 DVD drives. # # drivers/usb/storage/transport.c # 2003/12/15 07:11:03-08:00 stern@rowland.harvard.edu +12 -1 # USB Storage: Handle excess 0-length data packets # # ChangeSet # 2004/02/17 16:22:07-08:00 stern@rowland.harvard.edu # [PATCH] USB: Mask "HC Halted" bit in the UHCI status register # # Contrary to the UHCI specification document, in real controllers the "HC # Halted" bit in the status register cannot be cleared by writing a 1. It # will persist for as long as the controller is halted. Hence the bit needs # to be masked away before checking whether or not the controller initiated # an interrupt. # # Without this patch, other devices sharing the same IRQ line might not get # serviced while the host controller is suspended, because the always-on # status bit would cause the UHCI driver to report that it had handled the # interrupt. # # drivers/usb/host/uhci-hcd.c # 2004/02/17 08:44:58-08:00 stern@rowland.harvard.edu +3 -2 # USB: Mask "HC Halted" bit in the UHCI status register # # ChangeSet # 2004/02/17 16:21:51-08:00 stern@rowland.harvard.edu # [PATCH] USB: Simplify locking in UHCI # # This patch is an amalgam of 9 contributions from Stephen Hemminger. It # begins the process of straightening out the use of semaphores and locking # in the UHCI driver by removing unneeded irqsaves and irqrestores. It # also removes an unnecessary list node and makes a couple of other small # changes. # # # # clear_next_interrupt only called in IRQ context don't need irqsave/restore # # Since uhci_finish_completion is only called from IRQ routine, # the irqsave/irqrestore is redundant and unnecessary. # # UHCI transfer_result is only called from IRQ context # so irqsave/restore is unnecessary here. # # uhci_finish_urb is always called from irq so # no need for irqsave/irqrestore. # # uhci_add_complete only called from IRQ context # # The complete_list element in the urb private data is redundant, # since it is only used when the urb is on the complete list. # And given the state transitions, an urb can't be on the complete list # and any other list (remove, or urb_list). # Therefore just use urb_list to link the complete_list # # Use list_move_tail to move between remove (or urb_list) and the complete_list. # # Save irq state in uhci_stop so that the irqsave/irqrestore's # in all the free_pending and remove_pending code can be eliminated. # # Since uhci_stop now saves IRQ state, the free/remove pending routines # no longer need irqsave/irqrestore. # # drivers/usb/host/uhci-hcd.h # 2004/02/17 07:37:36-08:00 stern@rowland.harvard.edu +0 -1 # USB: Simplify locking in UHCI # # drivers/usb/host/uhci-hcd.c # 2004/02/17 07:40:25-08:00 stern@rowland.harvard.edu +30 -45 # USB: Simplify locking in UHCI # # drivers/usb/host/uhci-debug.c # 2004/02/17 07:37:36-08:00 stern@rowland.harvard.edu +1 -1 # USB: Simplify locking in UHCI # # ChangeSet # 2004/02/17 16:21:33-08:00 stern@rowland.harvard.edu # [PATCH] USB: ERRBUF_LEN compiling error when PAGE_SIZE=64KB on IA64 # # Randy, thanks for forwarding this to me. # # > Johannes, # > # > When I compile base kernel 2.6.1 with PAGE_SIZE=64KB on an IA64 # > platform, there is an error. # > CC init/version.o # > LD init/built-in.o # > LD .tmp_vmlinux1 # > drivers/built-in.o(.init.text+0x168a2): In function `uhci_hcd_init': # > : undefined reference to `__you_cannot_kmalloc_that_much' # > make: *** [.tmp_vmlinux1] Error 1 # > # > That's because ERRBUF_LEN (equal to PAGE_SIZE*8) is too long when # > PAGE_SIZE=64KB. Actually, there was a similar error found by Tony. See # > http://marc.theaimsgroup.com/?l=linux-ia64&m=105604765306485&w=2. # > # > Could you change the definition of ERRBUF_LEN to a fixed value? For # > example, 32*1024? # > # > Yanmin # # Yanmin, I'm the new maintainer for the UHCI driver. Yep, that's a # definite error. This will fix it. # # Also included in this patch: change some confusing references from "high # speed" to "full speed" and add proper hyphenation. # # drivers/usb/host/uhci-hcd.h # 2004/02/16 06:41:17-08:00 stern@rowland.harvard.edu +6 -6 # USB: ERRBUF_LEN compiling error when PAGE_SIZE=64KB on IA64 # # drivers/usb/host/uhci-hcd.c # 2004/02/16 06:41:17-08:00 stern@rowland.harvard.edu +6 -6 # USB: ERRBUF_LEN compiling error when PAGE_SIZE=64KB on IA64 # # ChangeSet # 2004/02/17 16:21:17-08:00 stern@rowland.harvard.edu # [PATCH] USB: Even out distribution of UHCI interrupt transfers # # This patch evens out the distribution of interrupt transfers for the UHCI # driver. It insures that no frame must handle interrupt queues for more # than two different periods, thus improving the bandwidth utilization. # # It also simplifies the initialization code by replacing a multi-nested # "if" statement with a simple bit-operation (thanks to Eric Piel for # suggesting this approach). # # ChangeSet # 2004/02/17 16:21:15-08:00 davem@nuts.davemloft.net # [TG3]: Bump driver version and reldate. # # drivers/usb/host/uhci-hcd.c # 2004/02/16 06:26:19-08:00 stern@rowland.harvard.edu +31 -35 # USB: Even out distribution of UHCI interrupt transfers # # drivers/usb/host/uhci-debug.c # 2004/02/16 06:26:19-08:00 stern@rowland.harvard.edu +4 -3 # USB: Even out distribution of UHCI interrupt transfers # # drivers/net/tg3.c # 2004/02/17 16:21:03-08:00 davem@nuts.davemloft.net +2 -2 # [TG3]: Bump driver version and reldate. # # ChangeSet # 2004/02/17 16:20:54-08:00 stern@rowland.harvard.edu # [PATCH] USB: Remove unneeded and error-provoking variable in UHCI # # This patch removes an unneeded "status" field from the UHCI driver's # URB-private data structure. The driver had been storing the status of # completed URBs there rather than in the URBs themselves. This not only is # wasteful of space but is also a cause of bugs, since the USB core relies # on urb->status for proper synchronization with the driver. # # The patch also takes care of a number of small things that have been # bugging me for ages: # # Close a small loophole by allowing an URB to be unlinked even # before the uhci_urb_enqueue() procedure has started. # # Remove some fossil code from back when interrupt URBs were # automagically resubmitted. # # Giveback unlinked URBs in the order they were unlinked. # # Don't set urb->status for dequeued URBs; the core has already # set it for us. # # Rename uhci_remove_pending_qhs to uhci_remove_pending_urbps. # (That has _really_ bothered me!) # # drivers/usb/host/uhci-hcd.h # 2004/02/10 07:48:36-08:00 stern@rowland.harvard.edu +0 -2 # USB: Remove unneeded and error-provoking variable in UHCI # # drivers/usb/host/uhci-hcd.c # 2004/02/10 08:29:52-08:00 stern@rowland.harvard.edu +15 -35 # USB: Remove unneeded and error-provoking variable in UHCI # # drivers/usb/host/uhci-debug.c # 2004/02/10 07:48:02-08:00 stern@rowland.harvard.edu +2 -2 # USB: Remove unneeded and error-provoking variable in UHCI # # ChangeSet # 2004/02/17 16:17:02-08:00 davem@nuts.davemloft.net # [TG3]: Fix early chip programming in tg3_setup_copper_phy(). # # 1) First action must be to set MAC_EVENT to zero. # 2) Do not forget to clear MI_COMPLETION/LNKSTATE_CHANGED # status bits in MAC_STATUS register. # # This fixes the bug wherein the link does not come up at all # at the first ifup done after tg3 module load. # # drivers/net/tg3.c # 2004/02/17 16:16:50-08:00 davem@nuts.davemloft.net +5 -1 # [TG3]: Fix early chip programming in tg3_setup_copper_phy(). # # 1) First action must be to set MAC_EVENT to zero. # 2) Do not forget to clear MI_COMPLETION/LNKSTATE_CHANGED # status bits in MAC_STATUS register. # # This fixes the bug wherein the link does not come up at all # at the first ifup done after tg3 module load. # # ChangeSet # 2004/02/17 16:10:36-08:00 domen@coderock.org # [PATCH] USB: some stv680 fixes # # - swapRGB is already initialized to 0 # - change "swapRGB_on == 1" to match in-source documentation # - submit urb with GFP_ATOMIC (interrupt context) - this made driver # unusable because of "might_sleep" messages. # - group some "case"s # - release vdev on fail # - remove "kfree(0)" checking # # drivers/usb/media/stv680.c # 2004/02/15 07:55:26-08:00 domen@coderock.org +6 -10 # USB: some stv680 fixes # # ChangeSet # 2004/02/17 16:08:12-08:00 davem@nuts.davemloft.net # [TG3]: Two more PHY bug workaround, plus fix DMA test on big-endian. # # drivers/net/tg3.h # 2004/02/17 16:08:00-08:00 davem@nuts.davemloft.net +5 -0 # [TG3]: Two more PHY bug workaround, plus fix DMA test on big-endian. # # drivers/net/tg3.c # 2004/02/17 16:08:00-08:00 davem@nuts.davemloft.net +20 -2 # [TG3]: Two more PHY bug workaround, plus fix DMA test on big-endian. # # ChangeSet # 2004/02/16 22:49:24-08:00 dlstevens@us.ibm.com # [IPV6]: Add sysctl to force MLD version. # # net/ipv6/mcast.c # 2004/02/16 22:49:11-08:00 dlstevens@us.ibm.com +4 -2 # [IPV6]: Add sysctl to force MLD version. # # net/ipv6/addrconf.c # 2004/02/16 22:49:11-08:00 dlstevens@us.ibm.com +11 -1 # [IPV6]: Add sysctl to force MLD version. # # include/linux/sysctl.h # 2004/02/16 22:49:11-08:00 dlstevens@us.ibm.com +2 -1 # [IPV6]: Add sysctl to force MLD version. # # include/linux/ipv6.h # 2004/02/16 22:49:11-08:00 dlstevens@us.ibm.com +2 -0 # [IPV6]: Add sysctl to force MLD version. # # ChangeSet # 2004/02/16 16:59:10-08:00 abbotti@mev.co.uk # [PATCH] USB: ftdi_sio new PIDs and name fix for sysfs # # This patch adds a couple of new PIDs for the ftdi_sio driver and # changes the name of the USB-UIRT device to avoid the "/" character, # as that appears as a directory separator in the sysfs namespace. # # drivers/usb/serial/ftdi_sio.h # 2004/02/10 04:30:41-08:00 abbotti@mev.co.uk +4 -0 # USB: ftdi_sio new PIDs and name fix for sysfs # # drivers/usb/serial/ftdi_sio.c # 2004/02/10 04:30:41-08:00 abbotti@mev.co.uk +12 -1 # USB: ftdi_sio new PIDs and name fix for sysfs # # ChangeSet # 2004/02/16 16:55:03-08:00 pmarques@grupopie.com # [PATCH] USB: fix usblp.c # # The line that IMHO triggers the bug is this: # # "writecount += usblp->writeurb->transfer_buffer_length;" # # It uses "usblp->writeurb->transfer_buffer_length" before initializing it, # assuming that it will be zero on the first run. If it is not zero, but instead # random *negative* garbage from memory, the loop will start printing endless data # from user-space data. # # drivers/usb/class/usblp.c # 2004/02/09 07:03:32-08:00 pmarques@grupopie.com +8 -12 # USB: fix usblp.c # # ChangeSet # 2004/02/16 16:52:13-08:00 david-b@pacbell.net # [PATCH] USB: EHCI updates (mostly periodic schedule scanning) # # [USB] EHCI updates # # Update periodic schedule scanning # - fix shutdown sometimes-hangs (Bernd Porr) # - resolve the "whole frame at once" FIXME # - try harder to avoid rescanning # - don't delegate interrupt qh handling to a buggy helper routine # - describe more of the relevant iso tuning parameters # # One-liners: # - URB_NO_INTERRUPT hint affects ISO # - show correct data toggle in sysfs debug files # - FIXME is resolved by Linus' 20msec delay # # drivers/usb/host/ehci-sched.c # 2004/02/16 08:50:52-08:00 david-b@pacbell.net +32 -64 # USB: EHCI updates (mostly periodic schedule scanning) # # drivers/usb/host/ehci-hub.c # 2004/02/16 08:50:52-08:00 david-b@pacbell.net +1 -1 # USB: EHCI updates (mostly periodic schedule scanning) # # drivers/usb/host/ehci-dbg.c # 2004/02/16 08:50:52-08:00 david-b@pacbell.net +1 -1 # USB: EHCI updates (mostly periodic schedule scanning) # # ChangeSet # 2004/02/16 14:36:24+00:00 davej@redhat.com # [CPUFREQ] bump copyrights. # # arch/i386/kernel/cpu/cpufreq/powernow-k7.c # 2004/02/16 14:36:17+00:00 davej@redhat.com +1 -1 # [CPUFREQ] bump copyrights. # # arch/i386/kernel/cpu/cpufreq/longhaul.c # 2004/02/16 14:36:17+00:00 davej@redhat.com +1 -1 # [CPUFREQ] bump copyrights. # # ChangeSet # 2004/02/15 21:10:42-08:00 sri@us.ibm.com # [SCTP] Revert back to use kmalloc() for ssnmap allocs of sizes < 128K. # # net/sctp/ssnmap.c # 2004/02/15 21:09:58-08:00 sri@us.ibm.com +19 -8 # [SCTP] Revert back to use kmalloc() for ssnmap allocs of sizes < 128K. # # ChangeSet # 2004/02/14 14:58:30-08:00 grundler@parisc-linux.org # [TG3]: Define MBOX_WRITE_REORDER flag to zero on non-x86. # # drivers/net/tg3.h # 2004/02/14 14:58:17-08:00 grundler@parisc-linux.org +4 -0 # [TG3]: Define MBOX_WRITE_REORDER flag to zero on non-x86. # # ChangeSet # 2004/02/14 14:46:44-08:00 hch@lst.de # [SUNGEM]: Kill unused variable on ppc. # # drivers/net/sungem.c # 2004/02/14 14:46:32-08:00 hch@lst.de +0 -1 # [SUNGEM]: Kill unused variable on ppc. # # ChangeSet # 2004/02/14 14:36:44-08:00 wensong@linux-vs.org # [IPVS] update the version number of code to 1.2.0 # # include/net/ip_vs.h # 2004/02/14 14:36:32-08:00 wensong@linux-vs.org +1 -1 # [IPVS] update the version number of code to 1.2.0 # # ChangeSet # 2004/02/14 12:51:56-08:00 wensong@linux-vs.org # [IPVS] retry to run kernel_thread when memory is temporarily exhausted # # net/ipv4/ipvs/ip_vs_sync.c # 2004/02/14 12:51:44-08:00 wensong@linux-vs.org +21 -8 # [IPVS] retry to run kernel_thread when memory is temporarily exhausted # # ChangeSet # 2004/02/14 12:51:17-08:00 wensong@linux-vs.org # [IPVS] remove the superfluous call of waitpid in sync code # # net/ipv4/ipvs/ip_vs_sync.c # 2004/02/14 12:51:05-08:00 wensong@linux-vs.org +0 -9 # [IPVS] remove the superfluous call of waitpid in sync code # # ChangeSet # 2004/02/14 12:47:58-08:00 petri.koistinen@iki.fi # [WAN]: Kconfig clean-up and update URL links. # # drivers/net/wan/Kconfig # 2004/02/14 12:47:46-08:00 petri.koistinen@iki.fi +299 -273 # [WAN]: Kconfig clean-up and update URL links. # # ChangeSet # 2004/02/14 12:41:51-08:00 romieu@fr.zoreil.com # [IRDA]: In stir4200 driver, defer netif_start_queue() until device opening succeeds. # # drivers/net/irda/stir4200.c # 2004/02/14 12:41:39-08:00 romieu@fr.zoreil.com +2 -2 # [IRDA]: In stir4200 driver, defer netif_start_queue() until device opening succeeds. # # ChangeSet # 2004/02/14 12:41:16-08:00 romieu@fr.zoreil.com # [IRDA]: Fix error return status in stir4200 driver. # # If stir_reset() succeeds, stir_net_open() must not return a # success status code for every failure until irlap_open(). # # drivers/net/irda/stir4200.c # 2004/02/14 12:36:52-08:00 romieu@fr.zoreil.com +2 -1 # [IRDA]: Fix error return status in stir4200 driver. # # If stir_reset() succeeds, stir_net_open() must not return a # success status code for every failure until irlap_open(). # # ChangeSet # 2004/02/13 23:20:47-08:00 ja@ssi.bg # [IPV4]: Add configurable restriction of local IP announcements in ARP requests. # # net/ipv4/devinet.c # 2004/02/13 23:20:35-08:00 ja@ssi.bg +9 -1 # [IPV4]: Add configurable restriction of local IP announcements in ARP requests. # # net/ipv4/arp.c # 2004/02/13 23:20:35-08:00 ja@ssi.bg +28 -3 # [IPV4]: Add configurable restriction of local IP announcements in ARP requests. # # include/linux/sysctl.h # 2004/02/13 23:20:35-08:00 ja@ssi.bg +1 -0 # [IPV4]: Add configurable restriction of local IP announcements in ARP requests. # # include/linux/inetdevice.h # 2004/02/13 23:20:35-08:00 ja@ssi.bg +2 -0 # [IPV4]: Add configurable restriction of local IP announcements in ARP requests. # # Documentation/networking/ip-sysctl.txt # 2004/02/13 23:20:35-08:00 ja@ssi.bg +31 -0 # [IPV4]: Add configurable restriction of local IP announcements in ARP requests. # # ChangeSet # 2004/02/13 23:13:01-08:00 grundler@parisc-linux.org # [TG3]: Abstract out mailbox workarounds into tw32_{rx,tw}_mbox(). # # drivers/net/tg3.c # 2004/02/13 23:12:45-08:00 grundler@parisc-linux.org +37 -54 # [TG3]: Abstract out mailbox workarounds into tw32_{rx,tw}_mbox(). # # ChangeSet # 2004/02/13 23:06:58-08:00 herbert@gondor.apana.org.au # [IPSEC]: Move hardware headers for decaped packets. # # Move the hardware header so that it appears next to the payload for AF_PACKET # sockets. # # net/ipv6/xfrm6_input.c # 2004/02/13 23:06:45-08:00 herbert@gondor.apana.org.au +17 -8 # [IPSEC]: Move hardware headers for decaped packets. # # Move the hardware header so that it appears next to the payload for AF_PACKET # sockets. # # net/ipv4/xfrm4_input.c # 2004/02/13 23:06:45-08:00 herbert@gondor.apana.org.au +13 -5 # [IPSEC]: Move hardware headers for decaped packets. # # Move the hardware header so that it appears next to the payload for AF_PACKET # sockets. # # net/core/dev.c # 2004/02/13 23:06:45-08:00 herbert@gondor.apana.org.au +1 -0 # [IPSEC]: Move hardware headers for decaped packets. # # Move the hardware header so that it appears next to the payload for AF_PACKET # sockets. # # include/linux/skbuff.h # 2004/02/13 23:06:45-08:00 herbert@gondor.apana.org.au +3 -0 # [IPSEC]: Move hardware headers for decaped packets. # # Move the hardware header so that it appears next to the payload for AF_PACKET # sockets. # # ChangeSet # 2004/02/13 23:05:21-08:00 davem@nuts.davemloft.net # [IRDA]: Forgot to add stir4200.c in previous commit. # # drivers/net/irda/stir4200.c # 2004/02/13 23:05:04-08:00 davem@nuts.davemloft.net +1282 -0 # [IRDA]: Forgot to add stir4200.c in previous commit. # # drivers/net/irda/stir4200.c # 2004/02/13 23:05:04-08:00 davem@nuts.davemloft.net +0 -0 # BitKeeper file /disk1/BK/net-2.6/drivers/net/irda/stir4200.c # # ChangeSet # 2004/02/13 23:04:17-08:00 jt@bougret.hpl.hp.com # [IRDA]: Add stir4200 driver. # # After a long maturation, this is time to send you the latest # version of the stir4200 USB driver. Initially started by Paul Stewart, # modified by Martin Diehl and me, and later partially rewriten by # Stephen Hemminger. # The hardware has many quirks. This is the first version that # work reliably at SIR and mostly work at FIR. We may never get optimal # operation from this hardware due to its pecularities, but at least its # now usable. # # drivers/net/irda/Makefile # 2004/02/13 23:01:36-08:00 jt@bougret.hpl.hp.com +1 -0 # [IRDA]: Add stir4200 driver. # # After a long maturation, this is time to send you the latest # version of the stir4200 USB driver. Initially started by Paul Stewart, # modified by Martin Diehl and me, and later partially rewriten by # Stephen Hemminger. # The hardware has many quirks. This is the first version that # work reliably at SIR and mostly work at FIR. We may never get optimal # operation from this hardware due to its pecularities, but at least its # now usable. # # drivers/net/irda/Kconfig # 2004/02/13 23:01:36-08:00 jt@bougret.hpl.hp.com +16 -0 # [IRDA]: Add stir4200 driver. # # After a long maturation, this is time to send you the latest # version of the stir4200 USB driver. Initially started by Paul Stewart, # modified by Martin Diehl and me, and later partially rewriten by # Stephen Hemminger. # The hardware has many quirks. This is the first version that # work reliably at SIR and mostly work at FIR. We may never get optimal # operation from this hardware due to its pecularities, but at least its # now usable. # # ChangeSet # 2004/02/13 12:27:20-05:00 jgarzik@redhat.com # [libata] catch, and ack, spurious DMA interrupts # # Hardware issue on Intel ICH5 requires an additional ack sequence # over and above the normal IDE DMA interrupt ack requirements. Issue # described in post to freebsd list: # http://www.mail-archive.com/freebsd-stable@freebsd.org/msg58421.html # # Since the bug workaround only requires a single additional PIO or # MMIO read in the interrupt handler, it is applied to all chipsets # using the standard libata interrupt handler. # # Credit for research the issue, creating the patch, and testing the # patch all go to Jon Burgess. # # drivers/scsi/libata-core.c # 2004/02/13 12:25:47-05:00 jgarzik@redhat.com +36 -0 # [libata] catch, and ack, spurious DMA interrupts # # Hardware issue on Intel ICH5 requires an additional ack sequence # over and above the normal IDE DMA interrupt ack requirements. Issue # described in post to freebsd list: # http://www.mail-archive.com/freebsd-stable@freebsd.org/msg58421.html # # Since the bug workaround only requires a single additional PIO or # MMIO read in the interrupt handler, it is applied to all chipsets # using the standard libata interrupt handler. # # Credit for research the issue, creating the patch, and testing the # patch all go to Jon Burgess. # # ChangeSet # 2004/02/13 12:13:32+00:00 davej@redhat.com # [CPUFREQ] Update URL. # # MAINTAINERS # 2004/02/13 12:13:26+00:00 davej@redhat.com +1 -1 # [CPUFREQ] Update URL. # # ChangeSet # 2004/02/12 12:05:24-08:00 davem@nuts.davemloft.net # [IPV6]: Kill 64-bit warnings in ndisc.c # # net/ipv6/ndisc.c # 2004/02/12 12:05:08-08:00 davem@nuts.davemloft.net +1 -1 # [IPV6]: Kill 64-bit warnings in ndisc.c # # ChangeSet # 2004/02/12 11:58:30-08:00 dlstevens@us.ibm.com # [IPV6]: Except MLD packets from source filtering. # # Co-authored with Yoshfuji Hideaki. # # net/ipv6/mcast.c # 2004/02/12 11:58:18-08:00 dlstevens@us.ibm.com +28 -1 # [IPV6]: Except MLD packets from source filtering. # # Co-authored with Yoshfuji Hideaki. # # net/ipv6/ip6_input.c # 2004/02/12 11:58:18-08:00 dlstevens@us.ibm.com +19 -14 # [IPV6]: Except MLD packets from source filtering. # # Co-authored with Yoshfuji Hideaki. # # include/net/addrconf.h # 2004/02/12 11:58:18-08:00 dlstevens@us.ibm.com +1 -0 # [IPV6]: Except MLD packets from source filtering. # # Co-authored with Yoshfuji Hideaki. # # ChangeSet # 2004/02/12 09:23:55-06:00 shaggy@austin.ibm.com # JFS: Don't do filename translation by default # # Due to its roots in OS/2, JFS has always tried to convert pathnames # into unicode. Unfortunately, it never had a reliable idea of what # the incoming character set was, so it defaulted to CONFIG_NLS_DEFAULT. # # This behavior was confusing and many users have requested that JFS # have a more sane behavior. This patch changes the default behavior # to store the incoming bytes directly without translation. This is # consistent with the behavior when the default value of # CONFIG_NLS_DEFAULT (iso8859-1) was defined. The default behavior # can be overridden by using the iocharset mount option. # # fs/jfs/super.c # 2004/02/12 09:23:49-06:00 shaggy@austin.ibm.com +2 -4 # Don't do file name translation by default # # fs/jfs/jfs_unicode.c # 2004/02/12 09:23:49-06:00 shaggy@austin.ibm.com +31 -17 # Don't do file name translation by default # # Documentation/filesystems/jfs.txt # 2004/02/12 09:23:49-06:00 shaggy@austin.ibm.com +3 -16 # Make default treatment of filenames sane -- only translate if # iocharset mount option present. Also get rid of out-of-date todo # list. # # ChangeSet # 2004/02/11 22:04:26-08:00 petri.koistinen@iki.fi # [HAMRADIO]: Fix URLs in Kconfig. # # drivers/net/hamradio/Kconfig # 2004/02/11 22:04:14-08:00 petri.koistinen@iki.fi +8 -5 # [HAMRADIO]: Fix URLs in Kconfig. # # ChangeSet # 2004/02/11 22:03:43-08:00 petri.koistinen@iki.fi # [IRDA]: Fix URLs in Kconfig. # # drivers/net/irda/Kconfig # 2004/02/11 22:03:31-08:00 petri.koistinen@iki.fi +1 -1 # [IRDA]: Fix URLs in Kconfig. # # ChangeSet # 2004/02/11 21:10:23-08:00 yoshfuji@linux-ipv6.org # [IPV6]: Kill remaining in6_u.u6_addrX uses. # # net/ipv6/netfilter/ip6t_eui64.c # 2004/02/11 21:10:04-08:00 yoshfuji@linux-ipv6.org +1 -1 # [IPV6]: Kill remaining in6_u.u6_addrX uses. # # net/ipv6/addrconf.c # 2004/02/11 21:10:04-08:00 yoshfuji@linux-ipv6.org +1 -1 # [IPV6]: Kill remaining in6_u.u6_addrX uses. # # ChangeSet # 2004/02/11 19:44:47-08:00 kas@informatics.muni.cz # [NET]: Do not send negative 2nd arg to skb_put(). # # With help from Yoshfuji Hideaki. # # net/ipv4/fib_rules.c # 2004/02/11 19:44:24-08:00 kas@informatics.muni.cz +1 -1 # [NET]: Do not send negative 2nd arg to skb_put(). # # With help from Yoshfuji Hideaki. # # net/decnet/dn_rules.c # 2004/02/11 19:44:24-08:00 kas@informatics.muni.cz +1 -1 # [NET]: Do not send negative 2nd arg to skb_put(). # # With help from Yoshfuji Hideaki. # # ChangeSet # 2004/02/11 19:31:09-08:00 miguel@cetuc.puc-rio.br # [NET_SCHED]: Fix slot leakage in SFQ scheduler. # # net/sched/sch_sfq.c # 2004/02/11 19:30:57-08:00 miguel@cetuc.puc-rio.br +1 -0 # [NET_SCHED]: Fix slot leakage in SFQ scheduler. # # ChangeSet # 2004/02/11 12:20:49-08:00 brazilnut@us.ibm.com # [NET]: Fix ethtool oops if device support get but not set ringparam. # # net/core/ethtool.c # 2004/02/11 12:20:37-08:00 brazilnut@us.ibm.com +1 -1 # [NET]: Fix ethtool oops if device support get but not set ringparam. # # ChangeSet # 2004/02/11 12:18:35-08:00 yoshfuji@linux-ipv6.org # [IPV6]: Spelling corrections, and remove some XXX's # # net/ipv6/route.c # 2004/02/11 12:18:23-08:00 yoshfuji@linux-ipv6.org +1 -1 # [IPV6]: Spelling corrections, and remove some XXX's # # net/ipv6/raw.c # 2004/02/11 12:18:23-08:00 yoshfuji@linux-ipv6.org +3 -3 # [IPV6]: Spelling corrections, and remove some XXX's # # net/ipv6/ndisc.c # 2004/02/11 12:18:22-08:00 yoshfuji@linux-ipv6.org +2 -2 # [IPV6]: Spelling corrections, and remove some XXX's # # net/ipv6/ip6_tunnel.c # 2004/02/11 12:18:22-08:00 yoshfuji@linux-ipv6.org +1 -1 # [IPV6]: Spelling corrections, and remove some XXX's # # net/ipv6/ip6_fib.c # 2004/02/11 12:18:22-08:00 yoshfuji@linux-ipv6.org +1 -1 # [IPV6]: Spelling corrections, and remove some XXX's # # net/ipv6/exthdrs.c # 2004/02/11 12:18:22-08:00 yoshfuji@linux-ipv6.org +1 -1 # [IPV6]: Spelling corrections, and remove some XXX's # # net/ipv6/addrconf.c # 2004/02/11 12:18:22-08:00 yoshfuji@linux-ipv6.org +1 -1 # [IPV6]: Spelling corrections, and remove some XXX's # # ChangeSet # 2004/02/11 12:16:41-08:00 grundler@parisc-linux.org # [PKTGEN]: Fix unintentional unaligned access. # # net/core/pktgen.c # 2004/02/11 12:16:29-08:00 grundler@parisc-linux.org +12 -6 # [PKTGEN]: Fix unintentional unaligned access. # # ChangeSet # 2004/02/11 12:14:10-08:00 yoshfuji@linux-ipv6.org # [IPV6]: Clean up ndisc printks. # # net/ipv6/ndisc.c # 2004/02/11 12:13:47-08:00 yoshfuji@linux-ipv6.org +104 -77 # [IPV6]: Clean up ndisc printks. # # ChangeSet # 2004/02/11 13:35:46-06:00 shaggy@austin.ibm.com # JFS: get_UCSname does not need nls_tab argument # # This is a minor code cleanup. get_UCSname can get nls_tab by # following the dentry to the superblock. This makes the calling code # simpler and prettier. # # fs/jfs/namei.c # 2004/02/11 13:35:41-06:00 shaggy@austin.ibm.com +10 -13 # get_UCSname doesn't need nls_tab argument # # fs/jfs/jfs_unicode.h # 2004/02/11 13:35:41-06:00 shaggy@austin.ibm.com +1 -2 # get_UCSname doesn't need nls_tab argument # # fs/jfs/jfs_unicode.c # 2004/02/11 13:35:41-06:00 shaggy@austin.ibm.com +3 -3 # get_UCSname doesn't need nls_tab argument # # ChangeSet # 2004/02/11 11:20:02-08:00 linux@kodeaffe.de # [NET]: Mention tuxmobil.org in drivers/net/Kconfig. # # drivers/net/Kconfig # 2004/02/11 11:19:50-08:00 linux@kodeaffe.de +2 -1 # [NET]: Mention tuxmobil.org in drivers/net/Kconfig. # # ChangeSet # 2004/02/11 10:42:16-08:00 grundler@parisc-linux.org # [TG3]: Reset GRC, if necessary, before DMA test. # # With help from Michael Chan. # # drivers/net/tg3.c # 2004/02/11 10:41:56-08:00 grundler@parisc-linux.org +16 -1 # [TG3]: Reset GRC, if necessary, before DMA test. # # With help from Michael Chan. # # ChangeSet # 2004/02/11 10:38:41-08:00 yoshfuji@linux-ipv6.org # [NET]: Kill bogus kmem cache alignment in neigh_table_init(). # # net/core/neighbour.c # 2004/02/11 10:38:29-08:00 yoshfuji@linux-ipv6.org +1 -2 # [NET]: Kill bogus kmem cache alignment in neigh_table_init(). # # ChangeSet # 2004/02/11 10:37:48-08:00 kazunori@miyazawa.org # [IPV6]: Unify ipv6 output routine. # # net/ipv6/xfrm6_policy.c # 2004/02/11 10:34:58-08:00 kazunori@miyazawa.org +1 -11 # [IPV6]: Unify ipv6 output routine. # # net/ipv6/route.c # 2004/02/11 10:34:58-08:00 kazunori@miyazawa.org +5 -4 # [IPV6]: Unify ipv6 output routine. # # net/ipv6/ndisc.c # 2004/02/11 10:34:58-08:00 kazunori@miyazawa.org +3 -58 # [IPV6]: Unify ipv6 output routine. # # include/net/ipv6.h # 2004/02/11 10:34:58-08:00 kazunori@miyazawa.org +1 -0 # [IPV6]: Unify ipv6 output routine. # # include/net/ip6_route.h # 2004/02/11 10:34:58-08:00 kazunori@miyazawa.org +1 -0 # [IPV6]: Unify ipv6 output routine. # # include/linux/ipv6_route.h # 2004/02/11 10:34:58-08:00 kazunori@miyazawa.org +0 -1 # [IPV6]: Unify ipv6 output routine. # # ChangeSet # 2004/02/08 13:09:03-08:00 willy@debian.org # [TG32]: Use pci_get_slot() to find 5704 peers, to handle domains properly. # # drivers/net/tg3.c # 2004/02/08 13:06:21-08:00 willy@debian.org +13 -12 # [TG32]: Use pci_get_slot() to find 5704 peers, to handle domains properly. # # ChangeSet # 2004/02/07 00:05:44-05:00 jgarzik@redhat.com # Merge # # drivers/net/wireless/airo.c # 2004/02/07 00:05:40-05:00 jgarzik@redhat.com +0 -0 # SCCS merged # # net/ipv6/sit.c # 2004/02/07 00:04:18-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # net/ipv6/ip6_tunnel.c # 2004/02/07 00:04:18-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/usb/net/usbnet.c # 2004/02/07 00:04:18-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/pppoe.c # 2004/02/07 00:04:18-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/acenic.c # 2004/02/07 00:04:18-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/02/07 00:00:35-05:00 jgarzik@redhat.com # Merge redhat.com:/spare/repo/linux-2.5 # into redhat.com:/spare/repo/netdev-2.6/netdev-alloc-6 # # drivers/net/wan/pc300_drv.c # 2004/02/07 00:00:24-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/02/06 23:38:05-05:00 jgarzik@redhat.com # Merge redhat.com:/spare/repo/linux-2.5 # into redhat.com:/spare/repo/netdev-2.6/e100-2 # # drivers/net/Makefile # 2004/02/06 23:37:57-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/Kconfig # 2004/02/06 23:37:57-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/01/19 18:58:13-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan] apply hdlc cleanups to new driver pci200syn # # drivers/net/wan/pci200syn.c # 2004/01/19 18:58:08-05:00 viro@parcelfarce.linux.theplanet.co.uk +31 -19 # [wan] apply hdlc cleanups to new driver pci200syn # # ChangeSet # 2004/01/19 18:44:37-05:00 jgarzik@redhat.com # Merge redhat.com:/spare/repo/netdev-2.6/netdev-alloc-6 # into redhat.com:/spare/repo/netdev-2.6/netdev-alloc-7 # # net/ipv4/ipmr.c # 2004/01/19 18:44:26-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # net/bluetooth/bnep/core.c # 2004/01/19 18:44:26-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/s390/net/qeth.c # 2004/01/19 18:44:26-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/s390/net/netiucv.c # 2004/01/19 18:44:26-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/s390/net/lcs.c # 2004/01/19 18:44:26-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/wireless/wl3501_cs.c # 2004/01/19 18:44:26-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/wireless/airo.c # 2004/01/19 18:44:26-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/wan/lapbether.c # 2004/01/19 18:44:25-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/01/19 18:41:32-05:00 jgarzik@redhat.com # Merge redhat.com:/spare/repo/netdev-2.6/netdev-alloc-5 # into redhat.com:/spare/repo/netdev-2.6/netdev-alloc-6 # # drivers/net/wan/pc300_drv.c # 2004/01/19 18:41:21-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/wan/lapbether.c # 2004/01/19 18:41:21-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/wan/farsync.c # 2004/01/19 18:41:21-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/01/19 18:11:34-05:00 jgarzik@redhat.com # Merge redhat.com:/spare/repo/netdev-2.6/e100-1 # into redhat.com:/spare/repo/netdev-2.6/e100-2 # # drivers/net/Makefile # 2004/01/19 18:11:23-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # drivers/net/Kconfig # 2004/01/19 18:11:23-05:00 jgarzik@redhat.com +0 -0 # Auto merged # # ChangeSet # 2004/01/13 15:30:03-05:00 scott.feldman@intel.com # [netdrvr e100] copyright + trailing blanks + misc # # * Misc: 2004 copyright, remove trailing white space, remove some # unused symbols. # # drivers/net/e100.c # 2004/01/09 19:50:02-05:00 scott.feldman@intel.com +86 -95 # copyright + trailing blanks + misc # # ChangeSet # 2004/01/13 15:29:55-05:00 scott.feldman@intel.com # [netdrvr e100] fix slab corruption # # * Addresses two problems, both resulting in slab corruption: 1) # driver indicating skb while HW is still DMA'ing (ouch!), 2) # driver not stopping receiver activity before downing i/f. # Fix is 1) wait for RNR (receiver-no-resources) interrupt # before restarting receiver, 2) reseting HW to stop receiver # before stopping i/f. # # This issue was also reproducible with eepro100. You need to turn off # the copybreak, and reduce the number of descriptors to 4. Then bang on # it with pktgen with 60-byte packets, with slab debugging enabled. # # For e100-3.0.x, the issue was a lot easier to reproduce with NAPI, # because NAPI polls independently of where the HW is at, so it's easier # for us to catch HW in the middle of finishing off the last Rx (as # it runs out of resources) and asking HW if it's idle. Checking the # RU status is not-reliable! That's the problem, and the mistake both # eepro100 and e100-3.0.x were making. # # The solution is rely on RNR interrupts as the only indicator that HW is # truly done, and then we're ready to restart the RU. We should only get # RNR interrupts when we overrun the Rx ring. With NAPI, if the ring is # overrun, we'll post RNR, but not restart the RU until we're out of # polling. Without NAPI, we'll restart the RU as soon as we get RNR. # # I ran some 24-hour tests with and without NAPI (with 4 descriptors) # and didn't get any corruption. Prior to this patch, I would get many # errors about slab corruption. # # Also, the patch is larger than you might expect, but I initially thought # I was doing something wrong with managing the ring, so I that # code using old fashion double-link list. The ring management wasn't the # problem, after all, but I prefer the old-fashion d-link implementation # as it's easier to read. # # drivers/net/e100.c # 2004/01/09 19:44:59-05:00 scott.feldman@intel.com +85 -100 # fix slab corruption # # ChangeSet # 2004/01/12 17:27:00-05:00 jgarzik@redhat.com # Eliminate ancient and unused include/linux/{if_pppvar,ppp}.h. # # Well, unused except for one silly constant in isdn_ppp.c. # # include/linux/isdn.h # 2004/01/12 17:26:56-05:00 jgarzik@redhat.com +0 -1 # Eliminate ancient and unused include/linux/{if_pppvar,ppp}.h. # # Well, unused except for one silly constant in isdn_ppp.c. # # drivers/net/pppoe.c # 2004/01/12 17:26:56-05:00 jgarzik@redhat.com +0 -1 # Eliminate ancient and unused include/linux/{if_pppvar,ppp}.h. # # Well, unused except for one silly constant in isdn_ppp.c. # # drivers/isdn/i4l/isdn_ppp.c # 2004/01/12 17:26:56-05:00 jgarzik@redhat.com +3 -0 # Eliminate ancient and unused include/linux/{if_pppvar,ppp}.h. # # Well, unused except for one silly constant in isdn_ppp.c. # # BitKeeper/deleted/.del-ppp.h~2ed9a29f82d978a2 # 2004/01/11 15:45:49-05:00 jgarzik@redhat.com +0 -0 # Delete: include/linux/ppp.h # # BitKeeper/deleted/.del-if_pppvar.h~c9982735aed95c5b # 2004/01/11 15:45:29-05:00 jgarzik@redhat.com +0 -0 # Delete: include/linux/if_pppvar.h # # ChangeSet # 2004/01/11 01:19:14-05:00 viro@parcelfarce.linux.theplanet.co.uk # Remove unused and invalid 'struct ppp' definition from if_pppvar.h. # # include/linux/if_pppvar.h # 2004/01/11 01:19:09-05:00 viro@parcelfarce.linux.theplanet.co.uk +0 -68 # Remove unused and invalid 'struct ppp' definition from if_pppvar.h. # # ChangeSet # 2004/01/10 20:16:19-05:00 shemminger@osdl.org # [PATCH] bugfixes for dgrs.c # # Update the RightSwitch dgrs.c driver for net-drivers-2.5-exp (2.6.1-rc3) # to resolve some of the outstanding cruft there. Al may have a better/newer patch. # # * Don't copy net_device structure on slave device! This won't work # because of state variables in structure. # * make sure and request_regions before doing i/o to the card # * use cpu_relax rather than barrier while spin waiting # * don't use dev->init to do the probing work because hard to get unwind # correct # * Use new pci/eisa probing model, don't search the bus directly # Beneficial side effect, don't need to keep on device list anymore. # * Be more careful about releaseing resources in error paths # # Compiled and module loaded/unloaded, but don't have this hardware. # # drivers/net/dgrs.c # 2004/01/08 11:44:05-05:00 shemminger@osdl.org +218 -145 # bugfixes for dgrs.c # # ChangeSet # 2004/01/10 19:24:27-05:00 viro@parcelfarce.linux.theplanet.co.uk # [netdrvr s390/qeth] Alloc fixes # # drivers/s390/net/qeth.c # 2004/01/10 19:24:23-05:00 viro@parcelfarce.linux.theplanet.co.uk +23 -31 # [netdrvr s390/qeth] Alloc fixes # # ChangeSet # 2004/01/10 19:23:59-05:00 viro@parcelfarce.linux.theplanet.co.uk # [netdrvr shaper] fix double-free # # Fix for double-free (we do explicit free_netdev() after unregister_netdev() # in shaper.c) # # drivers/net/shaper.c # 2004/01/10 19:23:54-05:00 viro@parcelfarce.linux.theplanet.co.uk +0 -1 # [netdrvr shaper] fix double-free # # Fix for double-free (we do explicit free_netdev() after unregister_netdev() # in shaper.c) # # ChangeSet # 2004/01/10 19:23:34-05:00 viro@parcelfarce.linux.theplanet.co.uk # [netdrvr dvb/dvb_net] fixes # # Don't leave dvbnet->device[...] dangling after we free the sucker # # drivers/media/dvb/dvb-core/dvb_net.c # 2004/01/10 19:23:30-05:00 viro@parcelfarce.linux.theplanet.co.uk +3 -1 # [netdrvr dvb/dvb_net] fixes # # Don't leave dvbnet->device[...] dangling after we free the sucker # # ChangeSet # 2004/01/10 19:22:49-05:00 viro@parcelfarce.linux.theplanet.co.uk # [netdrvr arch/uml] leak fix # # arch/um/drivers/net_kern.c # 2004/01/10 19:22:44-05:00 viro@parcelfarce.linux.theplanet.co.uk +5 -1 # [netdrvr arch/uml] leak fix # # ChangeSet # 2004/01/10 19:21:37-05:00 viro@parcelfarce.linux.theplanet.co.uk # [netdrvr saa9730] fix double-free # # Fixed double-free in saa9730.c (caller of that function does free_netdev() # itself if we return an error). # # drivers/net/saa9730.c # 2004/01/10 19:21:33-05:00 viro@parcelfarce.linux.theplanet.co.uk +3 -1 # [netdrvr saa9730] fix double-free # # Fixed double-free in saa9730.c (caller of that function does free_netdev() # itself if we return an error). # # ChangeSet # 2004/01/10 19:21:02-05:00 viro@parcelfarce.linux.theplanet.co.uk # [netdrvr arm/am79c961] Fix for IO-before-request_region race # # drivers/net/arm/am79c961a.c # 2004/01/10 19:20:58-05:00 viro@parcelfarce.linux.theplanet.co.uk +5 -5 # [netdrvr arm/am79c961] Fix for IO-before-request_region race # # ChangeSet # 2004/01/10 19:20:29-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan] leak fixes in hostess_sv11, lapbether # # drivers/net/wan/lapbether.c # 2004/01/10 19:20:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -0 # [wan] leak fixes in hostess_sv11, lapbether # # drivers/net/wan/hostess_sv11.c # 2004/01/10 19:20:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +3 -2 # [wan] leak fixes in hostess_sv11, lapbether # # ChangeSet # 2004/01/10 19:19:40-05:00 viro@parcelfarce.linux.theplanet.co.uk # [netdrvr s390/lcs] Leak fix # # lcs_cleanup_channel() is not enough there, we need full # lcs_cleanup_card() (e.g. to free netdev) # # drivers/s390/net/lcs.c # 2004/01/10 19:19:36-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -2 # [netdrvr s390/lcs] Leak fix # # lcs_cleanup_channel() is not enough there, we need full # lcs_cleanup_card() (e.g. to free netdev) # # ChangeSet # 2004/01/10 19:19:11-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wireless orinoco] check alloc_etherdev for failure # # drivers/net/wireless/orinoco.c # 2004/01/10 19:19:06-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -0 # [wireless orinoco] check alloc_etherdev for failure # # ChangeSet # 2004/01/10 19:18:42-05:00 viro@parcelfarce.linux.theplanet.co.uk # [netdrvr apne] resource leak fix # # drivers/net/apne.c # 2004/01/10 19:18:38-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -0 # [netdrvr apne] resource leak fix # # ChangeSet # 2004/01/10 19:18:06-05:00 viro@parcelfarce.linux.theplanet.co.uk # [netdrvr 3c509] Leak fixed # # drivers/net/3c509.c # 2004/01/10 19:18:02-05:00 viro@parcelfarce.linux.theplanet.co.uk +4 -0 # [netdrvr 3c509] Leak fixed # # ChangeSet # 2004/01/10 19:17:33-05:00 viro@parcelfarce.linux.theplanet.co.uk # [netdrvr acenic] Race and leak fixes # # drivers/net/acenic.c # 2004/01/10 19:17:29-05:00 viro@parcelfarce.linux.theplanet.co.uk +8 -7 # [netdrvr acenic] Race and leak fixes # # ChangeSet # 2004/01/10 19:16:58-05:00 viro@parcelfarce.linux.theplanet.co.uk # [all over] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # net/irda/irlan/irlan_eth.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # net/irda/irlan/irlan_common.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # net/ipv6/sit.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # net/ipv6/ip6_tunnel.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # net/ipv4/ipmr.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # net/ipv4/ipip.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # net/ipv4/ip_gre.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # net/bluetooth/bnep/core.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # net/atm/lec.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # net/8021q/vlan.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # drivers/usb/net/usbnet.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # drivers/usb/net/rtl8150.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # drivers/usb/net/pegasus.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # drivers/usb/net/kaweth.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # drivers/usb/net/catc.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # drivers/s390/net/lcs.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # drivers/net/wireless/wl3501_cs.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # drivers/net/wan/hdlc_fr.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +3 -2 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # drivers/net/wan/dlci.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # drivers/net/tokenring/3c359.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # drivers/net/fc/iph5526.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # drivers/net/appletalk/cops.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # drivers/message/fusion/mptlan.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # arch/ppc/8xx_io/fec.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # arch/ppc/8xx_io/enet.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # arch/ppc/8260_io/fcc_enet.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # arch/ppc/8260_io/enet.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # arch/ia64/hp/sim/simeth.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # arch/cris/arch-v10/drivers/ethernet.c # 2004/01/10 19:16:53-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [netdrvr] more kfree -> free_netdev # # Remaining kfree -> free_netdev replacements (easy part of free_netdev() fixes) # # ChangeSet # 2004/01/10 19:16:08-05:00 viro@parcelfarce.linux.theplanet.co.uk # [netdrvr isa-skeleton] cleanups and fixes # # isa-skeleton.c got the same changes as actual ISA drivers - dynamic allocation, # leak fixes, clobbering fixes, fix for IO-before-request_region(). # # drivers/net/isa-skeleton.c # 2004/01/10 19:16:04-05:00 viro@parcelfarce.linux.theplanet.co.uk +79 -54 # [netdrvr isa-skeleton] cleanups and fixes # # isa-skeleton.c got the same changes as actual ISA drivers - dynamic allocation, # leak fixes, clobbering fixes, fix for IO-before-request_region(). # # ChangeSet # 2004/01/10 19:15:29-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan sdla] Fixed leaks and double-free # # drivers/net/wan/sdla.c # 2004/01/10 19:15:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +87 -107 # [wan sdla] Fixed leaks and double-free # # ChangeSet # 2004/01/10 19:15:06-05:00 viro@parcelfarce.linux.theplanet.co.uk # [netdrvr fec] switched to sane allocation. It still leaks on failure exits, though. # # drivers/net/fec.c # 2004/01/10 19:15:01-05:00 viro@parcelfarce.linux.theplanet.co.uk +24 -15 # [netdrvr fec] switched to sane allocation. It still leaks on failure exits, though. # # ChangeSet # 2004/01/10 19:14:14-05:00 viro@parcelfarce.linux.theplanet.co.uk # [netdrvr s390/netiucv] partially sanitized wrt allocation # # drivers/s390/net/netiucv.c # 2004/01/10 19:14:09-05:00 viro@parcelfarce.linux.theplanet.co.uk +28 -17 # [netdrvr s390/netiucv] partially sanitized wrt allocation # # ChangeSet # 2004/01/10 19:13:39-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wireless airo] switched to sane allocation. # # drivers/net/wireless/airo.c # 2004/01/10 19:13:35-05:00 viro@parcelfarce.linux.theplanet.co.uk +11 -16 # [wireless airo] switched to sane allocation. # # ChangeSet # 2004/01/10 19:09:14-05:00 viro@parcelfarce.linux.theplanet.co.uk # [netdrvr tun] Killed bogus ->init() # # drivers/net/tun.c # 2004/01/10 19:09:09-05:00 viro@parcelfarce.linux.theplanet.co.uk +4 -7 # [netdrvr tun] Killed bogus ->init() # # ChangeSet # 2004/01/10 19:08:47-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan sealevel] Plugged a leak # # drivers/net/wan/sealevel.c # 2004/01/10 19:08:42-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -0 # [wan sealevel] Plugged a leak # # ChangeSet # 2004/01/10 19:08:20-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan sbni] sane net_device allocation; plug a bunch of leaks # # Plugged a bunch of leaks in sbni. Replaced check_region() with intended # request_region() in pci probe (BTW, that bugger should be turned into # normal PCI driver at some point). # # drivers/net/wan/sbni.c # 2004/01/10 19:08:16-05:00 viro@parcelfarce.linux.theplanet.co.uk +28 -9 # [wan sbni] sane net_device allocation; plug a bunch of leaks # # Plugged a bunch of leaks in sbni. Replaced check_region() with intended # request_region() in pci probe (BTW, that bugger should be turned into # normal PCI driver at some point). # # ChangeSet # 2004/01/10 19:07:29-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hostess_sv11] sane net_device allocation # # Sane allocation in sv11. Switched it to SET_MODULE_OWNER(), while we are # at it. Fixed a leak on exit and destroy-before-unregister race. # # drivers/net/wan/hostess_sv11.c # 2004/01/10 19:07:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +17 -15 # [wan hostess_sv11] sane net_device allocation # # Sane allocation in sv11. Switched it to SET_MODULE_OWNER(), while we are # at it. Fixed a leak on exit and destroy-before-unregister race. # # ChangeSet # 2004/01/10 19:06:53-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc_fr] Switched allocation of net_device to alloc_netdev(). # # drivers/net/wan/hdlc_fr.c # 2004/01/10 19:06:48-05:00 viro@parcelfarce.linux.theplanet.co.uk +18 -15 # [wan hdlc_fr] Switched allocation of net_device to alloc_netdev(). # # ChangeSet # 2004/01/10 19:06:22-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc] kill embedding of struct net_device # # Now we can kill the embedding of net_device into hdlc_device. Indeed, # all instances of hdlc_device are created by alloc_hdlcdev() and nothing # uses hdlc->netdev directly. So we can # * remove hdlc->netdev # * have alloc_hdlcdev() implemented via alloc_netdev() with the rest # of hdlc_device as private part of net_device. # * replace free_hdlcdev() with free_netdev(). # * have dev_to_hdlc(dev) simply return netdev_priv(dev). # # include/linux/hdlc.h # 2004/01/10 19:06:17-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -8 # [wan hdlc] kill embedding of struct net_device # # Now we can kill the embedding of net_device into hdlc_device. Indeed, # all instances of hdlc_device are created by alloc_hdlcdev() and nothing # uses hdlc->netdev directly. So we can # * remove hdlc->netdev # * have alloc_hdlcdev() implemented via alloc_netdev() with the rest # of hdlc_device as private part of net_device. # * replace free_hdlcdev() with free_netdev(). # * have dev_to_hdlc(dev) simply return netdev_priv(dev). # # drivers/net/wan/wanxl.c # 2004/01/10 19:06:17-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] kill embedding of struct net_device # # Now we can kill the embedding of net_device into hdlc_device. Indeed, # all instances of hdlc_device are created by alloc_hdlcdev() and nothing # uses hdlc->netdev directly. So we can # * remove hdlc->netdev # * have alloc_hdlcdev() implemented via alloc_netdev() with the rest # of hdlc_device as private part of net_device. # * replace free_hdlcdev() with free_netdev(). # * have dev_to_hdlc(dev) simply return netdev_priv(dev). # # drivers/net/wan/pc300_drv.c # 2004/01/10 19:06:17-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc] kill embedding of struct net_device # # Now we can kill the embedding of net_device into hdlc_device. Indeed, # all instances of hdlc_device are created by alloc_hdlcdev() and nothing # uses hdlc->netdev directly. So we can # * remove hdlc->netdev # * have alloc_hdlcdev() implemented via alloc_netdev() with the rest # of hdlc_device as private part of net_device. # * replace free_hdlcdev() with free_netdev(). # * have dev_to_hdlc(dev) simply return netdev_priv(dev). # # drivers/net/wan/n2.c # 2004/01/10 19:06:17-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc] kill embedding of struct net_device # # Now we can kill the embedding of net_device into hdlc_device. Indeed, # all instances of hdlc_device are created by alloc_hdlcdev() and nothing # uses hdlc->netdev directly. So we can # * remove hdlc->netdev # * have alloc_hdlcdev() implemented via alloc_netdev() with the rest # of hdlc_device as private part of net_device. # * replace free_hdlcdev() with free_netdev(). # * have dev_to_hdlc(dev) simply return netdev_priv(dev). # # drivers/net/wan/hdlc_generic.c # 2004/01/10 19:06:17-05:00 viro@parcelfarce.linux.theplanet.co.uk +25 -6 # [wan hdlc] kill embedding of struct net_device # # Now we can kill the embedding of net_device into hdlc_device. Indeed, # all instances of hdlc_device are created by alloc_hdlcdev() and nothing # uses hdlc->netdev directly. So we can # * remove hdlc->netdev # * have alloc_hdlcdev() implemented via alloc_netdev() with the rest # of hdlc_device as private part of net_device. # * replace free_hdlcdev() with free_netdev(). # * have dev_to_hdlc(dev) simply return netdev_priv(dev). # # drivers/net/wan/farsync.c # 2004/01/10 19:06:17-05:00 viro@parcelfarce.linux.theplanet.co.uk +4 -4 # [wan hdlc] kill embedding of struct net_device # # Now we can kill the embedding of net_device into hdlc_device. Indeed, # all instances of hdlc_device are created by alloc_hdlcdev() and nothing # uses hdlc->netdev directly. So we can # * remove hdlc->netdev # * have alloc_hdlcdev() implemented via alloc_netdev() with the rest # of hdlc_device as private part of net_device. # * replace free_hdlcdev() with free_netdev(). # * have dev_to_hdlc(dev) simply return netdev_priv(dev). # # drivers/net/wan/dscc4.c # 2004/01/10 19:06:17-05:00 viro@parcelfarce.linux.theplanet.co.uk +3 -3 # [wan hdlc] kill embedding of struct net_device # # Now we can kill the embedding of net_device into hdlc_device. Indeed, # all instances of hdlc_device are created by alloc_hdlcdev() and nothing # uses hdlc->netdev directly. So we can # * remove hdlc->netdev # * have alloc_hdlcdev() implemented via alloc_netdev() with the rest # of hdlc_device as private part of net_device. # * replace free_hdlcdev() with free_netdev(). # * have dev_to_hdlc(dev) simply return netdev_priv(dev). # # drivers/net/wan/c101.c # 2004/01/10 19:06:17-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] kill embedding of struct net_device # # Now we can kill the embedding of net_device into hdlc_device. Indeed, # all instances of hdlc_device are created by alloc_hdlcdev() and nothing # uses hdlc->netdev directly. So we can # * remove hdlc->netdev # * have alloc_hdlcdev() implemented via alloc_netdev() with the rest # of hdlc_device as private part of net_device. # * replace free_hdlcdev() with free_netdev(). # * have dev_to_hdlc(dev) simply return netdev_priv(dev). # # ChangeSet # 2004/01/10 19:05:38-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc] removal hdlc_to_dev() # # No more users, we may remove it. # # include/linux/hdlc.h # 2004/01/10 19:05:33-05:00 viro@parcelfarce.linux.theplanet.co.uk +0 -5 # [wan hdlc] removal hdlc_to_dev() # # No more users, we may remove it. # # ChangeSet # 2004/01/10 19:05:06-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan dscc4] embedded struct removal # # Killed embedded hdlc in dscc4 (same as for other drivers). Fixed a # setup-after-registration race. # # That was the last user of hdlc_to_dev(); killed. # # drivers/net/wan/dscc4.c # 2004/01/10 19:05:01-05:00 viro@parcelfarce.linux.theplanet.co.uk +32 -18 # [wan dscc4] embedded struct removal # # Killed embedded hdlc in dscc4 (same as for other drivers). Fixed a # setup-after-registration race. # # That was the last user of hdlc_to_dev(); killed. # # ChangeSet # 2004/01/10 19:03:28-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan farsync] embedded struct hdlc_device removal # # Removed embedded hdlc in farsync (same as for wanxl and friends). # setup-after-registration race fixed. # # drivers/net/wan/farsync.c # 2004/01/10 19:03:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +59 -41 # [wan farsync] embedded struct hdlc_device removal # # Removed embedded hdlc in farsync (same as for wanxl and friends). # setup-after-registration race fixed. # # ChangeSet # 2004/01/10 19:02:41-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan pc300] use alloc_hdlcdev()/free_hdlcdev(). Leak fixed # # drivers/net/wan/pc300_drv.c # 2004/01/10 19:02:36-05:00 viro@parcelfarce.linux.theplanet.co.uk +5 -3 # [wan pc300] use alloc_hdlcdev()/free_hdlcdev(). Leak fixed # # ChangeSet # 2004/01/10 19:02:00-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc] kill embedded struct in various drivers # # Killed embedded hdlc in hd6457x.c derivatives (same as wanxl in previous # patch) # # drivers/net/wan/n2.c # 2004/01/10 19:01:55-05:00 viro@parcelfarce.linux.theplanet.co.uk +15 -2 # [wan hdlc] kill embedded struct in various drivers # # Killed embedded hdlc in hd6457x.c derivatives (same as wanxl in previous # patch) # # drivers/net/wan/hd6457x.c # 2004/01/10 19:01:55-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc] kill embedded struct in various drivers # # Killed embedded hdlc in hd6457x.c derivatives (same as wanxl in previous # patch) # # drivers/net/wan/c101.c # 2004/01/10 19:01:55-05:00 viro@parcelfarce.linux.theplanet.co.uk +12 -1 # [wan hdlc] kill embedded struct in various drivers # # Killed embedded hdlc in hd6457x.c derivatives (same as wanxl in previous # patch) # # ChangeSet # 2004/01/10 19:01:23-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc] new private struct pointer in hdlc_device, and helpers for it # # New field in hdlc_device: void *priv; # New helpers: # struct net_device *alloc_hdlcdev(priv) allocates hdlc, sets ->priv and # returns pointer to hdlc->netdev # free_hdlcdev(dev) takes such pointer and frees its hdlc. # # wanxl switched to use of those; instead of embedding hdlc into card->ports[] # we allocate it separately right after card had been allocated and store pointer # to hdlc->netdev in card->ports[]->dev. Freeing is done just before freeing # card. Pointer back to card->ports[] is stored in hdlc->priv. port_to_dev() # and dev_to_port() rewritten in the obvious way; by now the rest of driver # doesn't care whether hdlc is embedded or not - everything uses port_to_dev() # and dev_to_port(). # # That killed embedded hdlc replacing it with pointer to net_device. Fairly # similar work will be done in the next few patches for other drivers. # # Additionally, setup-after-register and free_irq()-before-unregister races # had been fixed. # # include/linux/hdlc.h # 2004/01/10 19:01:18-05:00 viro@parcelfarce.linux.theplanet.co.uk +7 -0 # [wan hdlc] new private struct pointer in hdlc_device, and helpers for it # # New field in hdlc_device: void *priv; # New helpers: # struct net_device *alloc_hdlcdev(priv) allocates hdlc, sets ->priv and # returns pointer to hdlc->netdev # free_hdlcdev(dev) takes such pointer and frees its hdlc. # # wanxl switched to use of those; instead of embedding hdlc into card->ports[] # we allocate it separately right after card had been allocated and store pointer # to hdlc->netdev in card->ports[]->dev. Freeing is done just before freeing # card. Pointer back to card->ports[] is stored in hdlc->priv. port_to_dev() # and dev_to_port() rewritten in the obvious way; by now the rest of driver # doesn't care whether hdlc is embedded or not - everything uses port_to_dev() # and dev_to_port(). # # That killed embedded hdlc replacing it with pointer to net_device. Fairly # similar work will be done in the next few patches for other drivers. # # Additionally, setup-after-register and free_irq()-before-unregister races # had been fixed. # # drivers/net/wan/wanxl.c # 2004/01/10 19:01:18-05:00 viro@parcelfarce.linux.theplanet.co.uk +48 -33 # [wan hdlc] new private struct pointer in hdlc_device, and helpers for it # # New field in hdlc_device: void *priv; # New helpers: # struct net_device *alloc_hdlcdev(priv) allocates hdlc, sets ->priv and # returns pointer to hdlc->netdev # free_hdlcdev(dev) takes such pointer and frees its hdlc. # # wanxl switched to use of those; instead of embedding hdlc into card->ports[] # we allocate it separately right after card had been allocated and store pointer # to hdlc->netdev in card->ports[]->dev. Freeing is done just before freeing # card. Pointer back to card->ports[] is stored in hdlc->priv. port_to_dev() # and dev_to_port() rewritten in the obvious way; by now the rest of driver # doesn't care whether hdlc is embedded or not - everything uses port_to_dev() # and dev_to_port(). # # That killed embedded hdlc replacing it with pointer to net_device. Fairly # similar work will be done in the next few patches for other drivers. # # Additionally, setup-after-register and free_irq()-before-unregister races # had been fixed. # # drivers/net/wan/hdlc_generic.c # 2004/01/10 19:01:18-05:00 viro@parcelfarce.linux.theplanet.co.uk +10 -1 # [wan hdlc] new private struct pointer in hdlc_device, and helpers for it # # New field in hdlc_device: void *priv; # New helpers: # struct net_device *alloc_hdlcdev(priv) allocates hdlc, sets ->priv and # returns pointer to hdlc->netdev # free_hdlcdev(dev) takes such pointer and frees its hdlc. # # wanxl switched to use of those; instead of embedding hdlc into card->ports[] # we allocate it separately right after card had been allocated and store pointer # to hdlc->netdev in card->ports[]->dev. Freeing is done just before freeing # card. Pointer back to card->ports[] is stored in hdlc->priv. port_to_dev() # and dev_to_port() rewritten in the obvious way; by now the rest of driver # doesn't care whether hdlc is embedded or not - everything uses port_to_dev() # and dev_to_port(). # # That killed embedded hdlc replacing it with pointer to net_device. Fairly # similar work will be done in the next few patches for other drivers. # # Additionally, setup-after-register and free_irq()-before-unregister races # had been fixed. # # ChangeSet # 2004/01/10 19:00:10-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc] switch register_hdlc_device() to take net_device arg # # register_hdlc_device()/unregister_hdlc_device() switched to net_device. # Now all remaining callers of hdlc_to_dev() are isolated and we can # start killing them. # # include/linux/hdlc.h # 2004/01/10 19:00:06-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc] switch register_hdlc_device() to take net_device arg # # register_hdlc_device()/unregister_hdlc_device() switched to net_device. # Now all remaining callers of hdlc_to_dev() are isolated and we can # start killing them. # # drivers/net/wan/wanxl.c # 2004/01/10 19:00:06-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc] switch register_hdlc_device() to take net_device arg # # register_hdlc_device()/unregister_hdlc_device() switched to net_device. # Now all remaining callers of hdlc_to_dev() are isolated and we can # start killing them. # # drivers/net/wan/pc300_drv.c # 2004/01/10 19:00:06-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc] switch register_hdlc_device() to take net_device arg # # register_hdlc_device()/unregister_hdlc_device() switched to net_device. # Now all remaining callers of hdlc_to_dev() are isolated and we can # start killing them. # # drivers/net/wan/n2.c # 2004/01/10 19:00:06-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc] switch register_hdlc_device() to take net_device arg # # register_hdlc_device()/unregister_hdlc_device() switched to net_device. # Now all remaining callers of hdlc_to_dev() are isolated and we can # start killing them. # # drivers/net/wan/hdlc_generic.c # 2004/01/10 19:00:06-05:00 viro@parcelfarce.linux.theplanet.co.uk +5 -5 # [wan hdlc] switch register_hdlc_device() to take net_device arg # # register_hdlc_device()/unregister_hdlc_device() switched to net_device. # Now all remaining callers of hdlc_to_dev() are isolated and we can # start killing them. # # drivers/net/wan/farsync.c # 2004/01/10 19:00:06-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc] switch register_hdlc_device() to take net_device arg # # register_hdlc_device()/unregister_hdlc_device() switched to net_device. # Now all remaining callers of hdlc_to_dev() are isolated and we can # start killing them. # # drivers/net/wan/dscc4.c # 2004/01/10 19:00:06-05:00 viro@parcelfarce.linux.theplanet.co.uk +4 -4 # [wan hdlc] switch register_hdlc_device() to take net_device arg # # register_hdlc_device()/unregister_hdlc_device() switched to net_device. # Now all remaining callers of hdlc_to_dev() are isolated and we can # start killing them. # # drivers/net/wan/c101.c # 2004/01/10 19:00:06-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc] switch register_hdlc_device() to take net_device arg # # register_hdlc_device()/unregister_hdlc_device() switched to net_device. # Now all remaining callers of hdlc_to_dev() are isolated and we can # start killing them. # # ChangeSet # 2004/01/10 18:57:37-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan dscc4] Uses of ->hdlc and hdlc_to_dev() encapsulated into dscc4_to_dev(). # # drivers/net/wan/dscc4.c # 2004/01/10 18:57:33-05:00 viro@parcelfarce.linux.theplanet.co.uk +12 -7 # [wan dscc4] Uses of ->hdlc and hdlc_to_dev() encapsulated into dscc4_to_dev(). # # ChangeSet # 2004/01/10 18:56:58-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc] new hdlc_stats() helper # # New inlined helper - hdlc_stats(). A lot of places had it spelled out; # replaced with calls. # # include/linux/hdlc.h # 2004/01/10 18:56:54-05:00 viro@parcelfarce.linux.theplanet.co.uk +6 -0 # [wan hdlc] new hdlc_stats() helper # # New inlined helper - hdlc_stats(). A lot of places had it spelled out; # replaced with calls. # # drivers/net/wan/wanxl.c # 2004/01/10 18:56:54-05:00 viro@parcelfarce.linux.theplanet.co.uk +7 -8 # [wan hdlc] new hdlc_stats() helper # # New inlined helper - hdlc_stats(). A lot of places had it spelled out; # replaced with calls. # # drivers/net/wan/pc300_tty.c # 2004/01/10 18:56:54-05:00 viro@parcelfarce.linux.theplanet.co.uk +3 -3 # [wan hdlc] new hdlc_stats() helper # # New inlined helper - hdlc_stats(). A lot of places had it spelled out; # replaced with calls. # # drivers/net/wan/pc300_drv.c # 2004/01/10 18:56:54-05:00 viro@parcelfarce.linux.theplanet.co.uk +5 -5 # [wan hdlc] new hdlc_stats() helper # # New inlined helper - hdlc_stats(). A lot of places had it spelled out; # replaced with calls. # # drivers/net/wan/hdlc_raw_eth.c # 2004/01/10 18:56:54-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] new hdlc_stats() helper # # New inlined helper - hdlc_stats(). A lot of places had it spelled out; # replaced with calls. # # drivers/net/wan/hdlc_generic.c # 2004/01/10 18:56:54-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] new hdlc_stats() helper # # New inlined helper - hdlc_stats(). A lot of places had it spelled out; # replaced with calls. # # drivers/net/wan/hd6457x.c # 2004/01/10 18:56:54-05:00 viro@parcelfarce.linux.theplanet.co.uk +6 -6 # [wan hdlc] new hdlc_stats() helper # # New inlined helper - hdlc_stats(). A lot of places had it spelled out; # replaced with calls. # # drivers/net/wan/farsync.c # 2004/01/10 18:56:54-05:00 viro@parcelfarce.linux.theplanet.co.uk +5 -5 # [wan hdlc] new hdlc_stats() helper # # New inlined helper - hdlc_stats(). A lot of places had it spelled out; # replaced with calls. # # drivers/net/wan/dscc4.c # 2004/01/10 18:56:54-05:00 viro@parcelfarce.linux.theplanet.co.uk +4 -4 # [wan hdlc] new hdlc_stats() helper # # New inlined helper - hdlc_stats(). A lot of places had it spelled out; # replaced with calls. # # drivers/net/wan/c101.c # 2004/01/10 18:56:54-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] new hdlc_stats() helper # # New inlined helper - hdlc_stats(). A lot of places had it spelled out; # replaced with calls. # # ChangeSet # 2004/01/10 18:56:26-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan pc300] more direct use of net_device # # In pc300 replaced dev->hdlc with dev->dev (hdlc to net_device). Killed a # bunch of ugliness in pc300_tty.c, killed hdlc_to_dev() uses. # # drivers/net/wan/pc300_tty.c # 2004/01/10 18:56:21-05:00 viro@parcelfarce.linux.theplanet.co.uk +18 -22 # [wan pc300] more direct use of net_device # # In pc300 replaced dev->hdlc with dev->dev (hdlc to net_device). Killed a # bunch of ugliness in pc300_tty.c, killed hdlc_to_dev() uses. # # drivers/net/wan/pc300_drv.c # 2004/01/10 18:56:21-05:00 viro@parcelfarce.linux.theplanet.co.uk +19 -28 # [wan pc300] more direct use of net_device # # In pc300 replaced dev->hdlc with dev->dev (hdlc to net_device). Killed a # bunch of ugliness in pc300_tty.c, killed hdlc_to_dev() uses. # # drivers/net/wan/pc300.h # 2004/01/10 18:56:21-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan pc300] more direct use of net_device # # In pc300 replaced dev->hdlc with dev->dev (hdlc to net_device). Killed a # bunch of ugliness in pc300_tty.c, killed hdlc_to_dev() uses. # # ChangeSet # 2004/01/10 18:55:30-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc] switch internal ioctl dispatch to net_device # # Switched remaining ioctls to net_device, killed a bunch of hdlc_to_dev() # and killed hdlc_to_name(). # # include/linux/hdlc.h # 2004/01/10 18:55:25-05:00 viro@parcelfarce.linux.theplanet.co.uk +3 -9 # [wan hdlc] switch internal ioctl dispatch to net_device # # Switched remaining ioctls to net_device, killed a bunch of hdlc_to_dev() # and killed hdlc_to_name(). # # drivers/net/wan/hdlc_raw_eth.c # 2004/01/10 18:55:25-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc] switch internal ioctl dispatch to net_device # # Switched remaining ioctls to net_device, killed a bunch of hdlc_to_dev() # and killed hdlc_to_name(). # # drivers/net/wan/hdlc_raw.c # 2004/01/10 18:55:25-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc] switch internal ioctl dispatch to net_device # # Switched remaining ioctls to net_device, killed a bunch of hdlc_to_dev() # and killed hdlc_to_name(). # # drivers/net/wan/hdlc_ppp.c # 2004/01/10 18:55:25-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc] switch internal ioctl dispatch to net_device # # Switched remaining ioctls to net_device, killed a bunch of hdlc_to_dev() # and killed hdlc_to_name(). # # drivers/net/wan/hdlc_generic.c # 2004/01/10 18:55:25-05:00 viro@parcelfarce.linux.theplanet.co.uk +6 -6 # [wan hdlc] switch internal ioctl dispatch to net_device # # Switched remaining ioctls to net_device, killed a bunch of hdlc_to_dev() # and killed hdlc_to_name(). # # ChangeSet # 2004/01/10 18:54:53-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan wanxl] eliminated hdlc_to_name() uses and a bunch of port->hdlc ones. # # drivers/net/wan/wanxl.c # 2004/01/10 18:54:49-05:00 viro@parcelfarce.linux.theplanet.co.uk +28 -32 # [wan wanxl] eliminated hdlc_to_name() uses and a bunch of port->hdlc ones. # # ChangeSet # 2004/01/10 18:54:24-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc_x25] eliminated hdlc_to_dev() and hdlc_to_name() uses. # # include/linux/hdlc.h # 2004/01/10 18:54:19-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc_x25] eliminated hdlc_to_dev() and hdlc_to_name() uses. # # drivers/net/wan/hdlc_x25.c # 2004/01/10 18:54:19-05:00 viro@parcelfarce.linux.theplanet.co.uk +4 -5 # [wan hdlc_x25] eliminated hdlc_to_dev() and hdlc_to_name() uses. # # drivers/net/wan/hdlc_generic.c # 2004/01/10 18:54:19-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc_x25] eliminated hdlc_to_dev() and hdlc_to_name() uses. # # ChangeSet # 2004/01/10 18:53:51-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc] hdlc_fr: eliminated ->netdev, hdlc_to_dev() and hdlc_to_name() uses. # # include/linux/hdlc.h # 2004/01/10 18:53:47-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc] hdlc_fr: eliminated ->netdev, hdlc_to_dev() and hdlc_to_name() uses. # # drivers/net/wan/hdlc_generic.c # 2004/01/10 18:53:47-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc] hdlc_fr: eliminated ->netdev, hdlc_to_dev() and hdlc_to_name() uses. # # drivers/net/wan/hdlc_fr.c # 2004/01/10 18:53:47-05:00 viro@parcelfarce.linux.theplanet.co.uk +64 -55 # [wan hdlc] hdlc_fr: eliminated ->netdev, hdlc_to_dev() and hdlc_to_name() uses. # # ChangeSet # 2004/01/10 18:53:17-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc] hdlc_cisco: killed ->netdev, hdlc_to_name() and hdlc_to_dev() uses. # # include/linux/hdlc.h # 2004/01/10 18:53:12-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc_cisco: killed ->netdev, hdlc_to_name() and hdlc_to_dev() uses. # # drivers/net/wan/hdlc_generic.c # 2004/01/10 18:53:12-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc] hdlc_cisco: killed ->netdev, hdlc_to_name() and hdlc_to_dev() uses. # # drivers/net/wan/hdlc_cisco.c # 2004/01/10 18:53:12-05:00 viro@parcelfarce.linux.theplanet.co.uk +22 -21 # [wan hdlc] hdlc_cisco: killed ->netdev, hdlc_to_name() and hdlc_to_dev() uses. # # ChangeSet # 2004/01/10 18:52:47-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc] hdlc->proto.*() switched to net_device. # Eliminated a bunch of ->netdev and hdlc_to_dev() uses. # # include/linux/hdlc.h # 2004/01/10 18:52:43-05:00 viro@parcelfarce.linux.theplanet.co.uk +4 -4 # [wan hdlc] hdlc->proto.*() switched to net_device. # Eliminated a bunch of ->netdev and hdlc_to_dev() uses. # # drivers/net/wan/hdlc_x25.c # 2004/01/10 18:52:43-05:00 viro@parcelfarce.linux.theplanet.co.uk +4 -4 # [wan hdlc] hdlc->proto.*() switched to net_device. # Eliminated a bunch of ->netdev and hdlc_to_dev() uses. # # drivers/net/wan/hdlc_ppp.c # 2004/01/10 18:52:43-05:00 viro@parcelfarce.linux.theplanet.co.uk +4 -4 # [wan hdlc] hdlc->proto.*() switched to net_device. # Eliminated a bunch of ->netdev and hdlc_to_dev() uses. # # drivers/net/wan/hdlc_generic.c # 2004/01/10 18:52:43-05:00 viro@parcelfarce.linux.theplanet.co.uk +6 -6 # [wan hdlc] hdlc->proto.*() switched to net_device. # Eliminated a bunch of ->netdev and hdlc_to_dev() uses. # # drivers/net/wan/hdlc_fr.c # 2004/01/10 18:52:43-05:00 viro@parcelfarce.linux.theplanet.co.uk +8 -5 # [wan hdlc] hdlc->proto.*() switched to net_device. # Eliminated a bunch of ->netdev and hdlc_to_dev() uses. # # drivers/net/wan/hdlc_cisco.c # 2004/01/10 18:52:43-05:00 viro@parcelfarce.linux.theplanet.co.uk +6 -5 # [wan hdlc] hdlc->proto.*() switched to net_device. # Eliminated a bunch of ->netdev and hdlc_to_dev() uses. # # ChangeSet # 2004/01/10 18:51:07-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan farsync] Eliminated a bunch of port->hdlc and hdlc_to_dev() uses # # drivers/net/wan/farsync.c # 2004/01/10 18:51:03-05:00 viro@parcelfarce.linux.theplanet.co.uk +34 -27 # [wan farsync] Eliminated a bunch of port->hdlc and hdlc_to_dev() uses # # ChangeSet # 2004/01/10 18:50:28-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc] hdlc->attach() switched to net_device. # # include/linux/hdlc.h # 2004/01/10 18:50:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc->attach() switched to net_device. # # drivers/net/wan/wanxl.c # 2004/01/10 18:50:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -2 # [wan hdlc] hdlc->attach() switched to net_device. # # drivers/net/wan/pc300_drv.c # 2004/01/10 18:50:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -3 # [wan hdlc] hdlc->attach() switched to net_device. # # drivers/net/wan/hdlc_x25.c # 2004/01/10 18:50:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc->attach() switched to net_device. # # drivers/net/wan/hdlc_raw_eth.c # 2004/01/10 18:50:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc->attach() switched to net_device. # # drivers/net/wan/hdlc_raw.c # 2004/01/10 18:50:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc->attach() switched to net_device. # # drivers/net/wan/hdlc_ppp.c # 2004/01/10 18:50:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc->attach() switched to net_device. # # drivers/net/wan/hdlc_fr.c # 2004/01/10 18:50:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc->attach() switched to net_device. # # drivers/net/wan/hdlc_cisco.c # 2004/01/10 18:50:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc->attach() switched to net_device. # # drivers/net/wan/hd6457x.c # 2004/01/10 18:50:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +4 -15 # [wan hdlc] hdlc->attach() switched to net_device. # # drivers/net/wan/farsync.c # 2004/01/10 18:50:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc->attach() switched to net_device. # # drivers/net/wan/dscc4.c # 2004/01/10 18:50:24-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -3 # [wan hdlc] hdlc->attach() switched to net_device. # # ChangeSet # 2004/01/10 18:49:55-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc] hdlc_set_carrier() switched to net_device. # # include/linux/hdlc.h # 2004/01/10 18:49:50-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc_set_carrier() switched to net_device. # # drivers/net/wan/wanxl.c # 2004/01/10 18:49:50-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc_set_carrier() switched to net_device. # # drivers/net/wan/hdlc_generic.c # 2004/01/10 18:49:50-05:00 viro@parcelfarce.linux.theplanet.co.uk +7 -6 # [wan hdlc] hdlc_set_carrier() switched to net_device. # # drivers/net/wan/hd6457x.c # 2004/01/10 18:49:50-05:00 viro@parcelfarce.linux.theplanet.co.uk +3 -3 # [wan hdlc] hdlc_set_carrier() switched to net_device. # # drivers/net/wan/c101.c # 2004/01/10 18:49:50-05:00 viro@parcelfarce.linux.theplanet.co.uk +3 -4 # [wan hdlc] hdlc_set_carrier() switched to net_device. # # ChangeSet # 2004/01/10 18:49:23-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc] switch sca_xxx() to use net_device # # More hd6457x.c massage: sca_open(), sca_close(), sca_dump_rings() switched # to net_device. Bunch of hdlc_to_port() eliminated in favor of dev_to_port(). # # drivers/net/wan/n2.c # 2004/01/10 18:49:18-05:00 viro@parcelfarce.linux.theplanet.co.uk +6 -9 # [wan hdlc] switch sca_xxx() to use net_device # # More hd6457x.c massage: sca_open(), sca_close(), sca_dump_rings() switched # to net_device. Bunch of hdlc_to_port() eliminated in favor of dev_to_port(). # # drivers/net/wan/hd6457x.c # 2004/01/10 18:49:18-05:00 viro@parcelfarce.linux.theplanet.co.uk +11 -12 # [wan hdlc] switch sca_xxx() to use net_device # # More hd6457x.c massage: sca_open(), sca_close(), sca_dump_rings() switched # to net_device. Bunch of hdlc_to_port() eliminated in favor of dev_to_port(). # # drivers/net/wan/c101.c # 2004/01/10 18:49:18-05:00 viro@parcelfarce.linux.theplanet.co.uk +7 -10 # [wan hdlc] switch sca_xxx() to use net_device # # More hd6457x.c massage: sca_open(), sca_close(), sca_dump_rings() switched # to net_device. Bunch of hdlc_to_port() eliminated in favor of dev_to_port(). # # ChangeSet # 2004/01/10 18:48:26-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc] new port_to_dev() helper # # New helper in hd6457x.c: port_to_dev(). A bunch of port->hdlc eliminated. # # drivers/net/wan/n2.c # 2004/01/10 18:48:21-05:00 viro@parcelfarce.linux.theplanet.co.uk +10 -7 # [wan hdlc] new port_to_dev() helper # # New helper in hd6457x.c: port_to_dev(). A bunch of port->hdlc eliminated. # # drivers/net/wan/hd6457x.c # 2004/01/10 18:48:21-05:00 viro@parcelfarce.linux.theplanet.co.uk +25 -15 # [wan hdlc] new port_to_dev() helper # # New helper in hd6457x.c: port_to_dev(). A bunch of port->hdlc eliminated. # # drivers/net/wan/c101.c # 2004/01/10 18:48:21-05:00 viro@parcelfarce.linux.theplanet.co.uk +14 -10 # [wan hdlc] new port_to_dev() helper # # New helper in hd6457x.c: port_to_dev(). A bunch of port->hdlc eliminated. # # ChangeSet # 2004/01/10 18:47:42-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc] hdlc_close() switched to net_device. # # include/linux/hdlc.h # 2004/01/10 18:47:37-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc_close() switched to net_device. # # drivers/net/wan/wanxl.c # 2004/01/10 18:47:37-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc_close() switched to net_device. # # drivers/net/wan/pc300_drv.c # 2004/01/10 18:47:37-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc_close() switched to net_device. # # drivers/net/wan/n2.c # 2004/01/10 18:47:37-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc_close() switched to net_device. # # drivers/net/wan/hdlc_generic.c # 2004/01/10 18:47:37-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -1 # [wan hdlc] hdlc_close() switched to net_device. # # drivers/net/wan/farsync.c # 2004/01/10 18:47:37-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc_close() switched to net_device. # # drivers/net/wan/dscc4.c # 2004/01/10 18:47:37-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -4 # [wan hdlc] hdlc_close() switched to net_device. # # drivers/net/wan/c101.c # 2004/01/10 18:47:37-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc_close() switched to net_device. # # ChangeSet # 2004/01/10 18:44:19-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan hdlc] hdlc_open() switched to net_device # # Beginning of hdlc fixes. hdlc_open() switched from hdlc_device to net_device. # # include/linux/hdlc.h # 2004/01/10 18:44:15-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc_open() switched to net_device # # Beginning of hdlc fixes. hdlc_open() switched from hdlc_device to net_device. # # drivers/net/wan/wanxl.c # 2004/01/10 18:44:15-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc_open() switched to net_device # # Beginning of hdlc fixes. hdlc_open() switched from hdlc_device to net_device. # # drivers/net/wan/pc300_drv.c # 2004/01/10 18:44:15-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc_open() switched to net_device # # Beginning of hdlc fixes. hdlc_open() switched from hdlc_device to net_device. # # drivers/net/wan/n2.c # 2004/01/10 18:44:14-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc_open() switched to net_device # # Beginning of hdlc fixes. hdlc_open() switched from hdlc_device to net_device. # # drivers/net/wan/hdlc_generic.c # 2004/01/10 18:44:14-05:00 viro@parcelfarce.linux.theplanet.co.uk +6 -5 # [wan hdlc] hdlc_open() switched to net_device # # Beginning of hdlc fixes. hdlc_open() switched from hdlc_device to net_device. # # drivers/net/wan/farsync.c # 2004/01/10 18:44:14-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc_open() switched to net_device # # Beginning of hdlc fixes. hdlc_open() switched from hdlc_device to net_device. # # drivers/net/wan/dscc4.c # 2004/01/10 18:44:14-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc_open() switched to net_device # # Beginning of hdlc fixes. hdlc_open() switched from hdlc_device to net_device. # # drivers/net/wan/c101.c # 2004/01/10 18:44:14-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan hdlc] hdlc_open() switched to net_device # # Beginning of hdlc fixes. hdlc_open() switched from hdlc_device to net_device. # # ChangeSet # 2004/01/10 18:39:13-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan lapb] kill now-unused custom token container # # Nothing is using lapb->token anymore; removed, along with the old "token" # argument of lapb_register(). # # net/lapb/lapb_iface.c # 2004/01/10 18:39:04-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -2 # [wan lapb] kill now-unused custom token container # # Nothing is using lapb->token anymore; removed, along with the old "token" # argument of lapb_register(). # # include/net/lapb.h # 2004/01/10 18:39:04-05:00 viro@parcelfarce.linux.theplanet.co.uk +0 -1 # [wan lapb] kill now-unused custom token container # # Nothing is using lapb->token anymore; removed, along with the old "token" # argument of lapb_register(). # # include/linux/lapb.h # 2004/01/10 18:39:04-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan lapb] kill now-unused custom token container # # Nothing is using lapb->token anymore; removed, along with the old "token" # argument of lapb_register(). # # drivers/net/wan/x25_asy.c # 2004/01/10 18:39:04-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan lapb] kill now-unused custom token container # # Nothing is using lapb->token anymore; removed, along with the old "token" # argument of lapb_register(). # # drivers/net/wan/lapbether.c # 2004/01/10 18:39:04-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -3 # [wan lapb] kill now-unused custom token container # # Nothing is using lapb->token anymore; removed, along with the old "token" # argument of lapb_register(). # # drivers/net/wan/hdlc_x25.c # 2004/01/10 18:39:04-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan lapb] kill now-unused custom token container # # Nothing is using lapb->token anymore; removed, along with the old "token" # argument of lapb_register(). # # drivers/net/wan/comx-proto-lapb.c # 2004/01/10 18:39:04-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan lapb] kill now-unused custom token container # # Nothing is using lapb->token anymore; removed, along with the old "token" # argument of lapb_register(). # # ChangeSet # 2004/01/10 18:38:24-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan lapb] Printks switched from %p lapb->token to %p lapb->dev. # # net/lapb/lapb_timer.c # 2004/01/10 18:38:14-05:00 viro@parcelfarce.linux.theplanet.co.uk +7 -7 # [wan lapb] Printks switched from %p lapb->token to %p lapb->dev. # # net/lapb/lapb_subr.c # 2004/01/10 18:38:14-05:00 viro@parcelfarce.linux.theplanet.co.uk +3 -3 # [wan lapb] Printks switched from %p lapb->token to %p lapb->dev. # # net/lapb/lapb_out.c # 2004/01/10 18:38:14-05:00 viro@parcelfarce.linux.theplanet.co.uk +6 -6 # [wan lapb] Printks switched from %p lapb->token to %p lapb->dev. # # net/lapb/lapb_in.c # 2004/01/10 18:38:14-05:00 viro@parcelfarce.linux.theplanet.co.uk +63 -63 # [wan lapb] Printks switched from %p lapb->token to %p lapb->dev. # # net/lapb/lapb_iface.c # 2004/01/10 18:38:14-05:00 viro@parcelfarce.linux.theplanet.co.uk +5 -5 # [wan lapb] Printks switched from %p lapb->token to %p lapb->dev. # # ChangeSet # 2004/01/10 18:37:28-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan lapb] switch to use net_device instead of custom token # # lapb functions that used to take a token to select lapb_cb they'll deal with # are switched to getting net_device instead. Callbacks switched to using # lapb->dev instead of lapb->token. # # net/lapb/lapb_iface.c # 2004/01/10 18:37:21-05:00 viro@parcelfarce.linux.theplanet.co.uk +25 -29 # [wan lapb] switch to use net_device instead of custom token # # lapb functions that used to take a token to select lapb_cb they'll deal with # are switched to getting net_device instead. Callbacks switched to using # lapb->dev instead of lapb->token. # # include/linux/lapb.h # 2004/01/10 18:37:21-05:00 viro@parcelfarce.linux.theplanet.co.uk +13 -13 # [wan lapb] switch to use net_device instead of custom token # # lapb functions that used to take a token to select lapb_cb they'll deal with # are switched to getting net_device instead. Callbacks switched to using # lapb->dev instead of lapb->token. # # drivers/net/wan/x25_asy.c # 2004/01/10 18:37:21-05:00 viro@parcelfarce.linux.theplanet.co.uk +12 -12 # [wan lapb] switch to use net_device instead of custom token # # lapb functions that used to take a token to select lapb_cb they'll deal with # are switched to getting net_device instead. Callbacks switched to using # lapb->dev instead of lapb->token. # # drivers/net/wan/lapbether.c # 2004/01/10 18:37:21-05:00 viro@parcelfarce.linux.theplanet.co.uk +13 -18 # [wan lapb] switch to use net_device instead of custom token # # lapb functions that used to take a token to select lapb_cb they'll deal with # are switched to getting net_device instead. Callbacks switched to using # lapb->dev instead of lapb->token. # # drivers/net/wan/hdlc_x25.c # 2004/01/10 18:37:21-05:00 viro@parcelfarce.linux.theplanet.co.uk +19 -21 # [wan lapb] switch to use net_device instead of custom token # # lapb functions that used to take a token to select lapb_cb they'll deal with # are switched to getting net_device instead. Callbacks switched to using # lapb->dev instead of lapb->token. # # drivers/net/wan/comx-proto-lapb.c # 2004/01/10 18:37:21-05:00 viro@parcelfarce.linux.theplanet.co.uk +23 -23 # [wan lapb] switch to use net_device instead of custom token # # lapb functions that used to take a token to select lapb_cb they'll deal with # are switched to getting net_device instead. Callbacks switched to using # lapb->dev instead of lapb->token. # # ChangeSet # 2004/01/10 18:36:15-05:00 viro@parcelfarce.linux.theplanet.co.uk # [wan lapb] beginning of cleanups # # Beginning of lapb cleanups: lapb_register gets net_device along with the # "token" and it gets stored in lapb_cb (token argument will die later). # # net/lapb/lapb_iface.c # 2004/01/10 18:36:10-05:00 viro@parcelfarce.linux.theplanet.co.uk +2 -1 # [wan lapb] beginning of cleanups # # Beginning of lapb cleanups: lapb_register gets net_device along with the # "token" and it gets stored in lapb_cb (token argument will die later). # # include/net/lapb.h # 2004/01/10 18:36:10-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -0 # [wan lapb] beginning of cleanups # # Beginning of lapb cleanups: lapb_register gets net_device along with the # "token" and it gets stored in lapb_cb (token argument will die later). # # include/linux/lapb.h # 2004/01/10 18:36:10-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan lapb] beginning of cleanups # # Beginning of lapb cleanups: lapb_register gets net_device along with the # "token" and it gets stored in lapb_cb (token argument will die later). # # drivers/net/wan/x25_asy.c # 2004/01/10 18:36:10-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan lapb] beginning of cleanups # # Beginning of lapb cleanups: lapb_register gets net_device along with the # "token" and it gets stored in lapb_cb (token argument will die later). # # drivers/net/wan/lapbether.c # 2004/01/10 18:36:10-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan lapb] beginning of cleanups # # Beginning of lapb cleanups: lapb_register gets net_device along with the # "token" and it gets stored in lapb_cb (token argument will die later). # # drivers/net/wan/hdlc_x25.c # 2004/01/10 18:36:10-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan lapb] beginning of cleanups # # Beginning of lapb cleanups: lapb_register gets net_device along with the # "token" and it gets stored in lapb_cb (token argument will die later). # # drivers/net/wan/comx-proto-lapb.c # 2004/01/10 18:36:10-05:00 viro@parcelfarce.linux.theplanet.co.uk +1 -1 # [wan lapb] beginning of cleanups # # Beginning of lapb cleanups: lapb_register gets net_device along with the # "token" and it gets stored in lapb_cb (token argument will die later). # # ChangeSet # 2004/01/10 16:47:03-05:00 amir.noam@intel.com # [PATCH] [bonding 2.6] Use the per-bond values of all remaining parameters # # Change usage of the all remaining global parameters to the per-bond # values. # # drivers/net/bonding/bond_main.c # 2004/01/10 11:46:59-05:00 amir.noam@intel.com +71 -52 # [PATCH] [bonding 2.6] Use the per-bond values of all remaining parameters # # Change usage of the all remaining global parameters to the per-bond # values. # # ChangeSet # 2004/01/10 16:46:50-05:00 amir.noam@intel.com # [PATCH] [bonding 2.6] Use the per-bond value of the bond_mode parameter # # Change usage of the global 'bond_mode' parameter to the per-bond # value. # # drivers/net/bonding/bond_main.c # 2004/01/10 11:46:45-05:00 amir.noam@intel.com +76 -71 # [PATCH] [bonding 2.6] Use the per-bond value of the bond_mode parameter # # Change usage of the global 'bond_mode' parameter to the per-bond # value. # # ChangeSet # 2004/01/10 16:46:38-05:00 amir.noam@intel.com # [PATCH] [bonding 2.6] Save parameters in a per-bond data structure # # - Save the bonding parameters in a per-bond data structure. # - Move all handling of the insmod parameters to bond_check_params(). # - Fix the handling of some warning messages regarding parameter use. # # drivers/net/bonding/bonding.h # 2004/01/10 11:46:33-05:00 amir.noam@intel.com +16 -1 # [PATCH] [bonding 2.6] Save parameters in a per-bond data structure # # - Save the bonding parameters in a per-bond data structure. # - Move all handling of the insmod parameters to bond_check_params(). # - Fix the handling of some warning messages regarding parameter use. # # drivers/net/bonding/bond_main.c # 2004/01/10 11:46:33-05:00 amir.noam@intel.com +99 -75 # [PATCH] [bonding 2.6] Save parameters in a per-bond data structure # # - Save the bonding parameters in a per-bond data structure. # - Move all handling of the insmod parameters to bond_check_params(). # - Fix the handling of some warning messages regarding parameter use. # # ChangeSet # 2004/01/10 16:46:26-05:00 shmulik.hen@intel.com # [netdrvr bonding] trivial - Update comment blocks and version field # # Update comment blocks, version field and copyright years to match all # the recent changes that were accepted into 2.4/2.6. # # include/linux/if_bonding.h # 2004/01/10 11:46:21-05:00 shmulik.hen@intel.com +4 -1 # [netdrvr bonding] trivial - Update comment blocks and version field # # Update comment blocks, version field and copyright years to match all # the recent changes that were accepted into 2.4/2.6. # # drivers/net/bonding/bonding.h # 2004/01/10 11:46:21-05:00 shmulik.hen@intel.com +3 -3 # [netdrvr bonding] trivial - Update comment blocks and version field # # Update comment blocks, version field and copyright years to match all # the recent changes that were accepted into 2.4/2.6. # # drivers/net/bonding/bond_main.c # 2004/01/10 11:46:21-05:00 shmulik.hen@intel.com +6 -0 # [netdrvr bonding] trivial - Update comment blocks and version field # # Update comment blocks, version field and copyright years to match all # the recent changes that were accepted into 2.4/2.6. # # drivers/net/bonding/bond_alb.h # 2004/01/10 11:46:21-05:00 shmulik.hen@intel.com +2 -2 # [netdrvr bonding] trivial - Update comment blocks and version field # # Update comment blocks, version field and copyright years to match all # the recent changes that were accepted into 2.4/2.6. # # drivers/net/bonding/bond_alb.c # 2004/01/10 11:46:21-05:00 shmulik.hen@intel.com +5 -2 # [netdrvr bonding] trivial - Update comment blocks and version field # # Update comment blocks, version field and copyright years to match all # the recent changes that were accepted into 2.4/2.6. # # drivers/net/bonding/bond_3ad.h # 2004/01/10 11:46:21-05:00 shmulik.hen@intel.com +2 -2 # [netdrvr bonding] trivial - Update comment blocks and version field # # Update comment blocks, version field and copyright years to match all # the recent changes that were accepted into 2.4/2.6. # # drivers/net/bonding/bond_3ad.c # 2004/01/10 11:46:21-05:00 shmulik.hen@intel.com +2 -2 # [netdrvr bonding] trivial - Update comment blocks and version field # # Update comment blocks, version field and copyright years to match all # the recent changes that were accepted into 2.4/2.6. # # Documentation/networking/ifenslave.c # 2004/01/10 11:46:21-05:00 shmulik.hen@intel.com +2 -2 # [netdrvr bonding] trivial - Update comment blocks and version field # # Update comment blocks, version field and copyright years to match all # the recent changes that were accepted into 2.4/2.6. # # ChangeSet # 2004/01/10 16:45:35-05:00 amir.noam@intel.com # [PATCH] [bonding 2.6] Fix compilation warning in bond_alb.c # # The IPX_TYPE_* constants and ipxhdr.ipx_type are u8 values, so we # shouldn't use __constant_htons(). # # drivers/net/bonding/bond_alb.c # 2004/01/10 11:45:30-05:00 amir.noam@intel.com +1 -2 # [PATCH] [bonding 2.6] Fix compilation warning in bond_alb.c # # The IPX_TYPE_* constants and ipxhdr.ipx_type are u8 values, so we # shouldn't use __constant_htons(). # # ChangeSet # 2004/01/10 16:45:24-05:00 amir.noam@intel.com # [netdrvr bonding] fix build breakage # # drivers/net/bonding/bond_main.c # 2004/01/10 11:45:19-05:00 amir.noam@intel.com +2 -2 # [netdrvr bonding] fix build breakage # # ChangeSet # 2004/01/10 16:44:01-05:00 scott.feldman@intel.com # [netdrvr e100] netpoll + fixes to speed/duplex forced settings # # * Preserve forced speed/duplex settings during close/open sequence. # * Reset PHY when going from autoneg to forced speed/duplex settings # using ethtool. # * Add netpoll support. # # drivers/net/e100.c # 2004/01/10 11:43:54-05:00 scott.feldman@intel.com +56 -43 # [netdrvr e100] netpoll + fixes to speed/duplex forced settings # # * Preserve forced speed/duplex settings during close/open sequence. # * Reset PHY when going from autoneg to forced speed/duplex settings # using ethtool. # * Add netpoll support. # # ChangeSet # 2004/01/10 16:41:26-05:00 amir.noam@intel.com # [netdrvr bonding] Add support for slaves that use ethtool_ops # # When collecting link information from slaves via ETHTOOL, first try # using the relevant ethtool_ops functions. # # drivers/net/bonding/bond_main.c # 2004/01/10 11:41:21-05:00 amir.noam@intel.com +49 -24 # [netdrvr bonding] Add support for slaves that use ethtool_ops # # When collecting link information from slaves via ETHTOOL, first try # using the relevant ethtool_ops functions. # # ChangeSet # 2004/01/10 16:41:17-05:00 amir.noam@intel.com # [netdrvr bonding] Releasing the original active slave causes mac address duplication # # When releasing the active slave in TLB/ALB modes, # bond_alb_deinit_slave() must be called before trying to select a new # active slave. # # drivers/net/bonding/bond_main.c # 2004/01/10 11:41:12-05:00 amir.noam@intel.com +20 -14 # [netdrvr bonding] Releasing the original active slave causes mac address duplication # # When releasing the active slave in TLB/ALB modes, # bond_alb_deinit_slave() must be called before trying to select a new # active slave. # # ChangeSet # 2004/01/10 16:41:08-05:00 amir.noam@intel.com # [netdrvr bonding] Cannot remove and re-enslave the original active slave # # In TLB/ALB modes, when enslaving a slave that has the bond's mac # address, allow the operation if no other slave has that address. # # Should be applied after the cleanup patch set. # # drivers/net/bonding/bond_alb.c # 2004/01/10 11:41:03-05:00 amir.noam@intel.com +12 -1 # [netdrvr bonding] Cannot remove and re-enslave the original active slave # # In TLB/ALB modes, when enslaving a slave that has the bond's mac # address, allow the operation if no other slave has that address. # # Should be applied after the cleanup patch set. # # ChangeSet # 2004/01/10 16:25:23-05:00 jgarzik@redhat.com # [netdrvr e100] include linux/moduleparam.h # # Fixes build. # # drivers/net/e100.c # 2004/01/10 11:25:18-05:00 jgarzik@redhat.com +1 -0 # [netdrvr e100] include linux/moduleparam.h # # Fixes build. # # ChangeSet # 2004/01/10 16:19:08-05:00 scott.feldman@intel.com # [e100] ICH6 IDs + ia64 memcpy fix + module_param # # * Add ICH6 device IDs. Devices funcionally equivalent to supported ICH5 # devices, but new IDs. # * Fixed unaligned access to casted skb->data (Matt Willcox # [willy@debian.org]). # * MODULE_PARM -> module_param # * Bug printk after register_netdev to identify nic details. # * misc cleanups. # # drivers/net/e100.c # 2004/01/10 11:19:02-05:00 scott.feldman@intel.com +30 -22 # [e100] ICH6 IDs + ia64 memcpy fix + module_param # # * Add ICH6 device IDs. Devices funcionally equivalent to supported ICH5 # devices, but new IDs. # * Fixed unaligned access to casted skb->data (Matt Willcox # [willy@debian.org]). # * MODULE_PARM -> module_param # * Bug printk after register_netdev to identify nic details. # * misc cleanups. # # ChangeSet # 2004/01/10 15:56:28-05:00 scott.feldman@intel.com # [netdrvr] e100 version 3 (complete rewrite) # # drivers/net/Makefile # 2004/01/10 15:56:24-05:00 scott.feldman@intel.com +1 -1 # [netdrvr] e100 version 3 (complete rewrite) # # drivers/net/Kconfig # 2004/01/10 15:56:24-05:00 scott.feldman@intel.com +6 -1 # [netdrvr] e100 version 3 (complete rewrite) # # drivers/net/e100.c # 2004/01/10 15:55:36-05:00 jgarzik@redhat.com +2299 -0 # # drivers/net/e100.c # 2004/01/10 15:55:36-05:00 jgarzik@redhat.com +0 -0 # BitKeeper file /spare/repo/netdev-2.6/e100-2/drivers/net/e100.c # # BitKeeper/deleted/.del-Makefile~9f880007babd58ba # 2004/01/10 15:55:12-05:00 jgarzik@redhat.com +0 -0 # Delete: drivers/net/e100/Makefile # # BitKeeper/deleted/.del-LICENSE~40a12f4e7633252 # 2004/01/10 15:55:12-05:00 jgarzik@redhat.com +0 -0 # Delete: drivers/net/e100/LICENSE # # BitKeeper/deleted/.del-e100_ucode.h~384509176e82d05 # 2004/01/10 15:55:00-05:00 jgarzik@redhat.com +0 -0 # Delete: drivers/net/e100/e100_ucode.h # # BitKeeper/deleted/.del-e100_test.c~ebd1b417a1ab8572 # 2004/01/10 15:55:00-05:00 jgarzik@redhat.com +0 -0 # Delete: drivers/net/e100/e100_test.c # # BitKeeper/deleted/.del-e100_phy.h~f780fab579855857 # 2004/01/10 15:55:00-05:00 jgarzik@redhat.com +0 -0 # Delete: drivers/net/e100/e100_phy.h # # BitKeeper/deleted/.del-e100_phy.c~fdd23d9aa3ea8275 # 2004/01/10 15:55:00-05:00 jgarzik@redhat.com +0 -0 # Delete: drivers/net/e100/e100_phy.c # # BitKeeper/deleted/.del-e100_main.c~1f2323e5431e5b51 # 2004/01/10 15:55:00-05:00 jgarzik@redhat.com +0 -0 # Delete: drivers/net/e100/e100_main.c # # BitKeeper/deleted/.del-e100_eeprom.c~4da67b6cefb196d3 # 2004/01/10 15:55:00-05:00 jgarzik@redhat.com +0 -0 # Delete: drivers/net/e100/e100_eeprom.c # # BitKeeper/deleted/.del-e100.h~faef1250768c2f84 # 2004/01/10 15:55:00-05:00 jgarzik@redhat.com +0 -0 # Delete: drivers/net/e100/e100.h # # BitKeeper/deleted/.del-e100_config.h~20873ac5a63b4a94 # 2004/01/10 15:54:59-05:00 jgarzik@redhat.com +0 -0 # Delete: drivers/net/e100/e100_config.h # # BitKeeper/deleted/.del-e100_config.c~8bcd39115026455b # 2004/01/10 15:54:59-05:00 jgarzik@redhat.com +0 -0 # Delete: drivers/net/e100/e100_config.c # diff -Nru a/Documentation/Changes b/Documentation/Changes --- a/Documentation/Changes Thu Feb 19 23:44:28 2004 +++ b/Documentation/Changes Thu Feb 19 23:44:28 2004 @@ -216,13 +216,6 @@ as root before you can use this. You'll probably also want to get the user-space microcode_ctl utility to use with this. -If you have compiled the driver as a module you may need to add -the following line: - -alias char-major-10-184 microcode - -to your /etc/modules.conf file. - Powertweak ---------- @@ -258,17 +251,6 @@ mknod /dev/ppp c 108 0 as root. - -If you build ppp support as modules, you will need the following in -your /etc/modules.conf file: - -alias char-major-108 ppp_generic -alias /dev/ppp ppp_generic -alias tty-ldisc-3 ppp_async -alias tty-ldisc-14 ppp_synctty -alias ppp-compress-21 bsd_comp -alias ppp-compress-24 ppp_deflate -alias ppp-compress-26 ppp_deflate If you use devfsd and build ppp support as modules, you will need the following in your /etc/devfsd.conf file: diff -Nru a/Documentation/CodingStyle b/Documentation/CodingStyle --- a/Documentation/CodingStyle Thu Feb 19 23:44:24 2004 +++ b/Documentation/CodingStyle Thu Feb 19 23:44:24 2004 @@ -1,42 +1,75 @@ - Linux kernel coding style + Linux kernel coding style This is a short document describing the preferred coding style for the linux kernel. Coding style is very personal, and I won't _force_ my views on anybody, but this is what goes for anything that I have to be able to maintain, and I'd prefer it for most other things too. Please -at least consider the points made here. +at least consider the points made here. First off, I'd suggest printing out a copy of the GNU coding standards, -and NOT read it. Burn them, it's a great symbolic gesture. +and NOT read it. Burn them, it's a great symbolic gesture. Anyway, here goes: Chapter 1: Indentation -Tabs are 8 characters, and thus indentations are also 8 characters. +Tabs are 8 characters, and thus indentations are also 8 characters. There are heretic movements that try to make indentations 4 (or even 2!) characters deep, and that is akin to trying to define the value of PI to -be 3. +be 3. Rationale: The whole idea behind indentation is to clearly define where a block of control starts and ends. Especially when you've been looking at your screen for 20 straight hours, you'll find it a lot easier to see -how the indentation works if you have large indentations. +how the indentation works if you have large indentations. Now, some people will claim that having 8-character indentations makes the code move too far to the right, and makes it hard to read on a 80-character terminal screen. The answer to that is that if you need more than 3 levels of indentation, you're screwed anyway, and should fix -your program. +your program. In short, 8-char indents make things easier to read, and have the added -benefit of warning you when you're nesting your functions too deep. -Heed that warning. +benefit of warning you when you're nesting your functions too deep. +Heed that warning. +Don't put multiple statements on a single line unless you have +something to hide: - Chapter 2: Placing Braces + if (condition) do_this; + do_something_everytime; + +Outside of comments, documentation and except in Kconfig, spaces are never +used for indentation, and the above example is deliberately broken. + +Get a decent editor and don't leave whitespace at the end of lines. + + + Chapter 2: Breaking long lines and strings + +Coding style is all about readability and maintainability using commonly +available tools. + +The limit on the length of lines is 80 columns and this is a hard limit. + +Statements longer than 80 columns will be broken into sensible chunks. +Descendants are always substantially shorter than the parent and are placed +substantially to the right. The same applies to function headers with a long +argument list. Long strings are as well broken into shorter strings. + +void fun(int a, int b, int c) +{ + if (condition) + printk(KERN_WARNING "Warning this is a long printk with " + "3 parameters a: %u b: %u " + "c: %u \n", a, b, c); + else + next_statement; +} + + Chapter 3: Placing Braces The other issue that always comes up in C styling is the placement of braces. Unlike the indent size, there are few technical reasons to @@ -59,7 +92,7 @@ Heretic people all over the world have claimed that this inconsistency is ... well ... inconsistent, but all right-thinking people know that (a) K&R are _right_ and (b) K&R are right. Besides, functions are -special anyway (you can't nest them in C). +special anyway (you can't nest them in C). Note that the closing brace is empty on a line of its own, _except_ in the cases where it is followed by a continuation of the same statement, @@ -79,60 +112,60 @@ } else { .... } - -Rationale: K&R. + +Rationale: K&R. Also, note that this brace-placement also minimizes the number of empty (or almost empty) lines, without any loss of readability. Thus, as the supply of new-lines on your screen is not a renewable resource (think 25-line terminal screens here), you have more empty lines to put -comments on. +comments on. - Chapter 3: Naming + Chapter 4: Naming C is a Spartan language, and so should your naming be. Unlike Modula-2 and Pascal programmers, C programmers do not use cute names like ThisVariableIsATemporaryCounter. A C programmer would call that variable "tmp", which is much easier to write, and not the least more -difficult to understand. +difficult to understand. HOWEVER, while mixed-case names are frowned upon, descriptive names for global variables are a must. To call a global function "foo" is a -shooting offense. +shooting offense. GLOBAL variables (to be used only if you _really_ need them) need to have descriptive names, as do global functions. If you have a function that counts the number of active users, you should call that -"count_active_users()" or similar, you should _not_ call it "cntusr()". +"count_active_users()" or similar, you should _not_ call it "cntusr()". Encoding the type of a function into the name (so-called Hungarian notation) is brain damaged - the compiler knows the types anyway and can check those, and it only confuses the programmer. No wonder MicroSoft -makes buggy programs. +makes buggy programs. LOCAL variable names should be short, and to the point. If you have -some random integer loop counter, it should probably be called "i". +some random integer loop counter, it should probably be called "i". Calling it "loop_counter" is non-productive, if there is no chance of it being mis-understood. Similarly, "tmp" can be just about any type of -variable that is used to hold a temporary value. +variable that is used to hold a temporary value. If you are afraid to mix up your local variable names, you have another -problem, which is called the function-growth-hormone-imbalance syndrome. -See next chapter. +problem, which is called the function-growth-hormone-imbalance syndrome. +See next chapter. - - Chapter 4: Functions + + Chapter 5: Functions Functions should be short and sweet, and do just one thing. They should fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24, -as we all know), and do one thing and do that well. +as we all know), and do one thing and do that well. The maximum length of a function is inversely proportional to the complexity and indentation level of that function. So, if you have a conceptually simple function that is just one long (but simple) case-statement, where you have to do lots of small things for a lot of -different cases, it's OK to have a longer function. +different cases, it's OK to have a longer function. However, if you have a complex function, and you suspect that a less-than-gifted first-year high-school student might not even @@ -140,41 +173,78 @@ maximum limits all the more closely. Use helper functions with descriptive names (you can ask the compiler to in-line them if you think it's performance-critical, and it will probably do a better job of it -than you would have done). +than you would have done). Another measure of the function is the number of local variables. They shouldn't exceed 5-10, or you're doing something wrong. Re-think the function, and split it into smaller pieces. A human brain can generally easily keep track of about 7 different things, anything more and it gets confused. You know you're brilliant, but maybe you'd like -to understand what you did 2 weeks from now. +to understand what you did 2 weeks from now. + + + Chapter 6: Centralized exiting of functions +Albeit deprecated by some people, the equivalent of the goto statement is +used frequently by compilers in form of the unconditional jump instruction. - Chapter 5: Commenting +The goto statement comes in handy when a function exits from multiple +locations and some common work such as cleanup has to be done. + +The rationale is: + +- unconditional statements are easier to understand and follow +- nesting is reduced +- errors by not updating individual exit points when making + modifications are prevented +- saves the compiler work to optimize redundant code away ;) + +int fun(int ) +{ + int result = 0; + char *buffer = kmalloc(SIZE); + + if (buffer == NULL) + return -ENOMEM; + + if (condition1) { + while (loop1) { + ... + } + result = 1; + goto out; + } + ... +out: + kfree(buffer); + return result; +} + + Chapter 7: Commenting Comments are good, but there is also a danger of over-commenting. NEVER try to explain HOW your code works in a comment: it's much better to write the code so that the _working_ is obvious, and it's a waste of -time to explain badly written code. +time to explain badly written code. -Generally, you want your comments to tell WHAT your code does, not HOW. +Generally, you want your comments to tell WHAT your code does, not HOW. Also, try to avoid putting comments inside a function body: if the function is so complex that you need to separately comment parts of it, -you should probably go back to chapter 4 for a while. You can make +you should probably go back to chapter 5 for a while. You can make small comments to note or warn about something particularly clever (or ugly), but try to avoid excess. Instead, put the comments at the head of the function, telling people what it does, and possibly WHY it does -it. +it. - Chapter 6: You've made a mess of it + Chapter 8: You've made a mess of it That's OK, we all do. You've probably been told by your long-time Unix user helper that "GNU emacs" automatically formats the C sources for you, and you've noticed that yes, it does do that, but the defaults it uses are less than desirable (in fact, they are worse than random typing - an infinite number of monkeys typing into GNU emacs would never -make a good program). +make a good program). So, you can either get rid of GNU emacs, or change it to use saner values. To do the latter, you can stick the following in your .emacs file: @@ -192,7 +262,7 @@ to add (setq auto-mode-alist (cons '("/usr/src/linux.*/.*\\.[ch]$" . linux-c-mode) - auto-mode-alist)) + auto-mode-alist)) to your .emacs file if you want to have linux-c-mode switched on automagically when you edit source files under /usr/src/linux. @@ -201,33 +271,36 @@ everything is lost: use "indent". Now, again, GNU indent has the same brain-dead settings that GNU emacs -has, which is why you need to give it a few command line options. +has, which is why you need to give it a few command line options. However, that's not too bad, because even the makers of GNU indent recognize the authority of K&R (the GNU people aren't evil, they are just severely misguided in this matter), so you just give indent the -options "-kr -i8" (stands for "K&R, 8 character indents"). +options "-kr -i8" (stands for "K&R, 8 character indents"), or use +"scripts/Lindent", which indents in the latest style. "indent" has a lot of options, and especially when it comes to comment -re-formatting you may want to take a look at the manual page. But -remember: "indent" is not a fix for bad programming. +re-formatting you may want to take a look at the man page. But +remember: "indent" is not a fix for bad programming. - Chapter 7: Configuration-files + Chapter 9: Configuration-files -For configuration options (arch/xxx/config.in, and all the Config.in files), +For configuration options (arch/xxx/Kconfig, and all the Kconfig files), somewhat different indentation is used. -An indention level of 3 is used in the code, while the text in the config- -options should have an indention-level of 2 to indicate dependencies. The -latter only applies to bool/tristate options. For other options, just use -common sense. An example: - -if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - tristate 'Apply nitroglycerine inside the keyboard (DANGEROUS)' CONFIG_BOOM - if [ "$CONFIG_BOOM" != "n" ]; then - bool ' Output nice messages when you explode' CONFIG_CHEER - fi -fi +Help text is indented with 2 spaces. + +if CONFIG_EXPERIMENTAL + tristate CONFIG_BOOM + default n + help + Apply nitroglycerine inside the keyboard (DANGEROUS) + bool CONFIG_CHEER + depends on CONFIG_BOOM + default y + help + Output nice messages when you explode +endif Generally, CONFIG_EXPERIMENTAL should surround all options not considered stable. All options that are known to trash data (experimental write- @@ -235,20 +308,20 @@ experimental options should be denoted (EXPERIMENTAL). - Chapter 8: Data structures + Chapter 10: Data structures Data structures that have visibility outside the single-threaded environment they are created and destroyed in should always have reference counts. In the kernel, garbage collection doesn't exist (and outside the kernel garbage collection is slow and inefficient), which -means that you absolutely _have_ to reference count all your uses. +means that you absolutely _have_ to reference count all your uses. Reference counting means that you can avoid locking, and allows multiple users to have access to the data structure in parallel - and not having to worry about the structure suddenly going away from under them just -because they slept or did something else for a while. +because they slept or did something else for a while. -Note that locking is _not_ a replacement for reference counting. +Note that locking is _not_ a replacement for reference counting. Locking is used to keep data structures coherent, while reference counting is a memory management technique. Usually both are needed, and they are not to be confused with each other. @@ -264,3 +337,87 @@ Remember: if another thread can find your data structure, and you don't have a reference count on it, you almost certainly have a bug. + + + Chapter 11: Macros, Enums, Inline functions and RTL + +Names of macros defining constants and labels in enums are capitalized. + +#define CONSTANT 0x12345 + +Enums are preferred when defining several related constants. + +CAPITALIZED macro names are appreciated but macros resembling functions +may be named in lower case. + +Generally, inline functions are preferable to macros resembling functions. + +Macros with multiple statements should be enclosed in a do - while block: + +#define macrofun(a,b,c) \ + do { \ + if (a == 5) \ + do_this(b,c); \ + } while (0) + +Things to avoid when using macros: + +1) macros that affect control flow: + +#define FOO(x) \ + do { \ + if (blah(x) < 0) \ + return -EBUGGERED; \ + } while(0) + +is a _very_ bad idea. It looks like a function call but exits the "calling" +function; don't break the internal parsers of those who will read the code. + +2) macros that depend on having a local variable with a magic name: + +#define FOO(val) bar(index, val) + +might look like a good thing, but it's confusing as hell when one reads the +code and it's prone to breakage from seemingly innocent changes. + +3) macros with arguments that are used as l-values: FOO(x) = y; will +bite you if somebody e.g. turns FOO into an inline function. + +4) forgetting about precedence: macros defining constants using expressions +must enclose the expression in parentheses. Beware of similar issues with +macros using parameters. + +#define CONSTANT 0x4000 +#define CONSTEXP (CONSTANT | 3) + +The cpp manual deals with macros exhaustively. The gcc internals manual also +covers RTL which is used frequently with assembly language in the kernel. + + + Chapter 12: Printing kernel messages + +Kernel developers like to be seen as literate. Do mind the spelling +of kernel messages to make a good impression. Do not use crippled +words like "dont" and use "do not" or "don't" instead. + +Kernel messages do not have to be terminated with a period. + +Printing numbers in parentheses (%d) adds no value and should be avoided. + + + Chapter 13: References + +The C Programming Language, Second Edition +by Brian W. Kernighan and Dennis M. Ritchie. +Prentice Hall, Inc., 1988. +ISBN 0-13-110362-8 (paperback), 0-13-110370-9 (hardback). + +The Practice of Programming +Brian W. Kernighan, Rob Pike +Addison-Wesley, 1999, ISBN 0-201-61586-X + +GNU manuals - where in compliance with K&R and this text - for cpp, gcc, +gcc internals and indent, all available from www.gnu.org. + +-- +Last updated on 16 February 2004 by a community effort on LKML. diff -Nru a/Documentation/computone.txt b/Documentation/computone.txt --- a/Documentation/computone.txt Thu Feb 19 23:44:27 2004 +++ b/Documentation/computone.txt Thu Feb 19 23:44:27 2004 @@ -41,11 +41,11 @@ Note the hardware address from the Computone ISA cards installed into the system. These are required for editing ip2.c or editing - /etc/modules.conf, or for specification on the modprobe + /etc/modprobe.conf, or for specification on the modprobe command line. - Note that the /etc/modules.conf file is named /etc/conf.modules - with older versions of the module utilities. + Note that the /etc/modules.conf should be used for older (pre-2.6) + kernels. Software - @@ -58,7 +58,7 @@ c) Set address on ISA cards then: edit /usr/src/linux/drivers/char/ip2.c if needed or - edit /etc/modules.conf if needed (module). + edit /etc/modprobe.conf if needed (module). or both to match this setting. d) Run "make modules" e) Run "make modules_install" @@ -145,11 +145,11 @@ selects polled mode). If no base addresses are specified the defaults in ip2.c are used. If you are autoloading the driver module with kerneld or kmod the base addresses and interrupt number must also be set in ip2.c -and recompile or just insert and options line in /etc/modules.conf or both. +and recompile or just insert and options line in /etc/modprobe.conf or both. The options line is equivalent to the command line and takes precidence over what is in ip2.c. -/etc/modules.conf sample: +/etc/modprobe.conf sample: options ip2 io=1,0x328 irq=1,10 alias char-major-71 ip2 alias char-major-72 ip2 diff -Nru a/Documentation/crypto/api-intro.txt b/Documentation/crypto/api-intro.txt --- a/Documentation/crypto/api-intro.txt Thu Feb 19 23:44:26 2004 +++ b/Documentation/crypto/api-intro.txt Thu Feb 19 23:44:26 2004 @@ -68,7 +68,7 @@ CONFIGURATION NOTES As Triple DES is part of the DES module, for those using modular builds, -add the following line to /etc/modules.conf: +add the following line to /etc/modprobe.conf: alias des3_ede des diff -Nru a/Documentation/debugging-modules.txt b/Documentation/debugging-modules.txt --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/debugging-modules.txt Thu Feb 19 23:44:29 2004 @@ -0,0 +1,18 @@ +Debugging Modules after 2.6.3 +----------------------------- + +In almost all distributions, the kernel asks for modules which don't +exist, such as "net-pf-10" or whatever. Changing "modprobe -q" to +"succeed" in this case is hacky and breaks some setups, and also we +want to know if it failed for the fallback code for old aliases in +fs/char_dev.c, for example. + +In the past a debugging message which would fill people's logs was +emitted. This debugging message has been removed. The correct way +of debugging module problems is something like this: + +echo '#! /bin/sh' > /tmp/modprobe +echo 'echo "$@" >> /tmp/modprobe.log' >> /tmp/modprobe +echo 'exec /sbin/modprobe "$@"' >> /tmp/modprobe +chmod a+x /tmp/modprobe +echo /tmp/modprobe > /proc/sys/kernel/modprobe diff -Nru a/Documentation/digiboard.txt b/Documentation/digiboard.txt --- a/Documentation/digiboard.txt Thu Feb 19 23:44:25 2004 +++ b/Documentation/digiboard.txt Thu Feb 19 23:44:25 2004 @@ -24,7 +24,7 @@ The pcxx driver can be configured using the command line feature while loading the kernel with LILO or LOADLIN or, if built as a module, with arguments to insmod and modprobe or with parameters in -/etc/modules.conf for modprobe and kerneld. +/etc/modprobe.conf for modprobe and kerneld. After configuring the driver you need to create the device special files as described in "Device file creation:" below and set the appropriate @@ -91,13 +91,13 @@ The remaining board still uses ttyD8-ttyD15 and cud8-cud15. -Example line for /etc/modules.conf for use with kerneld and as default +Example line for /etc/modprobe.conf for use with kerneld and as default parameters for modprobe: options pcxx io=0x200 numports=8 -For kerneld to work you will likely need to add these two lines to your -/etc/modules.conf: +For kmod to work you will likely need to add these two lines to your +/etc/modprobe.conf: alias char-major-22 pcxx alias char-major-23 pcxx diff -Nru a/Documentation/fb/intel810.txt b/Documentation/fb/intel810.txt --- a/Documentation/fb/intel810.txt Thu Feb 19 23:44:26 2004 +++ b/Documentation/fb/intel810.txt Thu Feb 19 23:44:26 2004 @@ -194,7 +194,7 @@ modprobe i810fb vram=2 xres=1024 bpp=8 hsync1=30 hsync2=55 vsync1=50 \ vsync2=85 accel=1 mtrr=1 -Or just add the following to /etc/modules.conf +Or just add the following to /etc/modprobe.conf options i810fb vram=2 xres=1024 bpp=16 hsync1=30 hsync2=55 vsync1=50 \ vsync2=85 accel=1 mtrr=1 diff -Nru a/Documentation/filesystems/jfs.txt b/Documentation/filesystems/jfs.txt --- a/Documentation/filesystems/jfs.txt Thu Feb 19 23:44:26 2004 +++ b/Documentation/filesystems/jfs.txt Thu Feb 19 23:44:26 2004 @@ -12,10 +12,9 @@ The following mount options are supported: iocharset=name Character set to use for converting from Unicode to - ASCII. The default is compiled into the kernel as - CONFIG_NLS_DEFAULT. Use iocharset=utf8 for UTF8 - translations. This requires CONFIG_NLS_UTF8 to be set - in the kernel .config file. + ASCII. The default is to do no conversion. Use + iocharset=utf8 for UTF8 translations. This requires + CONFIG_NLS_UTF8 to be set in the kernel .config file. resize=value Resize the volume to blocks. JFS only supports growing a volume, not shrinking it. This option is only @@ -35,18 +34,6 @@ errors=continue Keep going on a filesystem error. errors=remount-ro Default. Remount the filesystem read-only on an error. errors=panic Panic and halt the machine if an error occurs. - -JFS TODO list: - -Plans for our near term development items - - - enhance support for logfile on dedicated partition - -Longer term work items - - - implement defrag utility, for online defragmenting - - add quota support - - add support for block sizes (512,1024,2048) Please send bugs, comments, cards and letters to shaggy@austin.ibm.com. diff -Nru a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt --- a/Documentation/filesystems/proc.txt Thu Feb 19 23:44:24 2004 +++ b/Documentation/filesystems/proc.txt Thu Feb 19 23:44:24 2004 @@ -900,6 +900,15 @@ Every mounted file system needs a super block, so if you plan to mount lots of file systems, you may want to increase these numbers. +aio-nr and aio-max-nr +--------------------- + +aio-nr is the running total of the number of events specified on the +io_setup system call for all currently active aio contexts. If aio-nr +reaches aio-max-nr then io_setup will fail with EAGAIN. Note that +raising aio-max-nr does not result in the pre-allocation or re-sizing +of any kernel data structures. + 2.2 /proc/sys/fs/binfmt_misc - Miscellaneous binary formats ----------------------------------------------------------- diff -Nru a/Documentation/ftape.txt b/Documentation/ftape.txt --- a/Documentation/ftape.txt Thu Feb 19 23:44:23 2004 +++ b/Documentation/ftape.txt Thu Feb 19 23:44:23 2004 @@ -242,15 +242,15 @@ Module parameters can be specified either directly when invoking the program 'insmod' at the shell prompt: - insmod ftape.o ft_tracing=4 + modprobe ftape ft_tracing=4 - or by editing the file `/etc/modules.conf' in which case they take + or by editing the file `/etc/modprobe.conf' in which case they take effect each time when the module is loaded with `modprobe' (please refer to the respective manual pages). Thus, you should add a line options ftape ft_tracing=4 - to `/etc/modules.conf` if you intend to increase the debugging + to `/etc/modprobe.conf` if you intend to increase the debugging output of the driver. @@ -298,7 +298,7 @@ 5. Example module parameter setting ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ To do the same, but with ftape compiled as a loadable kernel - module, add the following line to `/etc/modules.conf': + module, add the following line to `/etc/modprobe.conf': options ftape ft_probe_fc10=1 ft_tracing=4 diff -Nru a/Documentation/hayes-esp.txt b/Documentation/hayes-esp.txt --- a/Documentation/hayes-esp.txt Thu Feb 19 23:44:23 2004 +++ b/Documentation/hayes-esp.txt Thu Feb 19 23:44:23 2004 @@ -109,7 +109,7 @@ insmod esp dma=3 trigger=512 The esp module can be automatically loaded when needed. To cause this to -happen, add the following lines to /etc/modules.conf (replacing the last line +happen, add the following lines to /etc/modprobe.conf (replacing the last line with options for your configuration): alias char-major-57 esp diff -Nru a/Documentation/ide.txt b/Documentation/ide.txt --- a/Documentation/ide.txt Thu Feb 19 23:44:26 2004 +++ b/Documentation/ide.txt Thu Feb 19 23:44:26 2004 @@ -198,12 +198,11 @@ can only be compiled into the kernel, and the core code (ide.c) can be compiled as a loadable module provided no chipset support is needed. -When using ide.c/ide-tape.c as modules in combination with kerneld, add: +When using ide.c as a module in combination with kmod, add: alias block-major-3 ide-probe - alias char-major-37 ide-tape -respectively to /etc/modules.conf. +to /etc/modprobe.conf. When ide.c is used as a module, you can pass command line parameters to the driver using the "options=" keyword to insmod, while replacing any ',' with @@ -231,9 +230,10 @@ "hdx=cyl,head,sect" : disk drive is present, with specified geometry - "hdx=remap" : remap access of sector 0 to sector 1 (for EZD) + "hdx=remap" : remap access of sector 0 to sector 1 (for EZDrive) - "hdx=remap63" : remap the drive: shift all by 63 sectors (for DM) + "hdx=remap63" : remap the drive: add 63 to all sector numbers + (for DM OnTrack) "hdx=autotune" : driver will attempt to tune interface speed to the fastest PIO mode supported, @@ -242,16 +242,9 @@ and quite likely to cause trouble with older/odd IDE drives. - "hdx=slow" : insert a huge pause after each access to the data - port. Should be used only as a last resort. - "hdx=swapdata" : when the drive is a disk, byte swap all data "hdx=bswap" : same as above.......... - - "hdx=flash" : allows for more than one ata_flash disk to be - registered. In most cases, only one device - will be present. "hdx=scsi" : the return of the ide-scsi flag, this is useful for allowing ide-floppy, ide-tape, and ide-cdrom|writers diff -Nru a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt --- a/Documentation/kbuild/modules.txt Thu Feb 19 23:44:27 2004 +++ b/Documentation/kbuild/modules.txt Thu Feb 19 23:44:27 2004 @@ -17,12 +17,52 @@ Compiling modules outside the official kernel --------------------------------------------- -Often modules are developed outside the official kernel. -To keep up with changes in the build system the most portable way -to compile a module outside the kernel is to use the following command-line: + +Often modules are developed outside the official kernel. To keep up +with changes in the build system the most portable way to compile a +module outside the kernel is to use the kernel build system, +kbuild. Use the following command-line: make -C path/to/kernel/src SUBDIRS=$PWD modules This requires that a makefile exits made in accordance to -Documentation/kbuild/makefiles.txt. +Documentation/kbuild/makefiles.txt. Read that file for more details on +the build system. + +The following is a short summary of how to write your Makefile to get +you up and running fast. Assuming your module will be called +yourmodule.ko, your code should be in yourmodule.c and your Makefile +should include + +obj-m := yourmodule.o + +If the code for your module is in multiple files that need to be +linked, you need to tell the build system which files to compile. In +the case of multiple files, none of these files can be named +yourmodule.c because doing so would cause a problem with the linking +step. Assuming your code exists in file1.c, file2.c, and file3.c and +you want to build yourmodule.ko from them, your Makefile should +include + +obj-m := yourmodule.o +yourmodule-objs := file1.o file2.o file3.o + +Now for a final example to put it all together. Assuming the +KERNEL_SOURCE environment variable is set to the directory where you +compiled the kernel, a simple Makefile that builds yourmodule.ko as +described above would look like + +# Tells the build system to build yourmodule.ko. +obj-m := yourmodule.o + +# Tells the build system to build these object files and link them as +# yourmodule.o, before building yourmodule.ko. This line can be left +# out if all the code for your module is in one file, yourmodule.c. If +# you are using multiple files, none of these files can be named +# yourmodule.c. +yourmodule-objs := file1.o file2.o file3.o +# Invokes the kernel build system to come back to the current +# directory and build yourmodule.ko. +default: + make -C ${KERNEL_SOURCE} SUBDIRS=`pwd` modules diff -Nru a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt --- a/Documentation/kernel-parameters.txt Thu Feb 19 23:44:29 2004 +++ b/Documentation/kernel-parameters.txt Thu Feb 19 23:44:29 2004 @@ -237,7 +237,7 @@ Forces specified timesource (if avaliable) to be used when calculating gettimeofday(). If specicified timesource is not avalible, it defaults to PIT. - Format: { pit | tsc | cyclone | ... } + Format: { pit | tsc | cyclone | pmtmr } hpet= [IA-32,HPET] option to disable HPET and use PIT. Format: disable @@ -292,6 +292,9 @@ devfs= [DEVFS] See Documentation/filesystems/devfs/boot-options. + + dhash_entries= [KNL] + Set number of hash buckets for dentry cache. digi= [HW,SERIAL] IO parameters + enable/disable command. @@ -310,6 +313,23 @@ dtc3181e= [HW,SCSI] + earlyprintk= [x86, x86_64] + early_printk=vga + early_printk=serial[,ttySn[,baudrate]] + + Append ,keep to not disable it when the real console + takes over. + + Only vga or serial at a time, not both. + + Currently only ttyS0 and ttyS1 are supported. + + Interaction with the standard serial driver is not + very good. + + The VGA output is eventually overwritten by the real + console. + eata= [HW,SCSI] eda= [HW,PS2] @@ -424,6 +444,9 @@ idle= [HW] Format: idle=poll or idle=halt + ihash_entries= [KNL] + Set number of hash buckets for inode cache. + in2000= [HW,SCSI] See header of drivers/scsi/in2000.c. @@ -873,6 +896,9 @@ resume= [SWSUSP] Specify the partition device for software suspension + rhash_entries= [KNL,NET] + Set number of hash buckets for route cache + riscom8= [HW,SERIAL] Format: [,[,...]] @@ -1134,6 +1160,9 @@ tgfx= [HW,JOY] TurboGraFX parallel port interface tgfx_2= See Documentation/input/joystick-parport.txt. tgfx_3= + + thash_entries= [KNL,NET] + Set number of hash buckets for TCP connection tipar= [HW] See header of drivers/char/tipar.c. diff -Nru a/Documentation/networking/baycom.txt b/Documentation/networking/baycom.txt --- a/Documentation/networking/baycom.txt Thu Feb 19 23:44:27 2004 +++ b/Documentation/networking/baycom.txt Thu Feb 19 23:44:27 2004 @@ -93,10 +93,10 @@ modems it should access at which ports. This can be done with the setbaycom utility. If you are only using one modem, you can also configure the driver from the insmod command line (or by means of an option line in -/etc/modules.conf). +/etc/modprobe.conf). Examples: - insmod baycom_ser_fdx mode="ser12*" iobase=0x3f8 irq=4 + modprobe baycom_ser_fdx mode="ser12*" iobase=0x3f8 irq=4 sethdlc -i bcsf0 -p mode "ser12*" io 0x3f8 irq 4 Both lines configure the first port to drive a ser12 modem at the first diff -Nru a/Documentation/networking/bonding.txt b/Documentation/networking/bonding.txt --- a/Documentation/networking/bonding.txt Thu Feb 19 23:44:24 2004 +++ b/Documentation/networking/bonding.txt Thu Feb 19 23:44:24 2004 @@ -31,6 +31,7 @@ Frequently Asked Questions High Availability Promiscuous Sniffing notes +8021q VLAN support Limitations Resources and Links @@ -73,9 +74,9 @@ Bond Configuration ================== -You will need to add at least the following line to /etc/modules.conf +You will need to add at least the following line to /etc/modprobe.conf so the bonding driver will automatically load when the bond0 interface is -configured. Refer to the modules.conf manual page for specific modules.conf +configured. Refer to the modprobe.conf manual page for specific modprobe.conf syntax details. The Module Parameters section of this document describes each bonding driver parameter. @@ -132,18 +133,14 @@ appropriate rc directory. If you specifically need all network drivers loaded before the bonding driver, -adding the following line to modules.conf will cause the network driver for +adding the following line to modprobe.conf will cause the network driver for eth0 and eth1 to be loaded before the bonding driver. -probeall bond0 eth0 eth1 bonding +install bond0 /sbin/modprobe -a eth0 eth1 && /sbin/modprobe bonding Be careful not to reference bond0 itself at the end of the line, or modprobe will die in an endless recursive loop. -To have device characteristics (such as MTU size) propagate to slave devices, -set the bond characteristics before enslaving the device. The characteristics -are propagated during the enslave process. - If running SNMP agents, the bonding driver should be loaded before any network drivers participating in a bond. This requirement is due to the the interface index (ipAdEntIfIndex) being associated to the first interface found with a @@ -191,7 +188,7 @@ Optional parameters for the bonding driver can be supplied as command line arguments to the insmod command. Typically, these parameters are specified in -the file /etc/modules.conf (see the manual page for modules.conf). The +the file /etc/modprobe.conf (see the manual page for modprobe.conf). The available bonding driver parameters are listed below. If a parameter is not specified the default value is used. When initially configuring a bond, it is recommended "tail -f /var/log/messages" be run in a separate window to @@ -601,7 +598,7 @@ For ethernet cards not supporting MII status, the arp_interval and arp_ip_target parameters must be specified for bonding to work correctly. If packets have not been sent or received during the - specified arp_interval durration, an ARP request is sent to the + specified arp_interval duration, an ARP request is sent to the targets to generate send and receive traffic. If after this interval, either the successful send and/or receive count has not incremented, the next slave in the sequence will become the active @@ -669,16 +666,8 @@ that will be added. To restore your slaves' MAC addresses, you need to detach them - from the bond (`ifenslave -d bond0 eth0'), set them down - (`ifconfig eth0 down'), unload the drivers (`rmmod 3c59x', for - example) and reload them to get the MAC addresses from their - eeproms. If the driver is shared by several devices, you need - to turn them all down. Another solution is to look for the MAC - address at boot time (dmesg or tail /var/log/messages) and to - reset it by hand with ifconfig : - - # ifconfig eth0 down - # ifconfig eth0 hw ether 00:20:40:60:80:A0 + from the bond (`ifenslave -d bond0 eth0'). The bonding driver will then + restore the MAC addresses that the slaves had before they were enslaved. 9. Which transmit polices can be used? @@ -742,9 +731,8 @@ # modprobe bonding miimon=100 -Or, put the following lines in /etc/modules.conf: +Or, put the following line in /etc/modprobe.conf: - alias bond0 bonding options bond0 miimon=100 There are currently two policies for high availability. They are dependent on @@ -815,9 +803,8 @@ # modprobe bonding miimon=100 mode=1 -Or, put in your /etc/modules.conf : +Or, put in your /etc/modprobe.conf : - alias bond0 bonding options bond0 miimon=100 mode=active-backup Example 1: Using multiple host and multiple switches to build a "no single @@ -843,7 +830,7 @@ In this configuration, there is an ISL - Inter Switch Link (could be a trunk), several servers (host1, host2 ...) attached to both switches each, and one or -more ports to the outside world (port3...). One an only one slave on each host +more ports to the outside world (port3...). One and only one slave on each host is active at a time, while all links are still monitored (the system can detect a failure of active and backup links). @@ -919,7 +906,6 @@ must add the promisc flag there; it will be propagated down to the slave interfaces at ifenslave time; a full example might look like: - grep bond0 /etc/modules.conf || echo alias bond0 bonding >/etc/modules.conf ifconfig bond0 promisc up for if in eth1 eth2 ...;do ifconfig $if up @@ -931,6 +917,41 @@ interface, appropriately for its design functions in HA and channel capacity aggregating; but it works fine for unnumbered interfaces; just ignore all the warnings it emits. + + +8021q VLAN support +================== + +It is possible to configure VLAN devices over a bond interface using the 8021q +driver. However, only packets coming from the 8021q driver and passing through +bonding will be tagged by default. Self generated packets, like bonding's +learning packets or ARP packets generated by either ALB mode or the ARP +monitor mechanism, are tagged internally by bonding itself. As a result, +bonding has to "learn" what VLAN IDs are configured on top of it, and it uses +those IDs to tag self generated packets. + +For simplicity reasons, and to support the use of adapters that can do VLAN +hardware acceleration offloding, the bonding interface declares itself as +fully hardware offloaing capable, it gets the add_vid/kill_vid notifications +to gather the necessary information, and it propagates those actions to the +slaves. +In case of mixed adapter types, hardware accelerated tagged packets that should +go through an adapter that is not offloading capable are "un-accelerated" by the +bonding driver so the VLAN tag sits in the regular location. + +VLAN interfaces *must* be added on top of a bonding interface only after +enslaving at least one slave. This is because until the first slave is added the +bonding interface has a HW address of 00:00:00:00:00:00, which will be copied by +the VLAN interface when it is created. + +Notice that a problem would occur if all slaves are released from a bond that +still has VLAN interfaces on top of it. When later coming to add new slaves, the +bonding interface would get a HW address from the first slave, which might not +match that of the VLAN interfaces. It is recommended that either all VLANs are +removed and then re-added, or to manually set the bonding interface's HW +address so it matches the VLAN's. (Note: changing a VLAN interface's HW address +would set the underlying device -- i.e. the bonding interface -- to promiscouos +mode, which might not be what you want). Limitations diff -Nru a/Documentation/networking/dl2k.txt b/Documentation/networking/dl2k.txt --- a/Documentation/networking/dl2k.txt Thu Feb 19 23:44:26 2004 +++ b/Documentation/networking/dl2k.txt Thu Feb 19 23:44:26 2004 @@ -37,15 +37,15 @@ Install linux driver as following command: 1. make all -2. insmod dl2k.o +2. insmod dl2k.ko 3. ifconfig eth0 up 10.xxx.xxx.xxx netmask 255.0.0.0 ^^^^^^^^^^^^^^^\ ^^^^^^^^\ IP NETMASK Now eth0 should active, you can test it by "ping" or get more information by "ifconfig". If tested ok, continue the next step. -4. cp dl2k.o /lib/modules/`uname -r`/kernel/drivers/net -5. Add the following lines to /etc/modules.conf: +4. cp dl2k.ko /lib/modules/`uname -r`/kernel/drivers/net +5. Add the following line to /etc/modprobe.conf: alias eth0 dl2k 6. Run "netconfig" or "netconf" to create configuration script ifcfg-eth0 located at /etc/sysconfig/network-scripts or create it manually. @@ -154,8 +154,8 @@ ----------------- 1. Copy dl2k.o to the network modules directory, typically /lib/modules/2.x.x-xx/net or /lib/modules/2.x.x/kernel/drivers/net. - 2. Locate the boot module configuration file, most commonly modules.conf - or conf.modules in the /etc directory. Add the following lines: + 2. Locate the boot module configuration file, most commonly modprobe.conf + or modules.conf (for 2.4) in the /etc directory. Add the following lines: alias ethx dl2k options dl2k diff -Nru a/Documentation/networking/ifenslave.c b/Documentation/networking/ifenslave.c --- a/Documentation/networking/ifenslave.c Thu Feb 19 23:44:23 2004 +++ b/Documentation/networking/ifenslave.c Thu Feb 19 23:44:23 2004 @@ -89,13 +89,13 @@ * while it is running. It was already set during enslave. To * simplify things, it is now handeled separately. * - * - 2003/09/24 - Shmulik Hen + * - 2003/12/01 - Shmulik Hen * - Code cleanup and style changes * set version to 1.1.0 */ #define APP_VERSION "1.1.0" -#define APP_RELDATE "Septemer 24, 2003" +#define APP_RELDATE "December 1, 2003" #define APP_NAME "ifenslave" static char *version = diff -Nru a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt --- a/Documentation/networking/ip-sysctl.txt Thu Feb 19 23:44:24 2004 +++ b/Documentation/networking/ip-sysctl.txt Thu Feb 19 23:44:24 2004 @@ -499,6 +499,55 @@ conf/{all,interface}/arp_filter is set to TRUE, it will be disabled otherwise +arp_announce - INTEGER + Define different restriction levels for announcing the local + source IP address from IP packets in ARP requests sent on + interface: + 0 - (default) Use any local address, configured on any interface + 1 - Try to avoid local addresses that are not in the target's + subnet for this interface. This mode is useful when target + hosts reachable via this interface require the source IP + address in ARP requests to be part of their logical network + configured on the receiving interface. When we generate the + request we will check all our subnets that include the + target IP and will preserve the source address if it is from + such subnet. If there is no such subnet we select source + address according to the rules for level 2. + 2 - Always use the best local address for this target. + In this mode we ignore the source address in the IP packet + and try to select local address that we prefer for talks with + the target host. Such local address is selected by looking + for primary IP addresses on all our subnets on the outgoing + interface that include the target IP address. If no suitable + local address is found we select the first local address + we have on the outgoing interface or on all other interfaces, + with the hope we will receive reply for our request and + even sometimes no matter the source IP address we announce. + + The max value from conf/{all,interface}/arp_announce is used. + + Increasing the restriction level gives more chance for + receiving answer from the resolved target while decreasing + the level announces more valid sender's information. + +arp_ignore - INTEGER + Define different modes for sending replies in response to + received ARP requests that resolve local target IP addresses: + 0 - (default): reply for any local target IP address, configured + on any interface + 1 - reply only if the target IP address is local address + configured on the incoming interface + 2 - reply only if the target IP address is local address + configured on the incoming interface and both with the + sender's IP address are part from same subnet on this interface + 3 - do not reply for local addresses configured with scope host, + only resolutions for global and link addresses are replied + 4-7 - reserved + 8 - do not reply for all local addresses + + The max value from conf/{all,interface}/arp_ignore is used + when ARP request is received on the {interface} + tag - INTEGER Allows you to write a number, which can be used as required. Default value is 0. diff -Nru a/Documentation/networking/ltpc.txt b/Documentation/networking/ltpc.txt --- a/Documentation/networking/ltpc.txt Thu Feb 19 23:44:27 2004 +++ b/Documentation/networking/ltpc.txt Thu Feb 19 23:44:27 2004 @@ -25,7 +25,7 @@ If you load the driver as a module, you can pass the parameters "io=", "irq=", and "dma=" on the command line with insmod or modprobe, or add -them as options in /etc/modules.conf: +them as options in /etc/modprobe.conf: alias lt0 ltpc # autoload the module when the interface is configured options ltpc io=0x240 irq=9 dma=1 diff -Nru a/Documentation/networking/sk98lin.txt b/Documentation/networking/sk98lin.txt --- a/Documentation/networking/sk98lin.txt Thu Feb 19 23:44:26 2004 +++ b/Documentation/networking/sk98lin.txt Thu Feb 19 23:44:26 2004 @@ -1,10 +1,10 @@ -(C)Copyright 1999-2003 Marvell(R). +(C)Copyright 1999-2004 Marvell(R). All rights reserved =========================================================================== -sk98lin.txt created 15-Dec-2003 +sk98lin.txt created 13-Feb-2004 -Readme File for sk98lin v6.21 +Readme File for sk98lin v6.23 Marvell Yukon/SysKonnect SK-98xx Gigabit Ethernet Adapter family driver for LINUX This file contains @@ -174,7 +174,7 @@ to the driver module. If you use the kernel module loader, you can set driver parameters -in the file /etc/modules.conf (or old name: /etc/conf.modules). +in the file /etc/modprobe.conf (or /etc/modules.conf in 2.4 or earlier). To set the driver parameters in this file, proceed as follows: 1. Insert a line of the form : diff -Nru a/Documentation/networking/tuntap.txt b/Documentation/networking/tuntap.txt --- a/Documentation/networking/tuntap.txt Thu Feb 19 23:44:24 2004 +++ b/Documentation/networking/tuntap.txt Thu Feb 19 23:44:24 2004 @@ -45,13 +45,10 @@ bogus network interfaces to trick firewalls or administrators. Driver module autoloading - Make sure that "Kernel module loader" - module auto-loading support is enabled - in your kernel. - Add the following line to the /etc/modules.conf: - alias char-major-10-200 tun - and run - depmod -a + Make sure that "Kernel module loader" - module auto-loading + support is enabled in your kernel. The kernel should load it on + first access. Manual loading insert the module by hand: diff -Nru a/Documentation/networking/vortex.txt b/Documentation/networking/vortex.txt --- a/Documentation/networking/vortex.txt Thu Feb 19 23:44:23 2004 +++ b/Documentation/networking/vortex.txt Thu Feb 19 23:44:23 2004 @@ -59,8 +59,8 @@ ================= There are several parameters which may be provided to the driver when -its module is loaded. These are usually placed in /etc/modules.conf -(used to be conf.modules). Example: +its module is loaded. These are usually placed in /etc/modprobe.conf +(/etc/modules.conf in 2.4). Example: options 3c59x debug=3 rx_copybreak=300 @@ -216,6 +216,19 @@ to increase this value on LANs which have very high collision rates. The default value is 5000 (5.0 seconds). +enable_wol=N1,N2,N3,... + + Enable Wake-on-LAN support for the relevant interface. Donald + Becker's `ether-wake' application may be used to wake suspended + machines. + + Also enables the NIC's power management support. + +global_enable_wol=N + + Sets enable_wol mode for all 3c59x NICs in the machine. Entries in + the `enable_wol' array above will override any setting of this. + Media selection --------------- @@ -413,9 +426,9 @@ 1) Increase the debug level. Usually this is done via: - a) modprobe driver.o debug=7 - b) In /etc/conf.modules (or modules.conf): - options driver_name debug=7 + a) modprobe driver debug=7 + b) In /etc/modprobe.conf (or /etc/modules.conf for 2.4): + options driver debug=7 2) Recreate the problem with the higher debug level, send all logs to the maintainer. diff -Nru a/Documentation/parport.txt b/Documentation/parport.txt --- a/Documentation/parport.txt Thu Feb 19 23:44:26 2004 +++ b/Documentation/parport.txt Thu Feb 19 23:44:26 2004 @@ -39,7 +39,7 @@ KMod ---- -If you use kmod, you will find it useful to edit /etc/modules.conf. +If you use kmod, you will find it useful to edit /etc/modprobe.conf. Here is an example of the lines that need to be added: alias parport_lowlevel parport_pc diff -Nru a/Documentation/rocket.txt b/Documentation/rocket.txt --- a/Documentation/rocket.txt Thu Feb 19 23:44:25 2004 +++ b/Documentation/rocket.txt Thu Feb 19 23:44:25 2004 @@ -43,7 +43,7 @@ If installed as a module, the module must be loaded. This can be done manually by entering "modprobe rocket". To have the module loaded automatically -upon system boot, edit the /etc/modules.conf file and add the line +upon system boot, edit the /etc/modprobe.conf file and add the line "alias char-major-46 rocket". In order to use the ports, their device names (nodes) must be created with mknod. diff -Nru a/Documentation/s390/3270.txt b/Documentation/s390/3270.txt --- a/Documentation/s390/3270.txt Thu Feb 19 23:44:24 2004 +++ b/Documentation/s390/3270.txt Thu Feb 19 23:44:24 2004 @@ -48,7 +48,7 @@ script and the resulting /tmp/mkdev3270. If you have chosen to make tub3270 a module, you add a line to -/etc/modules.conf. If you are working on a VM virtual machine, you +/etc/modprobe.conf. If you are working on a VM virtual machine, you can use DEF GRAF to define virtual 3270 devices. You may generate both 3270 and 3215 console support, or one or the @@ -60,7 +60,7 @@ In brief, these are the steps: 1. Install the tub3270 patch - 2. (If a module) add a line to /etc/modules.conf + 2. (If a module) add a line to /etc/modprobe.conf 3. (If VM) define devices with DEF GRAF 4. Reboot 5. Configure @@ -84,13 +84,13 @@ make modules_install 2. (Perform this step only if you have configured tub3270 as a - module.) Add a line to /etc/modules.conf to automatically + module.) Add a line to /etc/modprobe.conf to automatically load the driver when it's needed. With this line added, you will see login prompts appear on your 3270s as soon as boot is complete (or with emulated 3270s, as soon as you dial into your vm guest using the command "DIAL "). Since the line-mode major number is 227, the line to add to - /etc/modules.conf should be: + /etc/modprobe.conf should be: alias char-major-227 tub3270 3. Define graphic devices to your vm guest machine, if you diff -Nru a/Documentation/scsi/aic79xx.txt b/Documentation/scsi/aic79xx.txt --- a/Documentation/scsi/aic79xx.txt Thu Feb 19 23:44:27 2004 +++ b/Documentation/scsi/aic79xx.txt Thu Feb 19 23:44:27 2004 @@ -210,7 +210,7 @@ INCORRECTLY CAN RENDER YOUR SYSTEM INOPERABLE. USE THEM WITH CAUTION. - Edit the file "modules.conf" in the directory /etc and add/edit a + Edit the file "modprobe.conf" in the directory /etc and add/edit a line containing 'options aic79xx aic79xx=[command[,command...]]' where 'command' is one or more of the following: ----------------------------------------------------------------- diff -Nru a/Documentation/scsi/aic7xxx.txt b/Documentation/scsi/aic7xxx.txt --- a/Documentation/scsi/aic7xxx.txt Thu Feb 19 23:44:24 2004 +++ b/Documentation/scsi/aic7xxx.txt Thu Feb 19 23:44:24 2004 @@ -186,7 +186,7 @@ INCORRECTLY CAN RENDER YOUR SYSTEM INOPERABLE. USE THEM WITH CAUTION. - Edit the file "modules.conf" in the directory /etc and add/edit a + Edit the file "modprobe.conf" in the directory /etc and add/edit a line containing 'options aic7xxx aic7xxx=[command[,command...]]' where 'command' is one or more of the following: ----------------------------------------------------------------- diff -Nru a/Documentation/scsi/osst.txt b/Documentation/scsi/osst.txt --- a/Documentation/scsi/osst.txt Thu Feb 19 23:44:27 2004 +++ b/Documentation/scsi/osst.txt Thu Feb 19 23:44:27 2004 @@ -67,7 +67,7 @@ If you want to have the module autoloaded on access to /dev/osst, you may add something like alias char-major-206 osst -to your /etc/modules.conf (old name: conf.modules). +to your /etc/modprobe.conf (before 2.6: modules.conf). You may find it convenient to create a symbolic link ln -s nosst0 /dev/tape diff -Nru a/Documentation/sonypi.txt b/Documentation/sonypi.txt --- a/Documentation/sonypi.txt Thu Feb 19 23:44:22 2004 +++ b/Documentation/sonypi.txt Thu Feb 19 23:44:22 2004 @@ -43,7 +43,7 @@ --------------- Several options can be passed to the sonypi driver, either by adding them -to /etc/modules.conf file, when the driver is compiled as a module or by +to /etc/modprobe.conf file, when the driver is compiled as a module or by adding the following to the kernel command line (in your bootloader): sonypi=minor[,verbose[,fnkeyinit[,camera[,compat[,mask[,useinput]]]]]] @@ -109,7 +109,7 @@ ----------- In order to automatically load the sonypi module on use, you can put those -lines in your /etc/modules.conf file: +lines in your /etc/modprobe.conf file: alias char-major-10-250 sonypi options sonypi minor=250 diff -Nru a/Documentation/sound/oss/AWE32 b/Documentation/sound/oss/AWE32 --- a/Documentation/sound/oss/AWE32 Thu Feb 19 23:44:26 2004 +++ b/Documentation/sound/oss/AWE32 Thu Feb 19 23:44:26 2004 @@ -47,12 +47,12 @@ Copy it to a directory of your choice, and unpack it there. -4) Edit /etc/modules.conf, and insert the following lines at the end of the +4) Edit /etc/modprobe.conf, and insert the following lines at the end of the file: alias sound-slot-0 sb alias sound-service-0-1 awe_wave - post-install awe_wave /usr/local/bin/sfxload PATH_TO_SOUND_BANK_FILE + install awe_wave /sbin/modprobe --first-time -i awe_wave && /usr/local/bin/sfxload PATH_TO_SOUND_BANK_FILE You will of course have to change "PATH_TO_SOUND_BANK_FILE" to the full path of of the sound bank file. That will enable the Sound Blaster and AWE diff -Nru a/Documentation/sound/oss/AudioExcelDSP16 b/Documentation/sound/oss/AudioExcelDSP16 --- a/Documentation/sound/oss/AudioExcelDSP16 Thu Feb 19 23:44:25 2004 +++ b/Documentation/sound/oss/AudioExcelDSP16 Thu Feb 19 23:44:25 2004 @@ -41,7 +41,7 @@ (0x300, 0x310, 0x320 or 0x330) mpu_irq MPU-401 irq line (5, 7, 9, 10 or 0) -The /etc/modules.conf will have lines like this: +The /etc/modprobe.conf will have lines like this: options opl3 io=0x388 options ad1848 io=0x530 irq=11 dma=3 @@ -51,11 +51,11 @@ ad1848 are the corresponding options for the MSS and OPL3 modules. Loading MSS and OPL3 needs to pre load the aedsp16 module to set up correctly -the sound card. Installation dependencies must be written in the modules.conf +the sound card. Installation dependencies must be written in the modprobe.conf file: -pre-install ad1848 modprobe aedsp16 -pre-install opl3 modprobe aedsp16 +install ad1848 /sbin/modprobe aedsp16 && /sbin/modprobe -i ad1848 +install opl3 /sbin/modprobe aedsp16 && /sbin/modprobe -i opl3 Then you must load the sound modules stack in this order: sound -> aedsp16 -> [ ad1848, opl3 ] diff -Nru a/Documentation/sound/oss/CMI8330 b/Documentation/sound/oss/CMI8330 --- a/Documentation/sound/oss/CMI8330 Thu Feb 19 23:44:23 2004 +++ b/Documentation/sound/oss/CMI8330 Thu Feb 19 23:44:23 2004 @@ -143,7 +143,7 @@ -Alma Chao suggests the following /etc/modules.conf: +Alma Chao suggests the following /etc/modprobe.conf: alias sound ad1848 alias synth0 opl3 diff -Nru a/Documentation/sound/oss/Introduction b/Documentation/sound/oss/Introduction --- a/Documentation/sound/oss/Introduction Thu Feb 19 23:44:29 2004 +++ b/Documentation/sound/oss/Introduction Thu Feb 19 23:44:29 2004 @@ -168,7 +168,7 @@ ========= If loading via modprobe, these common files are automatically loaded -when requested by modprobe. For example, my /etc/modules.conf contains: +when requested by modprobe. For example, my /etc/modprobe.conf contains: alias sound sb options sb io=0x240 irq=9 dma=3 dma16=5 mpu_io=0x300 @@ -228,7 +228,7 @@ driver, you should do the following: 1. remove sound modules (detailed above) -2. remove the sound modules from /etc/modules.conf +2. remove the sound modules from /etc/modprobe.conf 3. move the sound modules from /lib/modules//misc (for example, I make a /lib/modules//misc/tmp directory and copy the sound module files to that @@ -265,7 +265,7 @@ sb.o could be copied (or symlinked) to sb1.o for the second SoundBlaster. -2. Make a second entry in /etc/modules.conf, for example, +2. Make a second entry in /etc/modprobe.conf, for example, sound1 or sb1. This second entry should refer to the new module names for example sb1, and should include the I/O, etc. for the second sound card. @@ -369,7 +369,7 @@ 2) On the command line when using insmod or in a bash script using command line calls to load sound. -3) In /etc/modules.conf when using modprobe. +3) In /etc/modprobe.conf when using modprobe. 4) Via Red Hat's GPL'd /usr/sbin/sndconfig program (text based). diff -Nru a/Documentation/sound/oss/MAD16 b/Documentation/sound/oss/MAD16 --- a/Documentation/sound/oss/MAD16 Thu Feb 19 23:44:28 2004 +++ b/Documentation/sound/oss/MAD16 Thu Feb 19 23:44:28 2004 @@ -1,4 +1,5 @@ -(This recipe has been edited to update the configuration symbols.) +(This recipe has been edited to update the configuration symbols, + and change over to modprobe.conf for 2.6) From: Shaw Carruthers @@ -20,9 +21,9 @@ CONFIG_SOUND_MAD16=m CONFIG_SOUND_YM3812=m -modules.conf has: +modprobe.conf has: -alias char-major-14 mad16 +alias char-major-14-* mad16 options sb mad16=1 options mad16 io=0x530 irq=7 dma=0 dma16=1 && /usr/local/bin/aumix -w 15 -p 20 -m 0 -1 0 -2 0 -3 0 -i 0 diff -Nru a/Documentation/sound/oss/Maestro3 b/Documentation/sound/oss/Maestro3 --- a/Documentation/sound/oss/Maestro3 Thu Feb 19 23:44:27 2004 +++ b/Documentation/sound/oss/Maestro3 Thu Feb 19 23:44:27 2004 @@ -64,7 +64,7 @@ installed with the rest of the modules for the kernel on the system. Typically this will be in /lib/modules/ somewhere. 'alias sound-slot-0 maestro3' should also be added to your module configs (typically -/etc/modules.conf) if you're using modular OSS/Lite sound and want to +/etc/modprobe.conf) if you're using modular OSS/Lite sound and want to default to using a maestro3 chip. There are very few options to the driver. One is 'debug' which will diff -Nru a/Documentation/sound/oss/OPL3-SA2 b/Documentation/sound/oss/OPL3-SA2 --- a/Documentation/sound/oss/OPL3-SA2 Thu Feb 19 23:44:23 2004 +++ b/Documentation/sound/oss/OPL3-SA2 Thu Feb 19 23:44:23 2004 @@ -162,7 +162,7 @@ modprobe opl3 io=0x388 See the section "Automatic Module Loading" below for how to set up -/etc/modules.conf to automate this. +/etc/modprobe.conf to automate this. An important thing to remember that the opl3sa2 module's io argument is for it's own control port, which handles the card's master mixer for @@ -196,7 +196,7 @@ Lastly, if you're using modules and want to set up automatic module loading with kmod, the kernel module loader, here is the section I -currently use in my modules.conf file: +currently use in my modprobe.conf file: # Sound alias sound-slot-0 opl3sa2 diff -Nru a/Documentation/sound/oss/Opti b/Documentation/sound/oss/Opti --- a/Documentation/sound/oss/Opti Thu Feb 19 23:44:24 2004 +++ b/Documentation/sound/oss/Opti Thu Feb 19 23:44:24 2004 @@ -18,7 +18,7 @@ If you have another OS installed on your computer it is recommended that Linux and the other OS use the same resources. -Also, it is recommended that resources specified in /etc/modules.conf +Also, it is recommended that resources specified in /etc/modprobe.conf and resources specified in /etc/isapnp.conf agree. Compiling the sound driver @@ -68,9 +68,9 @@ Using kmod and autoloading the sound driver ------------------------------------------- Comment: as of linux-2.1.90 kmod is replacing kerneld. -The config file '/etc/modules.conf' is used as before. +The config file '/etc/modprobe.conf' is used as before. -This is the sound part of my /etc/modules.conf file. +This is the sound part of my /etc/modprobe.conf file. Following that I will explain each line. alias mixer0 mad16 @@ -80,7 +80,7 @@ options sb mad16=1 options mad16 irq=10 dma=0 dma16=1 io=0x530 joystick=1 cdtype=0 options opl3 io=0x388 -post-install mad16 /sbin/ad1848_mixer_reroute 14 8 15 3 16 6 +install mad16 /sbin/modprobe -i mad16 && /sbin/ad1848_mixer_reroute 14 8 15 3 16 6 If you have an MPU daughtercard or onboard MPU you will want to add to the "options mad16" line - eg diff -Nru a/Documentation/sound/oss/PAS16 b/Documentation/sound/oss/PAS16 --- a/Documentation/sound/oss/PAS16 Thu Feb 19 23:44:28 2004 +++ b/Documentation/sound/oss/PAS16 Thu Feb 19 23:44:28 2004 @@ -129,7 +129,7 @@ You can then get OPL3 functionality by issuing the command: insmod opl3 In addition, you must either add the following line to - /etc/modules.conf: + /etc/modprobe.conf: options opl3 io=0x388 or else add the following line to /etc/lilo.conf: opl3=0x388 @@ -159,5 +159,5 @@ append="pas2=0x388,10,3,-1,0,-1,-1,-1 opl3=0x388" If sound is built totally modular, the above options may be -specified in /etc/modules.conf for pas2.o, sb.o and opl3.o +specified in /etc/modprobe.conf for pas2, sb and opl3 respectively. diff -Nru a/Documentation/sound/oss/README.modules b/Documentation/sound/oss/README.modules --- a/Documentation/sound/oss/README.modules Thu Feb 19 23:44:27 2004 +++ b/Documentation/sound/oss/README.modules Thu Feb 19 23:44:27 2004 @@ -26,10 +26,10 @@ drivers/sound dir. Now one simply configures and makes one's kernel and modules in the usual way. - Then, add to your /etc/modules.conf something like: + Then, add to your /etc/modprobe.conf something like: -alias char-major-14 sb -post-install sb /sbin/modprobe "-k" "adlib_card" +alias char-major-14-* sb +install sb /sbin/modprobe -i sb && /sbin/modprobe adlib_card options sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330 options adlib_card io=0x388 # FM synthesizer @@ -65,12 +65,12 @@ Note that at present there is no way to configure the io, irq and other parameters for the modular drivers as one does for the wired drivers.. One needs to pass the modules the necessary parameters as arguments, either -with /etc/modules.conf or with command-line args to modprobe, e.g. +with /etc/modprobe.conf or with command-line args to modprobe, e.g. -modprobe -k sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330 -modprobe -k adlib_card io=0x388 +modprobe sb io=0x220 irq=7 dma=1 dma16=5 mpu_io=0x330 +modprobe adlib_card io=0x388 - recommend using /etc/modules.conf. + recommend using /etc/modprobe.conf. Persistent DMA Buffers: @@ -88,7 +88,7 @@ To make the sound driver use persistent DMA buffers we need to pass the sound.o module a "dmabuf=1" command-line argument. This is normally done -in /etc/modules.conf like so: +in /etc/modprobe.conf like so: options sound dmabuf=1 diff -Nru a/Documentation/sound/oss/Wavefront b/Documentation/sound/oss/Wavefront --- a/Documentation/sound/oss/Wavefront Thu Feb 19 23:44:23 2004 +++ b/Documentation/sound/oss/Wavefront Thu Feb 19 23:44:23 2004 @@ -189,16 +189,15 @@ 6) How do I configure my card ? ************************************************************ -You need to edit /etc/modules.conf. Here's mine (edited to show the +You need to edit /etc/modprobe.conf. Here's mine (edited to show the relevant details): # Sound system - alias char-major-14 wavefront + alias char-major-14-* wavefront alias synth0 wavefront alias mixer0 cs4232 alias audio0 cs4232 - pre-install wavefront modprobe "-k" "cs4232" - post-install wavefront modprobe "-k" "opl3" + install wavefront /sbin/modprobe cs4232 && /sbin/modprobe -i wavefront && /sbin/modprobe opl3 options wavefront io=0x200 irq=9 options cs4232 synthirq=9 synthio=0x200 io=0x530 irq=5 dma=1 dma2=0 options opl3 io=0x388 diff -Nru a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt --- a/Documentation/sysctl/fs.txt Thu Feb 19 23:44:22 2004 +++ b/Documentation/sysctl/fs.txt Thu Feb 19 23:44:22 2004 @@ -138,3 +138,13 @@ can have. You only need to increase super-max if you need to mount more filesystems than the current value in super-max allows you to. + +============================================================== + +aio-nr & aio-max-nr: + +aio-nr shows the current system-wide number of asynchronous io +requests. aio-max-nr allows you to change the maximum value +aio-nr can grow to. + +============================================================== diff -Nru a/Documentation/usb/scanner.txt b/Documentation/usb/scanner.txt --- a/Documentation/usb/scanner.txt Thu Feb 19 23:44:28 2004 +++ b/Documentation/usb/scanner.txt Thu Feb 19 23:44:28 2004 @@ -146,14 +146,14 @@ options scanner vendor=0x#### product=0x**** -to the /etc/modules.conf file replacing the #'s and the *'s with the +to the /etc/modprobe.conf file replacing the #'s and the *'s with the correct IDs. The IDs can be retrieved from the messages file or using "cat /proc/bus/usb/devices". If the default timeout is too low, i.e. there are frequent "timeout" messages, you may want to increase the timeout manually by using the parameter "read_timeout". The time is given in seconds. This is an example for -modules.conf with a timeout of 60 seconds: +modprobe.conf with a timeout of 60 seconds: options scanner read_timeout=60 diff -Nru a/Documentation/video4linux/CQcam.txt b/Documentation/video4linux/CQcam.txt --- a/Documentation/video4linux/CQcam.txt Thu Feb 19 23:44:28 2004 +++ b/Documentation/video4linux/CQcam.txt Thu Feb 19 23:44:28 2004 @@ -62,7 +62,7 @@ The configuration requires module configuration and device configuration. I like kmod or kerneld process with the -/etc/modules.conf file so the modules can automatically load/unload as +/etc/modprobe.conf file so the modules can automatically load/unload as they are used. The video devices could already exist, be generated using MAKEDEV, or need to be created. The following sections detail these procedures. @@ -71,15 +71,15 @@ 2.1 Module Configuration Using modules requires a bit of work to install and pass the -parameters. Understand that entries in /etc/modules.conf of: +parameters. Understand that entries in /etc/modprobe.conf of: alias parport_lowlevel parport_pc options parport_pc io=0x378 irq=none alias char-major-81 videodev alias char-major-81-0 c-qcam -will cause the kmod/kerneld/modprobe to do certain things. If you are -using kmod or kerneld, then a request for a 'char-major-81-0' will cause +will cause the kmod/modprobe to do certain things. If you are +using kmod, then a request for a 'char-major-81-0' will cause the 'c-qcam' module to load. If you have other video sources with modules, you might want to assign the different minor numbers to different modules. diff -Nru a/Documentation/video4linux/Zoran b/Documentation/video4linux/Zoran --- a/Documentation/video4linux/Zoran Thu Feb 19 23:44:26 2004 +++ b/Documentation/video4linux/Zoran Thu Feb 19 23:44:26 2004 @@ -233,7 +233,7 @@ option with X being the card number as given in the previous section. To have more than one card, use card=X1[,X2[,X3,[X4[..]]]] -To automate this, add the following to your /etc/modules.conf: +To automate this, add the following to your /etc/modprobe.conf: options zr36067 card=X1[,X2[,X3[,X4[..]]]] alias char-major-81-0 zr36067 diff -Nru a/Documentation/video4linux/bttv/Modprobe.conf b/Documentation/video4linux/bttv/Modprobe.conf --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/Documentation/video4linux/bttv/Modprobe.conf Thu Feb 19 23:44:29 2004 @@ -0,0 +1,11 @@ +# i2c +alias char-major-89 i2c-dev +options i2c-core i2c_debug=1 +options i2c-algo-bit bit_test=1 + +# bttv +alias char-major-81 videodev +alias char-major-81-0 bttv +options bttv card=2 radio=1 +options tuner debug=1 + diff -Nru a/Documentation/video4linux/bttv/Modules.conf b/Documentation/video4linux/bttv/Modules.conf --- a/Documentation/video4linux/bttv/Modules.conf Thu Feb 19 23:44:25 2004 +++ b/Documentation/video4linux/bttv/Modules.conf Thu Feb 19 23:44:25 2004 @@ -1,3 +1,6 @@ +# For modern kernels (2.6 or above), this belongs in /etc/modprobe.conf +# For for 2.4 kernels or earlier, this belongs in /etc/modules.conf. + # i2c alias char-major-89 i2c-dev options i2c-core i2c_debug=1 diff -Nru a/Documentation/video4linux/bttv/README b/Documentation/video4linux/bttv/README --- a/Documentation/video4linux/bttv/README Thu Feb 19 23:44:22 2004 +++ b/Documentation/video4linux/bttv/README Thu Feb 19 23:44:22 2004 @@ -22,7 +22,7 @@ cards is in CARDLIST.bttv If bttv takes very long to load (happens sometimes with the cheap -cards which have no tuner), try adding this to your modules.conf: +cards which have no tuner), try adding this to your modprobe.conf: options i2c-algo-bit bit_test=1 For the WinTV/PVR you need one firmware file from the driver CD: diff -Nru a/Documentation/video4linux/meye.txt b/Documentation/video4linux/meye.txt --- a/Documentation/video4linux/meye.txt Thu Feb 19 23:44:27 2004 +++ b/Documentation/video4linux/meye.txt Thu Feb 19 23:44:27 2004 @@ -42,7 +42,7 @@ --------------- Several options can be passed to the meye driver, either by adding them -to /etc/modules.conf file, when the driver is compiled as a module, or +to /etc/modprobe.conf file, when the driver is compiled as a module, or by adding the following to the kernel command line (in your bootloader): meye=gbuffers[,gbufsize[,video_nr]] @@ -59,7 +59,7 @@ ----------- In order to automatically load the meye module on use, you can put those lines -in your /etc/modules.conf file: +in your /etc/modprobe.conf file: alias char-major-81 videodev alias char-major-81-0 meye diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS Thu Feb 19 23:44:26 2004 +++ b/MAINTAINERS Thu Feb 19 23:44:26 2004 @@ -521,7 +521,7 @@ P: Dave Jones M: davej@codemonkey.org.uk L: cpufreq@www.linux.org.uk -W: http://www.codemonkey.org.uk/cpufreq/ +W: http://www.codemonkey.org.uk/projects/cpufreq/ S: Maintained CPUID/MSR DRIVER diff -Nru a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c --- a/arch/alpha/kernel/irq.c Thu Feb 19 23:44:27 2004 +++ b/arch/alpha/kernel/irq.c Thu Feb 19 23:44:27 2004 @@ -252,7 +252,7 @@ irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, irq_affinity[(long)data]); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -333,7 +333,7 @@ prof_cpu_mask_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, *(cpumask_t *)data); + int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/alpha/kernel/time.c b/arch/alpha/kernel/time.c --- a/arch/alpha/kernel/time.c Thu Feb 19 23:44:25 2004 +++ b/arch/alpha/kernel/time.c Thu Feb 19 23:44:25 2004 @@ -503,6 +503,7 @@ time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } diff -Nru a/arch/arm/Kconfig b/arch/arm/Kconfig --- a/arch/arm/Kconfig Thu Feb 19 23:44:25 2004 +++ b/arch/arm/Kconfig Thu Feb 19 23:44:25 2004 @@ -639,6 +639,8 @@ source "fs/Kconfig" +source "arch/arm/oprofile/Kconfig" + source "drivers/video/Kconfig" if ARCH_ACORN || ARCH_CLPS7500 || ARCH_TBOX || ARCH_SHARK || ARCH_SA1100 || PCI diff -Nru a/arch/arm/Makefile b/arch/arm/Makefile --- a/arch/arm/Makefile Thu Feb 19 23:44:24 2004 +++ b/arch/arm/Makefile Thu Feb 19 23:44:24 2004 @@ -116,6 +116,7 @@ core-$(CONFIG_FPE_NWFPE) += arch/arm/nwfpe/ core-$(CONFIG_FPE_FASTFPE) += $(FASTFPE_OBJ) +drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ drivers-$(CONFIG_ARCH_CLPS7500) += drivers/acorn/char/ drivers-$(CONFIG_ARCH_L7200) += drivers/acorn/char/ diff -Nru a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c --- a/arch/arm/kernel/time.c Thu Feb 19 23:44:26 2004 +++ b/arch/arm/kernel/time.c Thu Feb 19 23:44:26 2004 @@ -85,6 +85,9 @@ */ static inline void do_profile(struct pt_regs *regs) { + + profile_hook(regs); + if (!user_mode(regs) && prof_buffer && current->pid) { diff -Nru a/arch/arm/oprofile/Kconfig b/arch/arm/oprofile/Kconfig --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/oprofile/Kconfig Thu Feb 19 23:44:29 2004 @@ -0,0 +1,23 @@ + +menu "Profiling support" + depends on EXPERIMENTAL + +config PROFILING + bool "Profiling support (EXPERIMENTAL)" + help + Say Y here to enable the extended profiling support mechanisms used + by profilers such as OProfile. + + +config OPROFILE + tristate "OProfile system profiling (EXPERIMENTAL)" + depends on PROFILING + help + OProfile is a profiling system capable of profiling the + whole system, include the kernel, kernel modules, libraries, + and applications. + + If unsure, say N. + +endmenu + diff -Nru a/arch/arm/oprofile/Makefile b/arch/arm/oprofile/Makefile --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/oprofile/Makefile Thu Feb 19 23:44:29 2004 @@ -0,0 +1,9 @@ +obj-$(CONFIG_OPROFILE) += oprofile.o + +DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ + oprof.o cpu_buffer.o buffer_sync.o \ + event_buffer.o oprofile_files.o \ + oprofilefs.o oprofile_stats.o \ + timer_int.o ) + +oprofile-y := $(DRIVER_OBJS) init.o diff -Nru a/arch/arm/oprofile/init.c b/arch/arm/oprofile/init.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/arm/oprofile/init.c Thu Feb 19 23:44:29 2004 @@ -0,0 +1,22 @@ +/** + * @file init.c + * + * @remark Copyright 2004 Oprofile Authors + * + * @author Zwane Mwaikambo + */ + +#include +#include +#include + +int oprofile_arch_init(struct oprofile_operations **ops) +{ + int ret = -ENODEV; + + return ret; +} + +void oprofile_arch_exit(void) +{ +} diff -Nru a/arch/arm26/kernel/time.c b/arch/arm26/kernel/time.c --- a/arch/arm26/kernel/time.c Thu Feb 19 23:44:26 2004 +++ b/arch/arm26/kernel/time.c Thu Feb 19 23:44:26 2004 @@ -179,6 +179,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } diff -Nru a/arch/cris/arch-v10/drivers/ethernet.c b/arch/cris/arch-v10/drivers/ethernet.c --- a/arch/cris/arch-v10/drivers/ethernet.c Thu Feb 19 23:44:25 2004 +++ b/arch/cris/arch-v10/drivers/ethernet.c Thu Feb 19 23:44:25 2004 @@ -482,7 +482,7 @@ /* Register device */ err = register_netdev(dev); if (err) { - kfree(dev); + free_netdev(dev); return err; } diff -Nru a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c --- a/arch/cris/kernel/time.c Thu Feb 19 23:44:25 2004 +++ b/arch/cris/kernel/time.c Thu Feb 19 23:44:25 2004 @@ -108,6 +108,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; local_irq_restore(flags); + clock_was_set(); return 0; } diff -Nru a/arch/h8300/kernel/time.c b/arch/h8300/kernel/time.c --- a/arch/h8300/kernel/time.c Thu Feb 19 23:44:24 2004 +++ b/arch/h8300/kernel/time.c Thu Feb 19 23:44:24 2004 @@ -139,6 +139,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } diff -Nru a/arch/i386/Kconfig b/arch/i386/Kconfig --- a/arch/i386/Kconfig Thu Feb 19 23:44:23 2004 +++ b/arch/i386/Kconfig Thu Feb 19 23:44:23 2004 @@ -43,6 +43,15 @@ help Choose this option if your computer is a standard PC or compatible. +config X86_ELAN + bool "AMD Elan" + help + Select this for an AMD Elan processor. + + Do not use this option for K6/Athlon/Opteron processors! + + If unsure, choose "PC-compatible" instead. + config X86_VOYAGER bool "Voyager (NCR)" help @@ -130,6 +139,8 @@ default y depends on SMP && X86_ES7000 && MPENTIUMIII +if !X86_ELAN + choice prompt "Processor family" default M686 @@ -222,14 +233,20 @@ extended prefetch instructions in addition to the Pentium II extensions. +config MPENTIUMM + bool "Pentium M" + help + Select this for Intel Pentium M (not Pentium-4 M) + notebook chips. + config MPENTIUM4 - bool "Pentium-4/Celeron(P4-based)/Xeon" + bool "Pentium-4/Celeron(P4-based)/Pentium-4 M/Xeon" help - Select this for Intel Pentium 4 chips. This includes both - the Pentium 4 and P4-based Celeron chips. This option - enables compile flags optimized for the chip, uses the - correct cache shift, and applies any applicable Pentium III - optimizations. + Select this for Intel Pentium 4 chips. This includes the + Pentium 4, P4-based Celeron and Xeon, and Pentium-4 M + (not Pentium M) chips. This option enables compile flags + optimized for the chip, uses the correct cache shift, and + applies any applicable Pentium III optimizations. config MK6 bool "K6/K6-II/K6-III" @@ -312,6 +329,8 @@ when it has moderate overhead. This is intended for generic distributions kernels. +endif + # # Define implied options from the CPU selection here # @@ -328,9 +347,9 @@ config X86_L1_CACHE_SHIFT int default "7" if MPENTIUM4 || X86_GENERIC - default "4" if MELAN || M486 || M386 + default "4" if X86_ELAN || M486 || M386 default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 - default "6" if MK7 || MK8 + default "6" if MK7 || MK8 || MPENTIUMM config RWSEM_GENERIC_SPINLOCK bool @@ -374,22 +393,22 @@ config X86_ALIGNMENT_16 bool - depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 + depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 default y config X86_GOOD_APIC bool - depends on MK7 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 + depends on MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || MK8 default y config X86_INTEL_USERCOPY bool - depends on MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 + depends on MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M586MMX || X86_GENERIC || MK8 || MK7 default y config X86_USE_PPRO_CHECKSUM bool - depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 + depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 default y config X86_USE_3DNOW @@ -513,7 +532,7 @@ config X86_TSC bool - depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ + depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ default y config X86_MCE @@ -603,8 +622,6 @@ To compile this driver as a module, choose M here: the module will be called microcode. - If you use modprobe or kmod you may also want to add the line - 'alias char-major-10-184 microcode' to your /etc/modules.conf file. config X86_MSR tristate "/dev/cpu/*/msr - Model-specific register support" @@ -701,7 +718,7 @@ # Common NUMA Features config NUMA bool "Numa Memory Allocation Support" - depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI)) + depends on SMP && HIGHMEM64G && (X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI)) default n if X86_PC default y if (X86_NUMAQ || X86_SUMMIT) @@ -809,6 +826,14 @@ anything about EFI). However, even with this option, the resultant kernel should continue to boot on existing non-EFI platforms. +config IRQBALANCE + bool "Enable kernel irq balancing" + depends on SMP + default y + help + The defalut yes will allow the kernel to do irq load balancing. + Saying no will keep the kernel from doing irq load balancing. + config HAVE_DEC_LOCK bool depends on (SMP || PREEMPT) && X86_CMPXCHG @@ -821,6 +846,19 @@ depends on (((X86_SUMMIT || X86_GENERICARCH) && NUMA) || (X86 && EFI)) default y +config REGPARM + bool "Use register arguments (EXPERIMENTAL)" + depends on EXPERIMENTAL + default n + help + Compile the kernel with -mregparm=3. This uses an different ABI + and passes the first three arguments of a function call in registers. + This will probably break binary only modules. + + This feature is only enabled for gcc-3.0 and later - earlier compilers + generate incorrect output with certain kernel constructs when + -mregparm=3 is used. + endmenu @@ -1177,9 +1215,31 @@ Say Y here if you are developing drivers or trying to debug and identify kernel problems. +config EARLY_PRINTK + bool "Early printk" if EMBEDDED + default y + help + Write kernel log output directly into the VGA buffer or to a serial + port. + + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. For normal operation + it is not recommended because it looks ugly and doesn't cooperate + with klogd/syslogd or the X server. You should normally N here, + unless you want to debug such a crash. + config DEBUG_STACKOVERFLOW bool "Check for stack overflows" depends on DEBUG_KERNEL + +config DEBUG_STACK_USAGE + bool "Stack utilization instrumentation" + depends on DEBUG_KERNEL + help + Enables the display of the minimum amount of free stack which each + task has ever had available in the sysrq-T and sysrq-P debug output. + + This option will slow down process creation somewhat. config DEBUG_SLAB bool "Debug memory allocations" diff -Nru a/arch/i386/Makefile b/arch/i386/Makefile --- a/arch/i386/Makefile Thu Feb 19 23:44:24 2004 +++ b/arch/i386/Makefile Thu Feb 19 23:44:24 2004 @@ -34,8 +34,9 @@ cflags-$(CONFIG_M686) += -march=i686 cflags-$(CONFIG_MPENTIUMII) += $(call check_gcc,-march=pentium2,-march=i686) cflags-$(CONFIG_MPENTIUMIII) += $(call check_gcc,-march=pentium3,-march=i686) +cflags-$(CONFIG_MPENTIUMM) += $(call check_gcc,-march=pentium3,-march=i686) cflags-$(CONFIG_MPENTIUM4) += $(call check_gcc,-march=pentium4,-march=i686) -cflags-$(CONFIG_MK6) += $(call check_gcc,-march=k6,-march=i586) +cflags-$(CONFIG_MK6) += -march=k6 # Please note, that patches that add -march=athlon-xp and friends are pointless. # They make zero difference whatsosever to performance at this time. cflags-$(CONFIG_MK7) += $(call check_gcc,-march=athlon,-march=i686 $(align)-functions=4) @@ -46,6 +47,18 @@ cflags-$(CONFIG_MWINCHIP3D) += $(call check_gcc,-march=winchip2,-march=i586) cflags-$(CONFIG_MCYRIXIII) += $(call check_gcc,-march=c3,-march=i486) $(align)-functions=0 $(align)-jumps=0 $(align)-loops=0 cflags-$(CONFIG_MVIAC3_2) += $(call check_gcc,-march=c3-2,-march=i686) + +# AMD Elan support +cflags-$(CONFIG_X86_ELAN) += -march=i486 + +# -mregparm=3 works ok on gcc-3.0 and later +# +GCC_VERSION := $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC)) +cflags-$(CONFIG_REGPARM) += $(shell if [ $(GCC_VERSION) -ge 0300 ] ; then echo "-mregparm=3"; fi ;) + +# Enable unit-at-a-time mode when possible. It shrinks the +# kernel considerably. +CFLAGS += $(call check_gcc,-funit-at-a-time,) CFLAGS += $(cflags-y) diff -Nru a/arch/i386/boot/Makefile b/arch/i386/boot/Makefile --- a/arch/i386/boot/Makefile Thu Feb 19 23:44:24 2004 +++ b/arch/i386/boot/Makefile Thu Feb 19 23:44:24 2004 @@ -31,6 +31,8 @@ host-progs := tools/build +HOSTCFLAGS_build.o := -Iinclude + # --------------------------------------------------------------------------- $(obj)/zImage: IMAGE_OFFSET := 0x1000 diff -Nru a/arch/i386/boot/setup.S b/arch/i386/boot/setup.S --- a/arch/i386/boot/setup.S Thu Feb 19 23:44:25 2004 +++ b/arch/i386/boot/setup.S Thu Feb 19 23:44:25 2004 @@ -776,7 +776,7 @@ # AMD Elan bug fix by Robert Schwebel. # -#if defined(CONFIG_MELAN) +#if defined(CONFIG_X86_ELAN) movb $0x02, %al # alternate A20 gate outb %al, $0x92 # this works on SC410/SC520 a20_elan_wait: diff -Nru a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile --- a/arch/i386/kernel/Makefile Thu Feb 19 23:44:23 2004 +++ b/arch/i386/kernel/Makefile Thu Feb 19 23:44:23 2004 @@ -31,6 +31,7 @@ obj-$(CONFIG_ACPI_SRAT) += srat.o obj-$(CONFIG_HPET_TIMER) += time_hpet.o obj-$(CONFIG_EFI) += efi.o efi_stub.o +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o EXTRA_AFLAGS := -traditional diff -Nru a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c --- a/arch/i386/kernel/acpi/boot.c Thu Feb 19 23:44:27 2004 +++ b/arch/i386/kernel/acpi/boot.c Thu Feb 19 23:44:27 2004 @@ -376,6 +376,37 @@ } #endif +/* detect the location of the ACPI PM Timer */ +#ifdef CONFIG_X86_PM_TIMER +extern u32 pmtmr_ioport; + +static int __init acpi_parse_fadt(unsigned long phys, unsigned long size) +{ + struct fadt_descriptor_rev2 *fadt =0; + + fadt = (struct fadt_descriptor_rev2*) __acpi_map_table(phys,size); + if(!fadt) { + printk(KERN_WARNING PREFIX "Unable to map FADT\n"); + return 0; + } + + if (fadt->revision >= FADT2_REVISION_ID) { + /* FADT rev. 2 */ + if (fadt->xpm_tmr_blk.address_space_id != ACPI_ADR_SPACE_SYSTEM_IO) + return 0; + + pmtmr_ioport = fadt->xpm_tmr_blk.address; + } else { + /* FADT rev. 1 */ + pmtmr_ioport = fadt->V1_pm_tmr_blk; + } + if (pmtmr_ioport) + printk(KERN_INFO PREFIX "PM-Timer IO Port: %#x\n", pmtmr_ioport); + return 0; +} +#endif + + unsigned long __init acpi_find_rsdp (void) { @@ -447,6 +478,10 @@ acpi_disabled = 1; return result; } + +#ifdef CONFIG_X86_PM_TIMER + acpi_table_parse(ACPI_FADT, acpi_parse_fadt); +#endif #ifdef CONFIG_X86_LOCAL_APIC diff -Nru a/arch/i386/kernel/cpu/cpufreq/Kconfig b/arch/i386/kernel/cpu/cpufreq/Kconfig --- a/arch/i386/kernel/cpu/cpufreq/Kconfig Thu Feb 19 23:44:23 2004 +++ b/arch/i386/kernel/cpu/cpufreq/Kconfig Thu Feb 19 23:44:23 2004 @@ -54,7 +54,7 @@ config ELAN_CPUFREQ tristate "AMD Elan" - depends on CPU_FREQ_TABLE && MELAN + depends on CPU_FREQ_TABLE && X86_ELAN ---help--- This adds the CPUFreq driver for AMD Elan SC400 and SC410 processors. diff -Nru a/arch/i386/kernel/cpu/cpufreq/longhaul.c b/arch/i386/kernel/cpu/cpufreq/longhaul.c --- a/arch/i386/kernel/cpu/cpufreq/longhaul.c Thu Feb 19 23:44:22 2004 +++ b/arch/i386/kernel/cpu/cpufreq/longhaul.c Thu Feb 19 23:44:22 2004 @@ -1,5 +1,5 @@ /* - * (C) 2001-2003 Dave Jones. + * (C) 2001-2004 Dave Jones. * (C) 2002 Padraig Brady. * * Licensed under the terms of the GNU GPL License version 2. @@ -186,6 +186,7 @@ return target; } + static int guess_fsb(int maxmult) { int speed = (cpu_khz/1000); @@ -203,7 +204,6 @@ } - static int __init longhaul_get_ranges (void) { struct cpuinfo_x86 *c = cpu_data; @@ -359,7 +359,7 @@ return 0; } -static int longhaul_cpu_init (struct cpufreq_policy *policy) +static int __init longhaul_cpu_init (struct cpufreq_policy *policy) { struct cpuinfo_x86 *c = cpu_data; char *cpuname=NULL; diff -Nru a/arch/i386/kernel/cpu/cpufreq/longrun.c b/arch/i386/kernel/cpu/cpufreq/longrun.c --- a/arch/i386/kernel/cpu/cpufreq/longrun.c Thu Feb 19 23:44:27 2004 +++ b/arch/i386/kernel/cpu/cpufreq/longrun.c Thu Feb 19 23:44:27 2004 @@ -220,7 +220,7 @@ } -static int longrun_cpu_init(struct cpufreq_policy *policy) +static int __init longrun_cpu_init(struct cpufreq_policy *policy) { int result = 0; diff -Nru a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c Thu Feb 19 23:44:22 2004 +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c Thu Feb 19 23:44:22 2004 @@ -1,7 +1,7 @@ /* * AMD K7 Powernow driver. * (C) 2003 Dave Jones on behalf of SuSE Labs. - * (C) 2003 Dave Jones + * (C) 2003-2004 Dave Jones * * Licensed under the terms of the GNU GPL License version 2. * Based upon datasheets & sample CPUs kindly provided by AMD. diff -Nru a/arch/i386/kernel/cpu/mcheck/non-fatal.c b/arch/i386/kernel/cpu/mcheck/non-fatal.c --- a/arch/i386/kernel/cpu/mcheck/non-fatal.c Thu Feb 19 23:44:23 2004 +++ b/arch/i386/kernel/cpu/mcheck/non-fatal.c Thu Feb 19 23:44:23 2004 @@ -24,8 +24,6 @@ #include "mce.h" -static struct timer_list mce_timer; -static int timerset; static int firstbank; #define MCE_RATE 15*HZ /* timer rate is 15s */ @@ -35,14 +33,15 @@ u32 low, high; int i; - preempt_disable(); for (i=firstbank; i 1) - schedule_work (&mce_work); -#endif - mce_timer.expires = jiffies + MCE_RATE; - add_timer (&mce_timer); -} - static int __init init_nonfatal_mce_checker(void) { struct cpuinfo_x86 *c = &boot_cpu_data; @@ -91,17 +80,11 @@ else firstbank = 0; - if (timerset == 0) { - /* Set the timer to check for non-fatal - errors every MCE_RATE seconds */ - init_timer (&mce_timer); - mce_timer.expires = jiffies + MCE_RATE; - mce_timer.data = 0; - mce_timer.function = &mce_timerfunc; - add_timer (&mce_timer); - timerset = 1; - printk(KERN_INFO "Machine check exception polling timer started.\n"); - } + /* + * Check for non-fatal errors every MCE_RATE s + */ + schedule_delayed_work(&mce_work, MCE_RATE); + printk(KERN_INFO "Machine check exception polling timer started.\n"); return 0; } module_init(init_nonfatal_mce_checker); diff -Nru a/arch/i386/kernel/early_printk.c b/arch/i386/kernel/early_printk.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/kernel/early_printk.c Thu Feb 19 23:44:29 2004 @@ -0,0 +1,2 @@ + +#include "../../x86_64/kernel/early_printk.c" diff -Nru a/arch/i386/kernel/edd.c b/arch/i386/kernel/edd.c --- a/arch/i386/kernel/edd.c Thu Feb 19 23:44:24 2004 +++ b/arch/i386/kernel/edd.c Thu Feb 19 23:44:24 2004 @@ -134,18 +134,18 @@ for (i = 0; i < 4; i++) { if (isprint(info->params.host_bus_type[i])) { - p += snprintf(p, left, "%c", info->params.host_bus_type[i]); + p += scnprintf(p, left, "%c", info->params.host_bus_type[i]); } else { - p += snprintf(p, left, " "); + p += scnprintf(p, left, " "); } } if (!strncmp(info->params.host_bus_type, "ISA", 3)) { - p += snprintf(p, left, "\tbase_address: %x\n", + p += scnprintf(p, left, "\tbase_address: %x\n", info->params.interface_path.isa.base_address); } else if (!strncmp(info->params.host_bus_type, "PCIX", 4) || !strncmp(info->params.host_bus_type, "PCI", 3)) { - p += snprintf(p, left, + p += scnprintf(p, left, "\t%02x:%02x.%d channel: %u\n", info->params.interface_path.pci.bus, info->params.interface_path.pci.slot, @@ -154,12 +154,12 @@ } else if (!strncmp(info->params.host_bus_type, "IBND", 4) || !strncmp(info->params.host_bus_type, "XPRS", 4) || !strncmp(info->params.host_bus_type, "HTPT", 4)) { - p += snprintf(p, left, + p += scnprintf(p, left, "\tTBD: %llx\n", info->params.interface_path.ibnd.reserved); } else { - p += snprintf(p, left, "\tunknown: %llx\n", + p += scnprintf(p, left, "\tunknown: %llx\n", info->params.interface_path.unknown.reserved); } return (p - buf); @@ -178,43 +178,43 @@ for (i = 0; i < 8; i++) { if (isprint(info->params.interface_type[i])) { - p += snprintf(p, left, "%c", info->params.interface_type[i]); + p += scnprintf(p, left, "%c", info->params.interface_type[i]); } else { - p += snprintf(p, left, " "); + p += scnprintf(p, left, " "); } } if (!strncmp(info->params.interface_type, "ATAPI", 5)) { - p += snprintf(p, left, "\tdevice: %u lun: %u\n", + p += scnprintf(p, left, "\tdevice: %u lun: %u\n", info->params.device_path.atapi.device, info->params.device_path.atapi.lun); } else if (!strncmp(info->params.interface_type, "ATA", 3)) { - p += snprintf(p, left, "\tdevice: %u\n", + p += scnprintf(p, left, "\tdevice: %u\n", info->params.device_path.ata.device); } else if (!strncmp(info->params.interface_type, "SCSI", 4)) { - p += snprintf(p, left, "\tid: %u lun: %llu\n", + p += scnprintf(p, left, "\tid: %u lun: %llu\n", info->params.device_path.scsi.id, info->params.device_path.scsi.lun); } else if (!strncmp(info->params.interface_type, "USB", 3)) { - p += snprintf(p, left, "\tserial_number: %llx\n", + p += scnprintf(p, left, "\tserial_number: %llx\n", info->params.device_path.usb.serial_number); } else if (!strncmp(info->params.interface_type, "1394", 4)) { - p += snprintf(p, left, "\teui: %llx\n", + p += scnprintf(p, left, "\teui: %llx\n", info->params.device_path.i1394.eui); } else if (!strncmp(info->params.interface_type, "FIBRE", 5)) { - p += snprintf(p, left, "\twwid: %llx lun: %llx\n", + p += scnprintf(p, left, "\twwid: %llx lun: %llx\n", info->params.device_path.fibre.wwid, info->params.device_path.fibre.lun); } else if (!strncmp(info->params.interface_type, "I2O", 3)) { - p += snprintf(p, left, "\tidentity_tag: %llx\n", + p += scnprintf(p, left, "\tidentity_tag: %llx\n", info->params.device_path.i2o.identity_tag); } else if (!strncmp(info->params.interface_type, "RAID", 4)) { - p += snprintf(p, left, "\tidentity_tag: %x\n", + p += scnprintf(p, left, "\tidentity_tag: %x\n", info->params.device_path.raid.array_number); } else if (!strncmp(info->params.interface_type, "SATA", 4)) { - p += snprintf(p, left, "\tdevice: %u\n", + p += scnprintf(p, left, "\tdevice: %u\n", info->params.device_path.sata.device); } else { - p += snprintf(p, left, "\tunknown: %llx %llx\n", + p += scnprintf(p, left, "\tunknown: %llx %llx\n", info->params.device_path.unknown.reserved1, info->params.device_path.unknown.reserved2); } @@ -256,7 +256,7 @@ return -EINVAL; } - p += snprintf(p, left, "0x%02x\n", info->version); + p += scnprintf(p, left, "0x%02x\n", info->version); return (p - buf); } @@ -264,7 +264,7 @@ edd_show_disk80_sig(struct edd_device *edev, char *buf) { char *p = buf; - p += snprintf(p, left, "0x%08x\n", edd_disk80_sig); + p += scnprintf(p, left, "0x%08x\n", edd_disk80_sig); return (p - buf); } @@ -278,16 +278,16 @@ } if (info->interface_support & EDD_EXT_FIXED_DISK_ACCESS) { - p += snprintf(p, left, "Fixed disk access\n"); + p += scnprintf(p, left, "Fixed disk access\n"); } if (info->interface_support & EDD_EXT_DEVICE_LOCKING_AND_EJECTING) { - p += snprintf(p, left, "Device locking and ejecting\n"); + p += scnprintf(p, left, "Device locking and ejecting\n"); } if (info->interface_support & EDD_EXT_ENHANCED_DISK_DRIVE_SUPPORT) { - p += snprintf(p, left, "Enhanced Disk Drive support\n"); + p += scnprintf(p, left, "Enhanced Disk Drive support\n"); } if (info->interface_support & EDD_EXT_64BIT_EXTENSIONS) { - p += snprintf(p, left, "64-bit extensions\n"); + p += scnprintf(p, left, "64-bit extensions\n"); } return (p - buf); } @@ -302,21 +302,21 @@ } if (info->params.info_flags & EDD_INFO_DMA_BOUNDARY_ERROR_TRANSPARENT) - p += snprintf(p, left, "DMA boundary error transparent\n"); + p += scnprintf(p, left, "DMA boundary error transparent\n"); if (info->params.info_flags & EDD_INFO_GEOMETRY_VALID) - p += snprintf(p, left, "geometry valid\n"); + p += scnprintf(p, left, "geometry valid\n"); if (info->params.info_flags & EDD_INFO_REMOVABLE) - p += snprintf(p, left, "removable\n"); + p += scnprintf(p, left, "removable\n"); if (info->params.info_flags & EDD_INFO_WRITE_VERIFY) - p += snprintf(p, left, "write verify\n"); + p += scnprintf(p, left, "write verify\n"); if (info->params.info_flags & EDD_INFO_MEDIA_CHANGE_NOTIFICATION) - p += snprintf(p, left, "media change notification\n"); + p += scnprintf(p, left, "media change notification\n"); if (info->params.info_flags & EDD_INFO_LOCKABLE) - p += snprintf(p, left, "lockable\n"); + p += scnprintf(p, left, "lockable\n"); if (info->params.info_flags & EDD_INFO_NO_MEDIA_PRESENT) - p += snprintf(p, left, "no media present\n"); + p += scnprintf(p, left, "no media present\n"); if (info->params.info_flags & EDD_INFO_USE_INT13_FN50) - p += snprintf(p, left, "use int13 fn50\n"); + p += scnprintf(p, left, "use int13 fn50\n"); return (p - buf); } @@ -329,7 +329,7 @@ return -EINVAL; } - p += snprintf(p, left, "0x%x\n", info->params.num_default_cylinders); + p += scnprintf(p, left, "0x%x\n", info->params.num_default_cylinders); return (p - buf); } @@ -342,7 +342,7 @@ return -EINVAL; } - p += snprintf(p, left, "0x%x\n", info->params.num_default_heads); + p += scnprintf(p, left, "0x%x\n", info->params.num_default_heads); return (p - buf); } @@ -355,7 +355,7 @@ return -EINVAL; } - p += snprintf(p, left, "0x%x\n", info->params.sectors_per_track); + p += scnprintf(p, left, "0x%x\n", info->params.sectors_per_track); return (p - buf); } @@ -368,7 +368,7 @@ return -EINVAL; } - p += snprintf(p, left, "0x%llx\n", info->params.number_of_sectors); + p += scnprintf(p, left, "0x%llx\n", info->params.number_of_sectors); return (p - buf); } diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S --- a/arch/i386/kernel/entry.S Thu Feb 19 23:44:24 2004 +++ b/arch/i386/kernel/entry.S Thu Feb 19 23:44:24 2004 @@ -515,8 +515,8 @@ /* Do not access memory above the end of our stack page, * it might not exist. */ - andl $0x1fff,%eax - cmpl $0x1fec,%eax + andl $(THREAD_SIZE-1),%eax + cmpl $(THREAD_SIZE-20),%eax popl %eax jae nmi_stack_correct cmpl $sysenter_entry,12(%esp) diff -Nru a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S --- a/arch/i386/kernel/head.S Thu Feb 19 23:44:23 2004 +++ b/arch/i386/kernel/head.S Thu Feb 19 23:44:23 2004 @@ -16,6 +16,8 @@ #include #include #include +#include + #define OLD_CL_MAGIC_ADDR 0x90020 #define OLD_CL_MAGIC 0xA33F @@ -325,7 +327,7 @@ ret ENTRY(stack_start) - .long init_thread_union+8192 + .long init_thread_union+THREAD_SIZE .long __BOOT_DS /* This is the default interrupt "handler" :-) */ diff -Nru a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c --- a/arch/i386/kernel/io_apic.c Thu Feb 19 23:44:24 2004 +++ b/arch/i386/kernel/io_apic.c Thu Feb 19 23:44:24 2004 @@ -280,7 +280,7 @@ spin_unlock_irqrestore(&ioapic_lock, flags); } -#if defined(CONFIG_SMP) +#if defined(CONFIG_IRQBALANCE) # include /* kernel_thread() */ # include /* kstat */ # include /* kmalloc() */ @@ -689,9 +689,11 @@ __initcall(balanced_irq_init); -#else /* !SMP */ +#else /* !CONFIG_IRQBALANCE */ static inline void move_irq(int irq) { } +#endif /* CONFIG_IRQBALANCE */ +#ifndef CONFIG_SMP void send_IPI_self(int vector) { unsigned int cfg; @@ -706,7 +708,7 @@ */ apic_write_around(APIC_ICR, cfg); } -#endif /* defined(CONFIG_SMP) */ +#endif /* !CONFIG_SMP */ /* @@ -2150,6 +2152,10 @@ { int pin1, pin2; int vector; + unsigned int ver; + + ver = apic_read(APIC_LVR); + ver = GET_APIC_VERSION(ver); /* * get/set the timer IRQ vector: @@ -2163,11 +2169,17 @@ * mode for the 8259A whenever interrupts are routed * through I/O APICs. Also IRQ0 has to be enabled in * the 8259A which implies the virtual wire has to be - * disabled in the local APIC. + * disabled in the local APIC. Finally timer interrupts + * need to be acknowledged manually in the 8259A for + * do_slow_timeoffset() and for the i82489DX when using + * the NMI watchdog. */ apic_write_around(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_EXTINT); init_8259A(1); - timer_ack = 1; + if (nmi_watchdog == NMI_IO_APIC && !APIC_INTEGRATED(ver)) + timer_ack = 1; + else + timer_ack = !cpu_has_tsc; enable_8259A_irq(0); pin1 = find_isa_irq_pin(0, mp_INT); @@ -2185,7 +2197,8 @@ disable_8259A_irq(0); setup_nmi(); enable_8259A_irq(0); - check_nmi_watchdog(); + if (check_nmi_watchdog() < 0); + timer_ack = !cpu_has_tsc; } return; } @@ -2208,7 +2221,8 @@ add_pin_to_irq(0, 0, pin2); if (nmi_watchdog == NMI_IO_APIC) { setup_nmi(); - check_nmi_watchdog(); + if (check_nmi_watchdog() < 0); + timer_ack = !cpu_has_tsc; } return; } diff -Nru a/arch/i386/kernel/irq.c b/arch/i386/kernel/irq.c --- a/arch/i386/kernel/irq.c Thu Feb 19 23:44:23 2004 +++ b/arch/i386/kernel/irq.c Thu Feb 19 23:44:23 2004 @@ -435,7 +435,7 @@ long esp; __asm__ __volatile__("andl %%esp,%0" : - "=r" (esp) : "0" (8191)); + "=r" (esp) : "0" (THREAD_SIZE - 1)); if (unlikely(esp < (sizeof(struct thread_info) + 1024))) { printk("do_IRQ: stack overflow: %ld\n", esp - sizeof(struct thread_info)); @@ -927,7 +927,7 @@ static int irq_affinity_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, irq_affinity[(long)data]); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -968,7 +968,7 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, *(cpumask_t *)data); + int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/i386/kernel/microcode.c b/arch/i386/kernel/microcode.c --- a/arch/i386/kernel/microcode.c Thu Feb 19 23:44:23 2004 +++ b/arch/i386/kernel/microcode.c Thu Feb 19 23:44:23 2004 @@ -371,7 +371,9 @@ spin_lock_irqsave(µcode_update_lock, flags); /* write microcode via MSR 0x79 */ - wrmsr(MSR_IA32_UCODE_WRITE, (unsigned int)(uci->mc->bits), 0); + wrmsr(MSR_IA32_UCODE_WRITE, + (unsigned long) uci->mc->bits, + (unsigned long) uci->mc->bits >> 16 >> 16); wrmsr(MSR_IA32_UCODE_REV, 0, 0); __asm__ __volatile__ ("cpuid" : : : "ax", "bx", "cx", "dx"); @@ -507,3 +509,4 @@ module_init(microcode_init) module_exit(microcode_exit) +MODULE_ALIAS_MISCDEV(MICROCODE_MINOR); diff -Nru a/arch/i386/kernel/nmi.c b/arch/i386/kernel/nmi.c --- a/arch/i386/kernel/nmi.c Thu Feb 19 23:44:25 2004 +++ b/arch/i386/kernel/nmi.c Thu Feb 19 23:44:25 2004 @@ -42,7 +42,7 @@ * be enabled * -1: the lapic NMI watchdog is disabled, but can be enabled */ -static int nmi_active; +int nmi_active; #define K7_EVNTSEL_ENABLE (1 << 22) #define K7_EVNTSEL_INT (1 << 20) @@ -462,6 +462,7 @@ } } +EXPORT_SYMBOL(nmi_active); EXPORT_SYMBOL(nmi_watchdog); EXPORT_SYMBOL(disable_lapic_nmi_watchdog); EXPORT_SYMBOL(enable_lapic_nmi_watchdog); diff -Nru a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c --- a/arch/i386/kernel/process.c Thu Feb 19 23:44:22 2004 +++ b/arch/i386/kernel/process.c Thu Feb 19 23:44:22 2004 @@ -637,6 +637,8 @@ extern void scheduling_functions_end_here(void); #define first_sched ((unsigned long) scheduling_functions_start_here) #define last_sched ((unsigned long) scheduling_functions_end_here) +#define top_esp (THREAD_SIZE - sizeof(unsigned long)) +#define top_ebp (THREAD_SIZE - 2*sizeof(unsigned long)) unsigned long get_wchan(struct task_struct *p) { @@ -647,12 +649,12 @@ return 0; stack_page = (unsigned long)p->thread_info; esp = p->thread.esp; - if (!stack_page || esp < stack_page || esp > 8188+stack_page) + if (!stack_page || esp < stack_page || esp > top_esp+stack_page) return 0; /* include/asm-i386/system.h:switch_to() pushes ebp last. */ ebp = *(unsigned long *) esp; do { - if (ebp < stack_page || ebp > 8184+stack_page) + if (ebp < stack_page || ebp > top_ebp+stack_page) return 0; eip = *(unsigned long *) (ebp+4); if (eip < first_sched || eip >= last_sched) diff -Nru a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c --- a/arch/i386/kernel/setup.c Thu Feb 19 23:44:25 2004 +++ b/arch/i386/kernel/setup.c Thu Feb 19 23:44:25 2004 @@ -1118,6 +1118,19 @@ #endif paging_init(); +#ifdef CONFIG_EARLY_PRINTK + { + char *s = strstr(*cmdline_p, "earlyprintk="); + if (s) { + extern void setup_early_printk(char *); + + setup_early_printk(s); + printk("early console enabled\n"); + } + } +#endif + + dmi_scan_machine(); #ifdef CONFIG_X86_GENERICARCH diff -Nru a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c --- a/arch/i386/kernel/smpboot.c Thu Feb 19 23:44:25 2004 +++ b/arch/i386/kernel/smpboot.c Thu Feb 19 23:44:25 2004 @@ -948,6 +948,7 @@ printk("CPU%d: ", 0); print_cpu_info(&cpu_data[0]); + boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); boot_cpu_logical_apicid = logical_smp_processor_id(); current_thread_info()->cpu = 0; @@ -1008,8 +1009,6 @@ setup_local_APIC(); map_cpu_to_logical_apicid(); - if (GET_APIC_ID(apic_read(APIC_ID)) != boot_cpu_physical_apicid) - BUG(); setup_portio_remap(); diff -Nru a/arch/i386/kernel/timers/Makefile b/arch/i386/kernel/timers/Makefile --- a/arch/i386/kernel/timers/Makefile Thu Feb 19 23:44:22 2004 +++ b/arch/i386/kernel/timers/Makefile Thu Feb 19 23:44:22 2004 @@ -6,3 +6,4 @@ obj-$(CONFIG_X86_CYCLONE_TIMER) += timer_cyclone.o obj-$(CONFIG_HPET_TIMER) += timer_hpet.o +obj-$(CONFIG_X86_PM_TIMER) += timer_pm.o diff -Nru a/arch/i386/kernel/timers/common.c b/arch/i386/kernel/timers/common.c --- a/arch/i386/kernel/timers/common.c Thu Feb 19 23:44:24 2004 +++ b/arch/i386/kernel/timers/common.c Thu Feb 19 23:44:24 2004 @@ -137,3 +137,23 @@ } #endif +/* calculate cpu_khz */ +void __init init_cpu_khz(void) +{ + if (cpu_has_tsc) { + unsigned long tsc_quotient = calibrate_tsc(); + if (tsc_quotient) { + /* report CPU clock rate in Hz. + * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = + * clock/second. Our precision is about 100 ppm. + */ + { unsigned long eax=0, edx=1000; + __asm__("divl %2" + :"=a" (cpu_khz), "=d" (edx) + :"r" (tsc_quotient), + "0" (eax), "1" (edx)); + printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000); + } + } + } +} diff -Nru a/arch/i386/kernel/timers/timer.c b/arch/i386/kernel/timers/timer.c --- a/arch/i386/kernel/timers/timer.c Thu Feb 19 23:44:28 2004 +++ b/arch/i386/kernel/timers/timer.c Thu Feb 19 23:44:28 2004 @@ -19,6 +19,9 @@ #ifdef CONFIG_HPET_TIMER &timer_hpet, #endif +#ifdef CONFIG_X86_PM_TIMER + &timer_pmtmr, +#endif &timer_tsc, &timer_pit, NULL, diff -Nru a/arch/i386/kernel/timers/timer_cyclone.c b/arch/i386/kernel/timers/timer_cyclone.c --- a/arch/i386/kernel/timers/timer_cyclone.c Thu Feb 19 23:44:26 2004 +++ b/arch/i386/kernel/timers/timer_cyclone.c Thu Feb 19 23:44:26 2004 @@ -212,26 +212,7 @@ } } - /* init cpu_khz. - * XXX - This should really be done elsewhere, - * and in a more generic fashion. -johnstul@us.ibm.com - */ - if (cpu_has_tsc) { - unsigned long tsc_quotient = calibrate_tsc(); - if (tsc_quotient) { - /* report CPU clock rate in Hz. - * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) = - * clock/second. Our precision is about 100 ppm. - */ - { unsigned long eax=0, edx=1000; - __asm__("divl %2" - :"=a" (cpu_khz), "=d" (edx) - :"r" (tsc_quotient), - "0" (eax), "1" (edx)); - printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000); - } - } - } + init_cpu_khz(); /* Everything looks good! */ return 0; diff -Nru a/arch/i386/kernel/timers/timer_pm.c b/arch/i386/kernel/timers/timer_pm.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/i386/kernel/timers/timer_pm.c Thu Feb 19 23:44:29 2004 @@ -0,0 +1,217 @@ +/* + * (C) Dominik Brodowski 2003 + * + * Driver to use the Power Management Timer (PMTMR) available in some + * southbridges as primary timing source for the Linux kernel. + * + * Based on parts of linux/drivers/acpi/hardware/hwtimer.c, timer_pit.c, + * timer_hpet.c, and on Arjan van de Ven's implementation for 2.4. + * + * This file is licensed under the GPL v2. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* The I/O port the PMTMR resides at. + * The location is detected during setup_arch(), + * in arch/i386/acpi/boot.c */ +u32 pmtmr_ioport = 0; + + +/* value of the Power timer at last timer interrupt */ +static u32 offset_tick; +static u32 offset_delay; + +static unsigned long long monotonic_base; +static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED; + +#define ACPI_PM_MASK 0xFFFFFF /* limit it to 24 bits */ + +/*helper function to safely read acpi pm timesource*/ +static inline u32 read_pmtmr(void) +{ + u32 v1=0,v2=0,v3=0; + /* It has been reported that because of various broken + * chipsets (ICH4, PIIX4 and PIIX4E) where the ACPI PM time + * source is not latched, so you must read it multiple + * times to insure a safe value is read. + */ + do { + v1 = inl(pmtmr_ioport); + v2 = inl(pmtmr_ioport); + v3 = inl(pmtmr_ioport); + } while ((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) + || (v3 > v1 && v3 < v2)); + + /* mask the output to 24 bits */ + return v2 & ACPI_PM_MASK; +} + +static int init_pmtmr(char* override) +{ + u32 value1, value2; + unsigned int i; + + if (override[0] && strncmp(override,"pmtmr",5)) + return -ENODEV; + + if (!pmtmr_ioport) + return -ENODEV; + + /* we use the TSC for delay_pmtmr, so make sure it exists */ + if (!cpu_has_tsc) + return -ENODEV; + + /* "verify" this timing source */ + value1 = read_pmtmr(); + for (i = 0; i < 10000; i++) { + value2 = read_pmtmr(); + if (value2 == value1) + continue; + if (value2 > value1) + goto pm_good; + if ((value2 < value1) && ((value2) < 0xFFF)) + goto pm_good; + printk(KERN_INFO "PM-Timer had inconsistent results: 0x%#x, 0x%#x - aborting.\n", value1, value2); + return -EINVAL; + } + printk(KERN_INFO "PM-Timer had no reasonable result: 0x%#x - aborting.\n", value1); + return -ENODEV; + +pm_good: + init_cpu_khz(); + return 0; +} + +static inline u32 cyc2us(u32 cycles) +{ + /* The Power Management Timer ticks at 3.579545 ticks per microsecond. + * 1 / PM_TIMER_FREQUENCY == 0.27936511 =~ 286/1024 [error: 0.024%] + * + * Even with HZ = 100, delta is at maximum 35796 ticks, so it can + * easily be multiplied with 286 (=0x11E) without having to fear + * u32 overflows. + */ + cycles *= 286; + return (cycles >> 10); +} + +/* + * this gets called during each timer interrupt + * - Called while holding the writer xtime_lock + */ +static void mark_offset_pmtmr(void) +{ + u32 lost, delta, last_offset; + static int first_run = 1; + last_offset = offset_tick; + + write_seqlock(&monotonic_lock); + + offset_tick = read_pmtmr(); + + /* calculate tick interval */ + delta = (offset_tick - last_offset) & ACPI_PM_MASK; + + /* convert to usecs */ + delta = cyc2us(delta); + + /* update the monotonic base value */ + monotonic_base += delta * NSEC_PER_USEC; + write_sequnlock(&monotonic_lock); + + /* convert to ticks */ + delta += offset_delay; + lost = delta / (USEC_PER_SEC / HZ); + offset_delay = delta % (USEC_PER_SEC / HZ); + + + /* compensate for lost ticks */ + if (lost >= 2) + jiffies_64 += lost - 1; + + /* don't calculate delay for first run, + or if we've got less then a tick */ + if (first_run || (lost < 1)) { + first_run = 0; + offset_delay = 0; + } +} + + +static unsigned long long monotonic_clock_pmtmr(void) +{ + u32 last_offset, this_offset; + unsigned long long base, ret; + unsigned seq; + + + /* atomically read monotonic base & last_offset */ + do { + seq = read_seqbegin(&monotonic_lock); + last_offset = offset_tick; + base = monotonic_base; + } while (read_seqretry(&monotonic_lock, seq)); + + /* Read the pmtmr */ + this_offset = read_pmtmr(); + + /* convert to nanoseconds */ + ret = (this_offset - last_offset) & ACPI_PM_MASK; + ret = base + (cyc2us(ret) * NSEC_PER_USEC); + return ret; +} + +static void delay_pmtmr(unsigned long loops) +{ + unsigned long bclock, now; + + rdtscl(bclock); + do + { + rep_nop(); + rdtscl(now); + } while ((now-bclock) < loops); +} + + +/* + * get the offset (in microseconds) from the last call to mark_offset() + * - Called holding a reader xtime_lock + */ +static unsigned long get_offset_pmtmr(void) +{ + u32 now, offset, delta = 0; + + offset = offset_tick; + now = read_pmtmr(); + delta = (now - offset)&ACPI_PM_MASK; + + return (unsigned long) offset_delay + cyc2us(delta); +} + + +/* acpi timer_opts struct */ +struct timer_opts timer_pmtmr = { + .name = "pmtmr", + .init = init_pmtmr, + .mark_offset = mark_offset_pmtmr, + .get_offset = get_offset_pmtmr, + .monotonic_clock = monotonic_clock_pmtmr, + .delay = delay_pmtmr, +}; + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Dominik Brodowski "); +MODULE_DESCRIPTION("Power Management Timer (PMTMR) as primary timing source for x86"); diff -Nru a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c --- a/arch/i386/kernel/traps.c Thu Feb 19 23:44:23 2004 +++ b/arch/i386/kernel/traps.c Thu Feb 19 23:44:23 2004 @@ -119,7 +119,7 @@ unsigned long esp = tsk->thread.esp; /* User space on another CPU? */ - if ((esp ^ (unsigned long)tsk->thread_info) & (PAGE_MASK<<1)) + if ((esp ^ (unsigned long)tsk->thread_info) & ~(THREAD_SIZE - 1)) return; show_trace(tsk, (unsigned long *)esp); } @@ -255,12 +255,27 @@ void die(const char * str, struct pt_regs * regs, long err) { static int die_counter; + int nl = 0; console_verbose(); spin_lock_irq(&die_lock); bust_spinlocks(1); handle_BUG(regs); printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); +#ifdef CONFIG_PREEMPT + printk("PREEMPT "); + nl = 1; +#endif +#ifdef CONFIG_SMP + printk("SMP "); + nl = 1; +#endif +#ifdef CONFIG_DEBUG_PAGEALLOC + printk("DEBUG_PAGEALLOC"); + nl = 1; +#endif + if (nl) + printk("\n"); show_registers(regs); bust_spinlocks(0); spin_unlock_irq(&die_lock); diff -Nru a/arch/i386/oprofile/nmi_int.c b/arch/i386/oprofile/nmi_int.c --- a/arch/i386/oprofile/nmi_int.c Thu Feb 19 23:44:28 2004 +++ b/arch/i386/oprofile/nmi_int.c Thu Feb 19 23:44:28 2004 @@ -295,8 +295,6 @@ }; -#if !defined(CONFIG_X86_64) - static int __init p4_init(void) { __u8 cpu_model = current_cpu_data.x86_model; @@ -335,7 +333,9 @@ if (cpu_model > 0xd) return 0; - if (cpu_model > 5) { + if (cpu_model == 9) { + nmi_ops.cpu_type = "i386/p6_mobile"; + } else if (cpu_model > 5) { nmi_ops.cpu_type = "i386/piii"; } else if (cpu_model > 2) { nmi_ops.cpu_type = "i386/pii"; @@ -347,9 +347,6 @@ return 1; } -#endif /* !CONFIG_X86_64 */ - - /* in order to get driverfs right */ static int using_nmi; @@ -381,7 +378,6 @@ } break; -#if !defined(CONFIG_X86_64) case X86_VENDOR_INTEL: switch (family) { /* Pentium IV */ @@ -400,7 +396,6 @@ return -ENODEV; } break; -#endif /* !CONFIG_X86_64 */ default: return -ENODEV; diff -Nru a/arch/i386/oprofile/nmi_timer_int.c b/arch/i386/oprofile/nmi_timer_int.c --- a/arch/i386/oprofile/nmi_timer_int.c Thu Feb 19 23:44:24 2004 +++ b/arch/i386/oprofile/nmi_timer_int.c Thu Feb 19 23:44:24 2004 @@ -48,9 +48,13 @@ .cpu_type = "timer" }; - int __init nmi_timer_init(struct oprofile_operations ** ops) { + extern int nmi_active; + + if (nmi_active <= 0) + return -ENODEV; + *ops = &nmi_timer_ops; printk(KERN_INFO "oprofile: using NMI timer interrupt.\n"); return 0; diff -Nru a/arch/i386/oprofile/op_model_ppro.c b/arch/i386/oprofile/op_model_ppro.c --- a/arch/i386/oprofile/op_model_ppro.c Thu Feb 19 23:44:26 2004 +++ b/arch/i386/oprofile/op_model_ppro.c Thu Feb 19 23:44:26 2004 @@ -13,6 +13,7 @@ #include #include #include +#include #include "op_x86_model.h" #include "op_counter.h" @@ -100,6 +101,10 @@ CTR_WRITE(reset_value[i], msrs, i); } } + + /* Only P6 based Pentium M need to re-unmask the apic vector but it + * doesn't hurt other P6 variant */ + apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED); /* We can't work out if we really handled an interrupt. We * might have caught a *second* counter just after overflowing diff -Nru a/arch/i386/pci/fixup.c b/arch/i386/pci/fixup.c --- a/arch/i386/pci/fixup.c Thu Feb 19 23:44:26 2004 +++ b/arch/i386/pci/fixup.c Thu Feb 19 23:44:26 2004 @@ -188,22 +188,107 @@ } struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454GX, pci_fixup_i450gx }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5513, pci_fixup_ide_trash }, - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, pci_fixup_latency }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5598, pci_fixup_latency }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, pci_fixup_piix4_acpi }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_10, pci_fixup_ide_trash }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_11, pci_fixup_ide_trash }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_9, pci_fixup_ide_trash }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, pci_fixup_via_northbridge_bug }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8622, pci_fixup_via_northbridge_bug }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8361, pci_fixup_via_northbridge_bug }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8367_0, pci_fixup_via_northbridge_bug }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, pci_fixup_ncr53c810 }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_fixup_transparent_bridge }, - { 0 } + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82451NX, + .hook = pci_fixup_i450nx + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82454GX, + .hook = pci_fixup_i450gx + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_UMC, + .device = PCI_DEVICE_ID_UMC_UM8886BF, + .hook = pci_fixup_umc_ide + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_SI, + .device = PCI_DEVICE_ID_SI_5513, + .hook = pci_fixup_ide_trash + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, + .hook = pci_fixup_ide_bases + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_SI, + .device = PCI_DEVICE_ID_SI_5597, + .hook = pci_fixup_latency + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_SI, + .device = PCI_DEVICE_ID_SI_5598, + .hook = pci_fixup_latency + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82371AB_3, + .hook = pci_fixup_piix4_acpi + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801CA_10, + .hook = pci_fixup_ide_trash + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801CA_11, + .hook = pci_fixup_ide_trash + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82801DB_9, + .hook = pci_fixup_ide_trash + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_8363_0, + .hook = pci_fixup_via_northbridge_bug + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_8622, + .hook = pci_fixup_via_northbridge_bug + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_8361, + .hook = pci_fixup_via_northbridge_bug + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_VIA, + .device = PCI_DEVICE_ID_VIA_8367_0, + .hook = pci_fixup_via_northbridge_bug + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_NCR, + .device = PCI_DEVICE_ID_NCR_53C810, + .hook = pci_fixup_ncr53c810 + }, + { + .pass = PCI_FIXUP_HEADER, + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_ANY_ID, + .hook = pci_fixup_transparent_bridge + }, + { .pass = 0 } }; diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig --- a/arch/ia64/Kconfig Thu Feb 19 23:44:28 2004 +++ b/arch/ia64/Kconfig Thu Feb 19 23:44:28 2004 @@ -245,6 +245,12 @@ Say Y here to enable machine check support for IA-64. If you're unsure, answer Y. +config IA64_CYCLONE + bool "Support Cyclone(EXA) Time Source" + help + Say Y here to enable support for IBM EXA Cyclone time source. + If you're unsure, answer N. + config PM bool "Power Management support" depends on IA64_GENERIC || IA64_DIG || IA64_HP_ZX1 diff -Nru a/arch/ia64/hp/sim/simeth.c b/arch/ia64/hp/sim/simeth.c --- a/arch/ia64/hp/sim/simeth.c Thu Feb 19 23:44:26 2004 +++ b/arch/ia64/hp/sim/simeth.c Thu Feb 19 23:44:26 2004 @@ -224,7 +224,7 @@ err = register_netdev(dev); if (err) { - kfree(dev); + free_netdev(dev); return err; } diff -Nru a/arch/ia64/ia32/sys_ia32.c b/arch/ia64/ia32/sys_ia32.c --- a/arch/ia64/ia32/sys_ia32.c Thu Feb 19 23:44:26 2004 +++ b/arch/ia64/ia32/sys_ia32.c Thu Feb 19 23:44:26 2004 @@ -2413,44 +2413,85 @@ return sys_lseek(fd, offset, whence); } -extern asmlinkage long sys_getgroups (int gidsetsize, gid_t *grouplist); +static int +groups16_to_user(short *grouplist, struct group_info *group_info) +{ + int i; + short group; + + for (i = 0; i < group_info->ngroups; i++) { + group = (short)GROUP_AT(group_info, i); + if (put_user(group, grouplist+i)) + return -EFAULT; + } + + return 0; +} + +static int +groups16_from_user(struct group_info *group_info, short *grouplist) +{ + int i; + short group; + + for (i = 0; i < group_info->ngroups; i++) { + if (get_user(group, grouplist+i)) + return -EFAULT; + GROUP_AT(group_info, i) = (gid_t)group; + } + + return 0; +} asmlinkage long sys32_getgroups16 (int gidsetsize, short *grouplist) { - mm_segment_t old_fs = get_fs(); - gid_t gl[NGROUPS]; - int ret, i; - - set_fs(KERNEL_DS); - ret = sys_getgroups(gidsetsize, gl); - set_fs(old_fs); - - if (gidsetsize && ret > 0 && ret <= NGROUPS) - for (i = 0; i < ret; i++, grouplist++) - if (put_user(gl[i], grouplist)) - return -EFAULT; - return ret; -} + int i; -extern asmlinkage long sys_setgroups (int gidsetsize, gid_t *grouplist); + if (gidsetsize < 0) + return -EINVAL; + + get_group_info(current->group_info); + i = current->group_info->ngroups; + if (gidsetsize) { + if (i > gidsetsize) { + i = -EINVAL; + goto out; + } + if (groups16_to_user(grouplist, current->group_info)) { + i = -EFAULT; + goto out; + } + } +out: + put_group_info(current->group_info); + return i; +} asmlinkage long sys32_setgroups16 (int gidsetsize, short *grouplist) { - mm_segment_t old_fs = get_fs(); - gid_t gl[NGROUPS]; - int ret, i; + struct group_info *group_info; + int retval; - if ((unsigned) gidsetsize > NGROUPS) + if (!capable(CAP_SETGID)) + return -EPERM; + if ((unsigned)gidsetsize > NGROUPS_MAX) return -EINVAL; - for (i = 0; i < gidsetsize; i++, grouplist++) - if (get_user(gl[i], grouplist)) - return -EFAULT; - set_fs(KERNEL_DS); - ret = sys_setgroups(gidsetsize, gl); - set_fs(old_fs); - return ret; + + group_info = groups_alloc(gidsetsize); + if (!group_info) + return -ENOMEM; + retval = groups16_from_user(group_info, grouplist); + if (retval) { + put_group_info(group_info); + return retval; + } + + retval = set_current_groups(group_info); + put_group_info(group_info); + + return retval; } asmlinkage long diff -Nru a/arch/ia64/kernel/Makefile b/arch/ia64/kernel/Makefile --- a/arch/ia64/kernel/Makefile Thu Feb 19 23:44:28 2004 +++ b/arch/ia64/kernel/Makefile Thu Feb 19 23:44:28 2004 @@ -18,6 +18,7 @@ obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_SMP) += smp.o smpboot.o obj-$(CONFIG_PERFMON) += perfmon_default_smpl.o +obj-$(CONFIG_IA64_CYCLONE) += cyclone.o # The gate DSO image is built using a special linker script. targets += gate.so gate-syms.o diff -Nru a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c --- a/arch/ia64/kernel/acpi.c Thu Feb 19 23:44:25 2004 +++ b/arch/ia64/kernel/acpi.c Thu Feb 19 23:44:25 2004 @@ -49,6 +49,8 @@ #include #include #include +#include +#include #define PREFIX "ACPI: " @@ -304,6 +306,22 @@ return 0; } +/* Hook from generic ACPI tables.c */ +void __init acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + if (!strncmp(oem_id, "IBM", 3) && + (!strncmp(oem_table_id, "SERMOW", 6))){ + + /* Unfortunatly ITC_DRIFT is not yet part of the + * official SAL spec, so the ITC_DRIFT bit is not + * set by the BIOS on this hardware. + */ + sal_platform_features |= IA64_SAL_PLATFORM_FEATURE_ITC_DRIFT; + + /*Start cyclone clock*/ + cyclone_setup(0); + } +} static int __init acpi_parse_madt (unsigned long phys_addr, unsigned long size) @@ -327,6 +345,10 @@ ipi_base_addr = (unsigned long) ioremap(acpi_madt->lapic_address, 0); printk(KERN_INFO PREFIX "Local APIC address 0x%lx\n", ipi_base_addr); + + acpi_madt_oem_check(acpi_madt->header.oem_id, + acpi_madt->header.oem_table_id); + return 0; } diff -Nru a/arch/ia64/kernel/cyclone.c b/arch/ia64/kernel/cyclone.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/arch/ia64/kernel/cyclone.c Thu Feb 19 23:44:29 2004 @@ -0,0 +1,158 @@ +#include +#include +#include + +/* IBM Summit (EXA) Cyclone counter code*/ +#define CYCLONE_CBAR_ADDR 0xFEB00CD0 +#define CYCLONE_PMCC_OFFSET 0x51A0 +#define CYCLONE_MPMC_OFFSET 0x51D0 +#define CYCLONE_MPCS_OFFSET 0x51A8 +#define CYCLONE_TIMER_FREQ 100000000 + +int use_cyclone; +int __init cyclone_setup(char *str) +{ + use_cyclone = 1; + return 1; +} + +static u32* volatile cyclone_timer; /* Cyclone MPMC0 register */ +static u32 last_update_cyclone; + +static unsigned long offset_base; + +static unsigned long get_offset_cyclone(void) +{ + u32 now; + unsigned long offset; + + /* Read the cyclone timer */ + now = readl(cyclone_timer); + /* .. relative to previous update*/ + offset = now - last_update_cyclone; + + /* convert cyclone ticks to nanoseconds */ + offset = (offset*NSEC_PER_SEC)/CYCLONE_TIMER_FREQ; + + /* our adjusted time in nanoseconds */ + return offset_base + offset; +} + +static void update_cyclone(long delta_nsec) +{ + u32 now; + unsigned long offset; + + /* Read the cyclone timer */ + now = readl(cyclone_timer); + /* .. relative to previous update*/ + offset = now - last_update_cyclone; + + /* convert cyclone ticks to nanoseconds */ + offset = (offset*NSEC_PER_SEC)/CYCLONE_TIMER_FREQ; + + offset += offset_base; + + /* Be careful about signed/unsigned comparisons here: */ + if (delta_nsec < 0 || (unsigned long) delta_nsec < offset) + offset_base = offset - delta_nsec; + else + offset_base = 0; + + last_update_cyclone = now; +} + +static void reset_cyclone(void) +{ + offset_base = 0; + last_update_cyclone = readl(cyclone_timer); +} + +struct time_interpolator cyclone_interpolator = { + .get_offset = get_offset_cyclone, + .update = update_cyclone, + .reset = reset_cyclone, + .frequency = CYCLONE_TIMER_FREQ, + .drift = -100, +}; + +int __init init_cyclone_clock(void) +{ + u64* reg; + u64 base; /* saved cyclone base address */ + u64 offset; /* offset from pageaddr to cyclone_timer register */ + int i; + + if (!use_cyclone) + return -ENODEV; + + printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n"); + + /* find base address */ + offset = (CYCLONE_CBAR_ADDR); + reg = (u64*)ioremap_nocache(offset, sizeof(u64)); + if(!reg){ + printk(KERN_ERR "Summit chipset: Could not find valid CBAR register.\n"); + use_cyclone = 0; + return -ENODEV; + } + base = readq(reg); + if(!base){ + printk(KERN_ERR "Summit chipset: Could not find valid CBAR value.\n"); + use_cyclone = 0; + return -ENODEV; + } + iounmap(reg); + + /* setup PMCC */ + offset = (base + CYCLONE_PMCC_OFFSET); + reg = (u64*)ioremap_nocache(offset, sizeof(u64)); + if(!reg){ + printk(KERN_ERR "Summit chipset: Could not find valid PMCC register.\n"); + use_cyclone = 0; + return -ENODEV; + } + writel(0x00000001,reg); + iounmap(reg); + + /* setup MPCS */ + offset = (base + CYCLONE_MPCS_OFFSET); + reg = (u64*)ioremap_nocache(offset, sizeof(u64)); + if(!reg){ + printk(KERN_ERR "Summit chipset: Could not find valid MPCS register.\n"); + use_cyclone = 0; + return -ENODEV; + } + writel(0x00000001,reg); + iounmap(reg); + + /* map in cyclone_timer */ + offset = (base + CYCLONE_MPMC_OFFSET); + cyclone_timer = (u32*)ioremap_nocache(offset, sizeof(u32)); + if(!cyclone_timer){ + printk(KERN_ERR "Summit chipset: Could not find valid MPMC register.\n"); + use_cyclone = 0; + return -ENODEV; + } + + /*quick test to make sure its ticking*/ + for(i=0; i<3; i++){ + u32 old = readl(cyclone_timer); + int stall = 100; + while(stall--) barrier(); + if(readl(cyclone_timer) == old){ + printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n"); + iounmap(cyclone_timer); + cyclone_timer = 0; + use_cyclone = 0; + return -ENODEV; + } + } + /* initialize last tick */ + last_update_cyclone = readl(cyclone_timer); + register_time_interpolator(&cyclone_interpolator); + + return 0; +} + +__initcall(init_cyclone_clock); diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c --- a/arch/ia64/kernel/irq.c Thu Feb 19 23:44:27 2004 +++ b/arch/ia64/kernel/irq.c Thu Feb 19 23:44:27 2004 @@ -940,7 +940,7 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, irq_affinity[(long)data]); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -1005,7 +1005,7 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, *(cpumask_t *)data); + int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c --- a/arch/ia64/kernel/unwind.c Thu Feb 19 23:44:29 2004 +++ b/arch/ia64/kernel/unwind.c Thu Feb 19 23:44:29 2004 @@ -1416,7 +1416,7 @@ case UNW_WHERE_FR: if (rval <= 5) - val = unw.preg_index[UNW_REG_F2 + (rval - 1)]; + val = unw.preg_index[UNW_REG_F2 + (rval - 2)]; else if (rval >= 16 && rval <= 31) val = unw.preg_index[UNW_REG_F16 + (rval - 16)]; else { diff -Nru a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c --- a/arch/ia64/pci/pci.c Thu Feb 19 23:44:25 2004 +++ b/arch/ia64/pci/pci.c Thu Feb 19 23:44:25 2004 @@ -153,8 +153,10 @@ res->end = end; res->flags = flags; - if (insert_resource(root, res)) + if (insert_resource(root, res)) { + kfree(res); return -EBUSY; + } return 0; } diff -Nru a/arch/ia64/sn/io/drivers/ioconfig_bus.c b/arch/ia64/sn/io/drivers/ioconfig_bus.c --- a/arch/ia64/sn/io/drivers/ioconfig_bus.c Thu Feb 19 23:44:26 2004 +++ b/arch/ia64/sn/io/drivers/ioconfig_bus.c Thu Feb 19 23:44:26 2004 @@ -16,6 +16,7 @@ #include +#include #include #include #include diff -Nru a/arch/ia64/sn/io/io.c b/arch/ia64/sn/io/io.c --- a/arch/ia64/sn/io/io.c Thu Feb 19 23:44:24 2004 +++ b/arch/ia64/sn/io/io.c Thu Feb 19 23:44:24 2004 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c --- a/arch/ia64/sn/io/machvec/pci_bus_cvlink.c Thu Feb 19 23:44:27 2004 +++ b/arch/ia64/sn/io/machvec/pci_bus_cvlink.c Thu Feb 19 23:44:27 2004 @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -28,7 +27,7 @@ extern void register_pcibr_intr(int irq, pcibr_intr_t intr); -static void sn_dma_flush_init(unsigned long start, +static struct sn_flush_device_list *sn_dma_flush_init(unsigned long start, unsigned long end, int idx, int pin, int slot); extern int cbrick_type_get_nasid(nasid_t); @@ -54,7 +53,7 @@ } /* - * pci_bus_cvlink_init() - To be called once during initialization before + * pci_bus_cvlink_init() - To be called once during initialization before * SGI IO Infrastructure init is called. */ int @@ -74,7 +73,7 @@ } /* - * pci_bus_to_vertex() - Given a logical Linux Bus Number returns the associated + * pci_bus_to_vertex() - Given a logical Linux Bus Number returns the associated * pci bus vertex from the SGI IO Infrastructure. */ static inline vertex_hdl_t @@ -92,7 +91,7 @@ } /* - * devfn_to_vertex() - returns the vertex of the device given the bus, slot, + * devfn_to_vertex() - returns the vertex of the device given the bus, slot, * and function numbers. */ vertex_hdl_t @@ -133,8 +132,8 @@ * ../pci/1, ../pci/2 .. */ if (func == 0) { - sprintf(name, "%d", slot); - if (hwgraph_traverse(pci_bus, name, &device_vertex) == + sprintf(name, "%d", slot); + if (hwgraph_traverse(pci_bus, name, &device_vertex) == GRAPH_SUCCESS) { if (device_vertex) { return(device_vertex); @@ -156,19 +155,248 @@ return(device_vertex); } +/* + * sn_alloc_pci_sysdata() - This routine allocates a pci controller + * which is expected as the pci_dev and pci_bus sysdata by the Linux + * PCI infrastructure. + */ +static struct pci_controller * +sn_alloc_pci_sysdata(void) +{ + struct pci_controller *pci_sysdata; + + pci_sysdata = kmalloc(sizeof(*pci_sysdata), GFP_KERNEL); + if (!pci_sysdata) + return NULL; + + memset(pci_sysdata, 0, sizeof(*pci_sysdata)); + return pci_sysdata; +} + +/* + * sn_pci_fixup_bus() - This routine sets up a bus's resources + * consistent with the Linux PCI abstraction layer. + */ +static int __init +sn_pci_fixup_bus(struct pci_bus *bus) +{ + struct pci_controller *pci_sysdata; + struct sn_widget_sysdata *widget_sysdata; + + pci_sysdata = sn_alloc_pci_sysdata(); + if (!pci_sysdata) { + printk(KERN_WARNING "sn_pci_fixup_bus(): Unable to " + "allocate memory for pci_sysdata\n"); + return -ENOMEM; + } + widget_sysdata = kmalloc(sizeof(struct sn_widget_sysdata), + GFP_KERNEL); + if (!widget_sysdata) { + printk(KERN_WARNING "sn_pci_fixup_bus(): Unable to " + "allocate memory for widget_sysdata\n"); + kfree(pci_sysdata); + return -ENOMEM; + } + + widget_sysdata->vhdl = pci_bus_to_vertex(bus->number); + pci_sysdata->platform_data = (void *)widget_sysdata; + bus->sysdata = pci_sysdata; + return 0; +} + + +/* + * sn_pci_fixup_slot() - This routine sets up a slot's resources + * consistent with the Linux PCI abstraction layer. Resources acquired + * from our PCI provider include PIO maps to BAR space and interrupt + * objects. + */ +static int +sn_pci_fixup_slot(struct pci_dev *dev) +{ + extern int bit_pos_to_irq(int); + unsigned int irq; + int idx; + u16 cmd; + vertex_hdl_t vhdl; + unsigned long size; + struct pci_controller *pci_sysdata; + struct sn_device_sysdata *device_sysdata; + pciio_intr_line_t lines = 0; + vertex_hdl_t device_vertex; + pciio_provider_t *pci_provider; + pciio_intr_t intr_handle; + + /* Allocate a controller structure */ + pci_sysdata = sn_alloc_pci_sysdata(); + if (!pci_sysdata) { + printk(KERN_WARNING "sn_pci_fixup_slot: Unable to " + "allocate memory for pci_sysdata\n"); + return -ENOMEM; + } + + /* Set the device vertex */ + device_sysdata = kmalloc(sizeof(struct sn_device_sysdata), GFP_KERNEL); + if (!device_sysdata) { + printk(KERN_WARNING "sn_pci_fixup_slot: Unable to " + "allocate memory for device_sysdata\n"); + kfree(pci_sysdata); + return -ENOMEM; + } + + device_sysdata->vhdl = devfn_to_vertex(dev->bus->number, dev->devfn); + pci_sysdata->platform_data = (void *) device_sysdata; + dev->sysdata = pci_sysdata; + set_pci_provider(device_sysdata); + + pci_read_config_word(dev, PCI_COMMAND, &cmd); + + /* + * Set the resources address correctly. The assumption here + * is that the addresses in the resource structure has been + * read from the card and it was set in the card by our + * Infrastructure. NOTE: PIC and TIOCP don't have big-window + * upport for PCI I/O space. So by mapping the I/O space + * first we will attempt to use Device(x) registers for I/O + * BARs (which can't use big windows like MEM BARs can). + */ + vhdl = device_sysdata->vhdl; + + /* Allocate the IORESOURCE_IO space first */ + for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { + unsigned long start, end, addr; + + device_sysdata->pio_map[idx] = NULL; + + if (!(dev->resource[idx].flags & IORESOURCE_IO)) + continue; + + start = dev->resource[idx].start; + end = dev->resource[idx].end; + size = end - start; + if (!size) + continue; + + addr = (unsigned long)pciio_pio_addr(vhdl, 0, + PCIIO_SPACE_WIN(idx), 0, size, + &device_sysdata->pio_map[idx], 0); + + if (!addr) { + dev->resource[idx].start = 0; + dev->resource[idx].end = 0; + printk("sn_pci_fixup(): pio map failure for " + "%s bar%d\n", dev->slot_name, idx); + } else { + addr |= __IA64_UNCACHED_OFFSET; + dev->resource[idx].start = addr; + dev->resource[idx].end = addr + size; + } + + if (dev->resource[idx].flags & IORESOURCE_IO) + cmd |= PCI_COMMAND_IO; + } + + /* Allocate the IORESOURCE_MEM space next */ + for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { + unsigned long start, end, addr; + + if ((dev->resource[idx].flags & IORESOURCE_IO)) + continue; + + start = dev->resource[idx].start; + end = dev->resource[idx].end; + size = end - start; + if (!size) + continue; + + addr = (unsigned long)pciio_pio_addr(vhdl, 0, + PCIIO_SPACE_WIN(idx), 0, size, + &device_sysdata->pio_map[idx], 0); + + if (!addr) { + dev->resource[idx].start = 0; + dev->resource[idx].end = 0; + printk("sn_pci_fixup(): pio map failure for " + "%s bar%d\n", dev->slot_name, idx); + } else { + addr |= __IA64_UNCACHED_OFFSET; + dev->resource[idx].start = addr; + dev->resource[idx].end = addr + size; + } + + if (dev->resource[idx].flags & IORESOURCE_MEM) + cmd |= PCI_COMMAND_MEMORY; + } + + /* + * Update the Command Word on the Card. + */ + cmd |= PCI_COMMAND_MASTER; /* If the device doesn't support */ + /* bit gets dropped .. no harm */ + pci_write_config_word(dev, PCI_COMMAND, cmd); + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, (unsigned char *)&lines); + device_vertex = device_sysdata->vhdl; + pci_provider = device_sysdata->pci_provider; + device_sysdata->intr_handle = NULL; + + if (!lines) + return 0; + + irqpdaindr->curr = dev; + + intr_handle = (pci_provider->intr_alloc)(device_vertex, NULL, lines, device_vertex); + if (intr_handle == NULL) { + printk(KERN_WARNING "sn_pci_fixup: pcibr_intr_alloc() failed\n"); + kfree(pci_sysdata); + kfree(device_sysdata); + return -ENOMEM; + } + + device_sysdata->intr_handle = intr_handle; + irq = intr_handle->pi_irq; + irqpdaindr->device_dev[irq] = dev; + (pci_provider->intr_connect)(intr_handle, (intr_func_t)0, (intr_arg_t)0); + dev->irq = irq; + + register_pcibr_intr(irq, (pcibr_intr_t)intr_handle); + + for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { + int ibits = ((pcibr_intr_t)intr_handle)->bi_ibits; + int i; + + size = dev->resource[idx].end - + dev->resource[idx].start; + if (size == 0) continue; + + for (i=0; i<8; i++) { + if (ibits & (1 << i) ) { + extern pcibr_info_t pcibr_info_get(vertex_hdl_t); + device_sysdata->dma_flush_list = + sn_dma_flush_init(dev->resource[idx].start, + dev->resource[idx].end, + idx, + i, + PCIBR_INFO_SLOT_GET_EXT(pcibr_info_get(device_sysdata->vhdl))); + } + } + } + return 0; +} + struct sn_flush_nasid_entry flush_nasid_list[MAX_NASIDS]; /* Initialize the data structures for flushing write buffers after a PIO read. - * The theory is: + * The theory is: * Take an unused int. pin and associate it with a pin that is in use. * After a PIO read, force an interrupt on the unused pin, forcing a write buffer flush - * on the in use pin. This will prevent the race condition between PIO read responses and + * on the in use pin. This will prevent the race condition between PIO read responses and * DMA writes. */ -static void +static struct sn_flush_device_list * sn_dma_flush_init(unsigned long start, unsigned long end, int idx, int pin, int slot) { - nasid_t nasid; + nasid_t nasid; unsigned long dnasid; int wid_num; int bus; @@ -187,7 +415,7 @@ sizeof(struct sn_flush_device_list *), GFP_KERNEL); if (!flush_nasid_list[nasid].widget_p) { printk(KERN_WARNING "sn_dma_flush_init: Cannot allocate memory for nasid list\n"); - return; + return NULL; } memset(flush_nasid_list[nasid].widget_p, 0, (HUB_WIDGET_ID_MAX+1) * sizeof(struct sn_flush_device_list *)); } @@ -197,8 +425,8 @@ itte = HUB_L(IIO_ITTE_GET(nasid, itte_index)); flush_nasid_list[nasid].iio_itte[bwin] = itte; - wid_num = (itte >> IIO_ITTE_WIDGET_SHIFT) & - IIO_ITTE_WIDGET_MASK; + wid_num = (itte >> IIO_ITTE_WIDGET_SHIFT) + & IIO_ITTE_WIDGET_MASK; bus = itte & IIO_ITTE_OFFSET_MASK; if (bus == 0x4 || bus == 0x8) { bus = 0; @@ -211,16 +439,16 @@ * because these are the IOC4 slots and we don't flush them. */ if (isIO9(nasid) && bus == 0 && (slot == 1 || slot == 4)) { - return; + return NULL; } if (flush_nasid_list[nasid].widget_p[wid_num] == NULL) { flush_nasid_list[nasid].widget_p[wid_num] = (struct sn_flush_device_list *)kmalloc( DEV_PER_WIDGET * sizeof (struct sn_flush_device_list), GFP_KERNEL); if (!flush_nasid_list[nasid].widget_p[wid_num]) { printk(KERN_WARNING "sn_dma_flush_init: Cannot allocate memory for nasid sub-list\n"); - return; + return NULL; } - memset(flush_nasid_list[nasid].widget_p[wid_num], 0, + memset(flush_nasid_list[nasid].widget_p[wid_num], 0, DEV_PER_WIDGET * sizeof (struct sn_flush_device_list)); p = &flush_nasid_list[nasid].widget_p[wid_num][0]; for (i=0; iflush_addr)); pcireg_bridge_intr_addr_set(b, 6, ((virt_to_phys(&p->flush_addr) & 0xfffffffff) | - (dnasid << 36) | (0xfUL << 48))); + (dnasid << 36) | (0xfUL << 48))); } else if (pin == 2) { /* 12160 SCSI device in IO9 */ p->force_int_addr = (unsigned long)pcireg_bridge_force_always_addr_get(b, 4); pcireg_bridge_intr_device_bit_set(b, (2<<12)); dnasid = NASID_GET(virt_to_phys(&p->flush_addr)); pcireg_bridge_intr_addr_set(b, 4, ((virt_to_phys(&p->flush_addr) & 0xfffffffff) | - (dnasid << 36) | (0xfUL << 48))); + (dnasid << 36) | (0xfUL << 48))); } else { /* slot == 6 */ p->force_int_addr = (unsigned long)pcireg_bridge_force_always_addr_get(b, 7); pcireg_bridge_intr_device_bit_set(b, (5<<21)); dnasid = NASID_GET(virt_to_phys(&p->flush_addr)); pcireg_bridge_intr_addr_set(b, 7, ((virt_to_phys(&p->flush_addr) & 0xfffffffff) | - (dnasid << 36) | (0xfUL << 48))); + (dnasid << 36) | (0xfUL << 48))); } } else { p->force_int_addr = (unsigned long)pcireg_bridge_force_always_addr_get(b, (pin +2)); @@ -301,239 +529,13 @@ dnasid = NASID_GET(virt_to_phys(&p->flush_addr)); pcireg_bridge_intr_addr_set(b, (pin + 2), ((virt_to_phys(&p->flush_addr) & 0xfffffffff) | - (dnasid << 36) | (0xfUL << 48))); - } -} - -/* - * sn_pci_fixup() - This routine is called when platform_pci_fixup() is - * invoked at the end of pcibios_init() to link the Linux pci - * infrastructure to SGI IO Infrasturcture - ia64/kernel/pci.c - * - * Other platform specific fixup can also be done here. - */ -static void __init -sn_pci_fixup(int arg) -{ - struct list_head *ln; - struct pci_bus *pci_bus = NULL; - struct pci_dev *device_dev = NULL; - struct sn_widget_sysdata *widget_sysdata; - struct sn_device_sysdata *device_sysdata; - pcibr_intr_t intr_handle; - pciio_provider_t *pci_provider; - vertex_hdl_t device_vertex; - pciio_intr_line_t lines = 0; - extern int numnodes; - int cnode; - - if (arg == 0) { -#ifdef CONFIG_PROC_FS - extern void register_sn_procfs(void); -#endif - extern void sgi_master_io_infr_init(void); - extern void sn_init_cpei_timer(void); - - sgi_master_io_infr_init(); - - for (cnode = 0; cnode < numnodes; cnode++) { - extern void intr_init_vecblk(cnodeid_t); - intr_init_vecblk(cnode); - } - - sn_init_cpei_timer(); - -#ifdef CONFIG_PROC_FS - register_sn_procfs(); -#endif - return; - } - - - done_probing = 1; - - /* - * Initialize the pci bus vertex in the pci_bus struct. - */ - for( ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) { - pci_bus = pci_bus_b(ln); - widget_sysdata = kmalloc(sizeof(struct sn_widget_sysdata), - GFP_KERNEL); - if (!widget_sysdata) { - printk(KERN_WARNING "sn_pci_fixup(): Unable to " - "allocate memory for widget_sysdata\n"); - return; - } - widget_sysdata->vhdl = pci_bus_to_vertex(pci_bus->number); - pci_bus->sysdata = (void *)widget_sysdata; - } - - /* - * set the root start and end so that drivers calling check_region() - * won't see a conflict - */ - -#ifdef CONFIG_IA64_SGI_SN_SIM - if (! IS_RUNNING_ON_SIMULATOR()) { - ioport_resource.start = 0xc000000000000000; - ioport_resource.end = 0xcfffffffffffffff; - } -#endif - - /* - * Set the root start and end for Mem Resource. - */ - iomem_resource.start = 0; - iomem_resource.end = 0xffffffffffffffff; - - /* - * Initialize the device vertex in the pci_dev struct. - */ - while ((device_dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, device_dev)) != NULL) { - unsigned int irq; - int idx; - u16 cmd; - vertex_hdl_t vhdl; - unsigned long size; - extern int bit_pos_to_irq(int); - - /* Set the device vertex */ - - device_sysdata = kmalloc(sizeof(struct sn_device_sysdata), - GFP_KERNEL); - if (!device_sysdata) { - printk(KERN_WARNING "sn_pci_fixup: Cannot allocate memory for device sysdata\n"); - return; - } - - device_sysdata->vhdl = devfn_to_vertex(device_dev->bus->number, device_dev->devfn); - device_dev->sysdata = (void *) device_sysdata; - set_pci_provider(device_sysdata); - - pci_read_config_word(device_dev, PCI_COMMAND, &cmd); - - /* - * Set the resources address correctly. The assumption here - * is that the addresses in the resource structure has been - * read from the card and it was set in the card by our - * Infrastructure .. - */ - vhdl = device_sysdata->vhdl; - /* Allocate the IORESOURCE_IO space first */ - for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { - unsigned long start, end, addr; - - if (!(device_dev->resource[idx].flags & IORESOURCE_IO)) - continue; - - start = device_dev->resource[idx].start; - end = device_dev->resource[idx].end; - size = end - start; - if (!size) - continue; - - addr = (unsigned long)pciio_pio_addr(vhdl, 0, - PCIIO_SPACE_WIN(idx), 0, size, 0, 0); - if (!addr) { - device_dev->resource[idx].start = 0; - device_dev->resource[idx].end = 0; - printk("sn_pci_fixup(): pio map failure for " - "%s bar%d\n", device_dev->slot_name, idx); - } else { - addr |= __IA64_UNCACHED_OFFSET; - device_dev->resource[idx].start = addr; - device_dev->resource[idx].end = addr + size; - } - - if (device_dev->resource[idx].flags & IORESOURCE_IO) - cmd |= PCI_COMMAND_IO; - } - - /* Allocate the IORESOURCE_MEM space next */ - for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { - unsigned long start, end, addr; - - if ((device_dev->resource[idx].flags & IORESOURCE_IO)) - continue; - - start = device_dev->resource[idx].start; - end = device_dev->resource[idx].end; - size = end - start; - if (!size) - continue; - - addr = (unsigned long)pciio_pio_addr(vhdl, 0, - PCIIO_SPACE_WIN(idx), 0, size, 0, 0); - if (!addr) { - device_dev->resource[idx].start = 0; - device_dev->resource[idx].end = 0; - printk("sn_pci_fixup(): pio map failure for " - "%s bar%d\n", device_dev->slot_name, idx); - } else { - addr |= __IA64_UNCACHED_OFFSET; - device_dev->resource[idx].start = addr; - device_dev->resource[idx].end = addr + size; - } - - if (device_dev->resource[idx].flags & IORESOURCE_MEM) - cmd |= PCI_COMMAND_MEMORY; - } - - /* - * Update the Command Word on the Card. - */ - cmd |= PCI_COMMAND_MASTER; /* If the device doesn't support */ - /* bit gets dropped .. no harm */ - pci_write_config_word(device_dev, PCI_COMMAND, cmd); - - pci_read_config_byte(device_dev, PCI_INTERRUPT_PIN, - (unsigned char *)&lines); - device_sysdata = (struct sn_device_sysdata *)device_dev->sysdata; - device_vertex = device_sysdata->vhdl; - pci_provider = device_sysdata->pci_provider; - - if (!lines) { - continue; - } - - irqpdaindr->curr = device_dev; - intr_handle = (pci_provider->intr_alloc)(device_vertex, NULL, lines, device_vertex); - - if (intr_handle == NULL) { - printk("sn_pci_fixup: pcibr_intr_alloc() failed\n"); - continue; - } - irq = intr_handle->bi_irq; - irqpdaindr->device_dev[irq] = device_dev; - (pci_provider->intr_connect)(intr_handle, (intr_func_t)0, (intr_arg_t)0); - device_dev->irq = irq; - register_pcibr_intr(irq, (pcibr_intr_t)intr_handle); - - for (idx = 0; idx < PCI_ROM_RESOURCE; idx++) { - int ibits = intr_handle->bi_ibits; - int i; - - size = device_dev->resource[idx].end - - device_dev->resource[idx].start; - if (size == 0) - continue; - - for (i=0; i<8; i++) { - if (ibits & (1 << i) ) { - sn_dma_flush_init(device_dev->resource[idx].start, - device_dev->resource[idx].end, - idx, - i, - PCIBR_INFO_SLOT_GET_EXT(pcibr_info_get(device_sysdata->vhdl))); - } - } - } - + (dnasid << 36) | (0xfUL << 48))); } + return p; } /* - * linux_bus_cvlink() Creates a link between the Linux PCI Bus number + * linux_bus_cvlink() Creates a link between the Linux PCI Bus number * to the actual hardware component that it represents: * /dev/hw/linux/busnum/0 -> ../../../hw/module/001c01/slab/0/Ibrick/xtalk/15/pci * @@ -553,7 +555,7 @@ continue; sprintf(name, "%x", index); - (void) hwgraph_edge_add(linux_busnum, busnum_to_pcibr_vhdl[index], + (void) hwgraph_edge_add(linux_busnum, busnum_to_pcibr_vhdl[index], name); } } @@ -564,7 +566,7 @@ * Linux PCI Bus numbers are assigned from lowest module_id numbers * (rack/slot etc.) */ -static int +static int pci_bus_map_create(struct pcibr_list_s *softlistp, moduleid_t moduleid) { @@ -574,10 +576,10 @@ memset(moduleid_str, 0, 16); format_module_id(moduleid_str, moduleid, MODULE_FORMAT_BRIEF); - (void) ioconfig_get_busnum((char *)moduleid_str, &basebus_num); + (void) ioconfig_get_busnum((char *)moduleid_str, &basebus_num); /* - * Assign the correct bus number and also the nasid of this + * Assign the correct bus number and also the nasid of this * pci Xwidget. */ bus_number = basebus_num + pcibr_widget_to_bus(pci_bus); @@ -605,20 +607,20 @@ printk("pci_bus_map_create: Cannot allocate memory for ate maps\n"); return -1; } - memset(busnum_to_atedmamaps[bus_number], 0x0, + memset(busnum_to_atedmamaps[bus_number], 0x0, sizeof(struct pcibr_dmamap_s) * MAX_ATE_MAPS); return(0); } /* - * pci_bus_to_hcl_cvlink() - This routine is called after SGI IO Infrastructure + * pci_bus_to_hcl_cvlink() - This routine is called after SGI IO Infrastructure * initialization has completed to set up the mappings between PCI BRIDGE - * ASIC and logical pci bus numbers. + * ASIC and logical pci bus numbers. * * Must be called before pci_init() is invoked. */ int -pci_bus_to_hcl_cvlink(void) +pci_bus_to_hcl_cvlink(void) { int i; extern pcibr_list_p pcibr_list; @@ -635,7 +637,7 @@ /* Is this PCI bus associated with this moduleid? */ moduleid = NODE_MODULEID( - NASID_TO_COMPACT_NODEID(pcibr_soft->bs_nasid)); + NASID_TO_COMPACT_NODEID(pcibr_soft->bs_nasid)); if (modules[i]->id == moduleid) { struct pcibr_list_s *new_element; @@ -656,9 +658,9 @@ continue; } - /* - * BASEIO IObricks attached to a module have - * a higher priority than non BASEIO IOBricks + /* + * BASEIO IObricks attached to a module have + * a higher priority than non BASEIO IOBricks * when it comes to persistant pci bus * numbering, so put them on the front of the * list. @@ -674,7 +676,7 @@ softlistp = softlistp->bl_next; } - /* + /* * We now have a list of all the pci bridges associated with * the module_id, modules[i]. Call pci_bus_map_create() for * each pci bridge @@ -702,13 +704,26 @@ /* * Ugly hack to get PCI setup until we have a proper ACPI namespace. */ + +#define PCI_BUSES_TO_SCAN 256 + extern struct pci_ops sn_pci_ops; int __init sn_pci_init (void) { -# define PCI_BUSES_TO_SCAN 256 int i = 0; struct pci_controller *controller; + struct list_head *ln; + struct pci_bus *pci_bus = NULL; + struct pci_dev *pci_dev = NULL; + extern int numnodes; + int cnode, ret; +#ifdef CONFIG_PROC_FS + extern void register_sn_procfs(void); +#endif + extern void sgi_master_io_infr_init(void); + extern void sn_init_cpei_timer(void); + if (!ia64_platform_is("sn2") || IS_RUNNING_ON_SIMULATOR()) return 0; @@ -721,7 +736,19 @@ /* * set pci_raw_ops, etc. */ - sn_pci_fixup(0); + + sgi_master_io_infr_init(); + + for (cnode = 0; cnode < numnodes; cnode++) { + extern void intr_init_vecblk(cnodeid_t); + intr_init_vecblk(cnode); + } + + sn_init_cpei_timer(); + +#ifdef CONFIG_PROC_FS + register_sn_procfs(); +#endif controller = kmalloc(sizeof(struct pci_controller), GFP_KERNEL); if (controller) { @@ -734,7 +761,53 @@ /* * actually find devices and fill in hwgraph structs */ - sn_pci_fixup(1); + + done_probing = 1; + + /* + * Initialize the pci bus vertex in the pci_bus struct. + */ + for( ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) { + pci_bus = pci_bus_b(ln); + ret = sn_pci_fixup_bus(pci_bus); + if ( ret ) { + printk(KERN_WARNING + "sn_pci_fixup: sn_pci_fixup_bus fails : error %d\n", + ret); + return; + } + } + + /* + * set the root start and end so that drivers calling check_region() + * won't see a conflict + */ + +#ifdef CONFIG_IA64_SGI_SN_SIM + if (! IS_RUNNING_ON_SIMULATOR()) { + ioport_resource.start = 0xc000000000000000; + ioport_resource.end = 0xcfffffffffffffff; + } +#endif + + /* + * Set the root start and end for Mem Resource. + */ + iomem_resource.start = 0; + iomem_resource.end = 0xffffffffffffffff; + + /* + * Initialize the device vertex in the pci_dev struct. + */ + while ((pci_dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) != NULL) { + ret = sn_pci_fixup_slot(pci_dev); + if ( ret ) { + printk(KERN_WARNING + "sn_pci_fixup: sn_pci_fixup_slot fails : error %d\n", + ret); + return; + } + } return 0; } diff -Nru a/arch/ia64/sn/io/machvec/pci_dma.c b/arch/ia64/sn/io/machvec/pci_dma.c --- a/arch/ia64/sn/io/machvec/pci_dma.c Thu Feb 19 23:44:24 2004 +++ b/arch/ia64/sn/io/machvec/pci_dma.c Thu Feb 19 23:44:24 2004 @@ -127,7 +127,7 @@ /* * Get hwgraph vertex for the device */ - device_sysdata = (struct sn_device_sysdata *) hwdev->sysdata; + device_sysdata = SN_DEVICE_SYSDATA(hwdev); vhdl = device_sysdata->vhdl; /* @@ -240,7 +240,7 @@ /* * Get the hwgraph vertex for the device */ - device_sysdata = (struct sn_device_sysdata *) hwdev->sysdata; + device_sysdata = SN_DEVICE_SYSDATA(hwdev); vhdl = device_sysdata->vhdl; /* @@ -367,7 +367,7 @@ /* * find vertex for the device */ - device_sysdata = (struct sn_device_sysdata *)hwdev->sysdata; + device_sysdata = SN_DEVICE_SYSDATA(hwdev); vhdl = device_sysdata->vhdl; /* diff -Nru a/arch/ia64/sn/io/sn2/bte_error.c b/arch/ia64/sn/io/sn2/bte_error.c --- a/arch/ia64/sn/io/sn2/bte_error.c Thu Feb 19 23:44:26 2004 +++ b/arch/ia64/sn/io/sn2/bte_error.c Thu Feb 19 23:44:26 2004 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/geo_op.c b/arch/ia64/sn/io/sn2/geo_op.c --- a/arch/ia64/sn/io/sn2/geo_op.c Thu Feb 19 23:44:26 2004 +++ b/arch/ia64/sn/io/sn2/geo_op.c Thu Feb 19 23:44:26 2004 @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/klconflib.c b/arch/ia64/sn/io/sn2/klconflib.c --- a/arch/ia64/sn/io/sn2/klconflib.c Thu Feb 19 23:44:22 2004 +++ b/arch/ia64/sn/io/sn2/klconflib.c Thu Feb 19 23:44:22 2004 @@ -474,8 +474,6 @@ return(0); } -#include "asm/sn/sn_private.h" - /* * Format a module id for printing. * diff -Nru a/arch/ia64/sn/io/sn2/ml_SN_init.c b/arch/ia64/sn/io/sn2/ml_SN_init.c --- a/arch/ia64/sn/io/sn2/ml_SN_init.c Thu Feb 19 23:44:22 2004 +++ b/arch/ia64/sn/io/sn2/ml_SN_init.c Thu Feb 19 23:44:22 2004 @@ -11,12 +11,12 @@ #include #include #include -#include #include #include #include #include #include +#include int maxcpus; @@ -69,12 +69,15 @@ } void -init_platform_hubinfo(nodepda_t **nodepdaindr) { +init_platform_hubinfo(nodepda_t **nodepdaindr) +{ cnodeid_t cnode; hubinfo_t hubinfo; nodepda_t *npda; extern int numionodes; + if (IS_RUNNING_ON_SIMULATOR()) + return; for (cnode = 0; cnode < numionodes; cnode++) { npda = nodepdaindr[cnode]; hubinfo = (hubinfo_t)npda->pdinfo; diff -Nru a/arch/ia64/sn/io/sn2/ml_SN_intr.c b/arch/ia64/sn/io/sn2/ml_SN_intr.c --- a/arch/ia64/sn/io/sn2/ml_SN_intr.c Thu Feb 19 23:44:27 2004 +++ b/arch/ia64/sn/io/sn2/ml_SN_intr.c Thu Feb 19 23:44:27 2004 @@ -30,6 +30,7 @@ #include #include #include +#include extern irqpda_t *irqpdaindr; extern cnodeid_t master_node_get(vertex_hdl_t vhdl); @@ -216,7 +217,6 @@ { cpuid_t cpu, best_cpu = CPU_NONE; int slice, min_count = 1000; - irqpda_t *irqs; for (slice = CPUS_PER_NODE - 1; slice >= 0; slice--) { int intrs; @@ -227,8 +227,7 @@ if (!cpu_online(cpu)) continue; - irqs = irqpdaindr; - intrs = irqs->num_irq_used; + intrs = pdacpu(cpu)->sn_num_irqs; if (min_count > intrs) { min_count = intrs; @@ -243,6 +242,7 @@ } } } + pdacpu(best_cpu)->sn_num_irqs++; return best_cpu; } diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c Thu Feb 19 23:44:23 2004 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_ate.c Thu Feb 19 23:44:23 2004 @@ -8,7 +8,6 @@ #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c Thu Feb 19 23:44:27 2004 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c Thu Feb 19 23:44:27 2004 @@ -8,7 +8,6 @@ #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c Thu Feb 19 23:44:27 2004 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_intr.c Thu Feb 19 23:44:27 2004 @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_reg.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_reg.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_reg.c Thu Feb 19 23:44:27 2004 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_reg.c Thu Feb 19 23:44:27 2004 @@ -8,7 +8,6 @@ #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c b/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c --- a/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c Thu Feb 19 23:44:28 2004 +++ b/arch/ia64/sn/io/sn2/pcibr/pcibr_rrb.c Thu Feb 19 23:44:28 2004 @@ -8,7 +8,6 @@ #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/pic.c b/arch/ia64/sn/io/sn2/pic.c --- a/arch/ia64/sn/io/sn2/pic.c Thu Feb 19 23:44:26 2004 +++ b/arch/ia64/sn/io/sn2/pic.c Thu Feb 19 23:44:26 2004 @@ -90,10 +90,15 @@ peer_widget_info->w_efunc = 0; peer_widget_info->w_einfo = 0; peer_widget_info->w_name = kmalloc(strlen(peer_path) + 1, GFP_KERNEL); + if (!peer_widget_info->w_name) { + kfree(peer_widget_info); + return -ENOMEM; + } strcpy(peer_widget_info->w_name, peer_path); if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_XWIDGET, (arbitrary_info_t)peer_widget_info) != GRAPH_SUCCESS) { + kfree(peer_widget_info->w_name); kfree(peer_widget_info); return 0; } @@ -359,6 +364,9 @@ s = dev_to_name(pcibr_vhdl, devnm, MAXDEVNAME); pcibr_soft->bs_name = kmalloc(strlen(s) + 1, GFP_KERNEL); + if (!pcibr_soft->bs_name) + return -ENOMEM; + strcpy(pcibr_soft->bs_name, s); pcibr_soft->bs_conn = xconn_vhdl; diff -Nru a/arch/ia64/sn/io/sn2/shub.c b/arch/ia64/sn/io/sn2/shub.c --- a/arch/ia64/sn/io/sn2/shub.c Thu Feb 19 23:44:25 2004 +++ b/arch/ia64/sn/io/sn2/shub.c Thu Feb 19 23:44:25 2004 @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/shub_intr.c b/arch/ia64/sn/io/sn2/shub_intr.c --- a/arch/ia64/sn/io/sn2/shub_intr.c Thu Feb 19 23:44:25 2004 +++ b/arch/ia64/sn/io/sn2/shub_intr.c Thu Feb 19 23:44:25 2004 @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/sn2/shuberror.c b/arch/ia64/sn/io/sn2/shuberror.c --- a/arch/ia64/sn/io/sn2/shuberror.c Thu Feb 19 23:44:28 2004 +++ b/arch/ia64/sn/io/sn2/shuberror.c Thu Feb 19 23:44:28 2004 @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/io/xswitch.c b/arch/ia64/sn/io/xswitch.c --- a/arch/ia64/sn/io/xswitch.c Thu Feb 19 23:44:23 2004 +++ b/arch/ia64/sn/io/xswitch.c Thu Feb 19 23:44:23 2004 @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff -Nru a/arch/ia64/sn/kernel/irq.c b/arch/ia64/sn/kernel/irq.c --- a/arch/ia64/sn/kernel/irq.c Thu Feb 19 23:44:23 2004 +++ b/arch/ia64/sn/kernel/irq.c Thu Feb 19 23:44:23 2004 @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -121,7 +120,7 @@ static void sn_set_affinity_irq(unsigned int irq, unsigned long cpu) { -#if CONFIG_SMP +#ifdef CONFIG_SMP int redir = 0; struct sn_intr_list_t *p = sn_intr_list[irq]; pcibr_intr_t intr; diff -Nru a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c --- a/arch/ia64/sn/kernel/setup.c Thu Feb 19 23:44:24 2004 +++ b/arch/ia64/sn/kernel/setup.c Thu Feb 19 23:44:24 2004 @@ -85,6 +85,7 @@ u64 master_node_bedrock_address; static void sn_init_pdas(char **); +static void scan_for_ionodes(void); static nodepda_t *nodepdaindr[MAX_COMPACT_NODES]; @@ -131,7 +132,7 @@ * may not be initialized yet. */ -static int +static int __init pxm_to_nasid(int pxm) { int i; @@ -358,11 +359,10 @@ * * One time setup for Node Data Area. Called by sn_setup(). */ -void +void __init sn_init_pdas(char **cmdline_p) { cnodeid_t cnode; - void scan_for_ionodes(void); /* * Make sure that the PDA fits entirely in the same page as the @@ -498,7 +498,7 @@ * physical_node_map and the pda and increment numionodes. */ -void +static void __init scan_for_ionodes(void) { int nasid = 0; diff -Nru a/arch/m68k/Kconfig b/arch/m68k/Kconfig --- a/arch/m68k/Kconfig Thu Feb 19 23:44:26 2004 +++ b/arch/m68k/Kconfig Thu Feb 19 23:44:26 2004 @@ -1030,8 +1030,7 @@ precision in some cases. To compile this driver as a module, choose M here: the - module will be called genrtc. To load the module automatically - add 'alias char-major-10-135 genrtc' to your /etc/modules.conf + module will be called genrtc. config GEN_RTC_X bool "Extended RTC operation" diff -Nru a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c --- a/arch/m68k/kernel/time.c Thu Feb 19 23:44:23 2004 +++ b/arch/m68k/kernel/time.c Thu Feb 19 23:44:23 2004 @@ -174,6 +174,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } diff -Nru a/arch/m68knommu/kernel/time.c b/arch/m68knommu/kernel/time.c --- a/arch/m68knommu/kernel/time.c Thu Feb 19 23:44:26 2004 +++ b/arch/m68knommu/kernel/time.c Thu Feb 19 23:44:26 2004 @@ -199,6 +199,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } diff -Nru a/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S b/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S --- a/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S Thu Feb 19 23:44:27 2004 +++ b/arch/m68knommu/platform/5407/MOTOROLA/crt0_ram.S Thu Feb 19 23:44:27 2004 @@ -99,10 +99,12 @@ movec %d0, %ACR3 /* Enable cache */ - move.l #0xa4098400, %d0 /* Write buffer, dflt precise */ + move.l #0xb6088400, %d0 /* Enable caches */ movec %d0,%CACR nop + +#ifdef CONFIG_ROMFS_FS /* * Move ROM filesystem above bss :-) */ @@ -123,6 +125,12 @@ move.l %d0, -(%a1) cmp.l %a0, %a2 /* Check if at end */ bne _copy_romfs + +#else /* CONFIG_ROMFS_FS */ + lea.l _ebss, %a1 + move.l %a1, _ramstart +#endif /* CONFIG_ROMFS_FS */ + /* * Zero out the bss region. diff -Nru a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c --- a/arch/mips/kernel/irq.c Thu Feb 19 23:44:23 2004 +++ b/arch/mips/kernel/irq.c Thu Feb 19 23:44:23 2004 @@ -835,7 +835,7 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, irq_affinity[(long)data]); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -873,7 +873,7 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, *(cpumask_t *)data); + int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/mips/kernel/sysirix.c b/arch/mips/kernel/sysirix.c --- a/arch/mips/kernel/sysirix.c Thu Feb 19 23:44:28 2004 +++ b/arch/mips/kernel/sysirix.c Thu Feb 19 23:44:28 2004 @@ -368,7 +368,7 @@ retval = HZ; goto out; case 4: - retval = NGROUPS; + retval = NGROUPS_MAX; goto out; case 5: retval = NR_OPEN; diff -Nru a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c --- a/arch/mips/kernel/time.c Thu Feb 19 23:44:24 2004 +++ b/arch/mips/kernel/time.c Thu Feb 19 23:44:24 2004 @@ -132,7 +132,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); - + clock_was_set(); return 0; } diff -Nru a/arch/parisc/kernel/time.c b/arch/parisc/kernel/time.c --- a/arch/parisc/kernel/time.c Thu Feb 19 23:44:24 2004 +++ b/arch/parisc/kernel/time.c Thu Feb 19 23:44:24 2004 @@ -230,6 +230,7 @@ time_esterror = NTP_PHASE_LIMIT; } write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } EXPORT_SYMBOL(do_settimeofday); diff -Nru a/arch/ppc/8260_io/enet.c b/arch/ppc/8260_io/enet.c --- a/arch/ppc/8260_io/enet.c Thu Feb 19 23:44:22 2004 +++ b/arch/ppc/8260_io/enet.c Thu Feb 19 23:44:22 2004 @@ -851,7 +851,7 @@ err = register_netdev(dev); if (err) { - kfree(dev); + free_netdev(dev); return err; } diff -Nru a/arch/ppc/8260_io/fcc_enet.c b/arch/ppc/8260_io/fcc_enet.c --- a/arch/ppc/8260_io/fcc_enet.c Thu Feb 19 23:44:25 2004 +++ b/arch/ppc/8260_io/fcc_enet.c Thu Feb 19 23:44:25 2004 @@ -1371,7 +1371,7 @@ err = register_netdev(dev); if (err) { - kfree(dev); + free_netdev(dev); return err; } diff -Nru a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c --- a/arch/ppc/8xx_io/enet.c Thu Feb 19 23:44:24 2004 +++ b/arch/ppc/8xx_io/enet.c Thu Feb 19 23:44:24 2004 @@ -949,7 +949,7 @@ err = register_netdev(dev); if (err) { - kfree(dev); + free_netdev(dev); return err; } diff -Nru a/arch/ppc/8xx_io/fec.c b/arch/ppc/8xx_io/fec.c --- a/arch/ppc/8xx_io/fec.c Thu Feb 19 23:44:28 2004 +++ b/arch/ppc/8xx_io/fec.c Thu Feb 19 23:44:28 2004 @@ -1748,7 +1748,7 @@ err = register_netdev(dev); if (err) { - kfree(dev); + free_netdev(dev); return err; } diff -Nru a/arch/ppc/kernel/irq.c b/arch/ppc/kernel/irq.c --- a/arch/ppc/kernel/irq.c Thu Feb 19 23:44:27 2004 +++ b/arch/ppc/kernel/irq.c Thu Feb 19 23:44:27 2004 @@ -575,7 +575,7 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, irq_affinity[(long)data]); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -616,7 +616,7 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, *(cpumask_t *)data); + int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c --- a/arch/ppc/kernel/setup.c Thu Feb 19 23:44:28 2004 +++ b/arch/ppc/kernel/setup.c Thu Feb 19 23:44:28 2004 @@ -53,7 +53,7 @@ extern void power4_idle(void); extern boot_infos_t *boot_infos; -char saved_command_line[256]; +char saved_command_line[COMMAND_LINE_SIZE]; unsigned char aux_device_present; struct ide_machdep_calls ppc_ide_md; char *sysmap; @@ -501,7 +501,7 @@ ulong *data = rec->data; switch (rec->tag) { case BI_CMD_LINE: - memcpy(cmd_line, (void *)data, rec->size); + strlcpy(cmd_line, (void *)data, sizeof(cmd_line)); break; case BI_SYSMAP: sysmap = (char *)((data[0] >= (KERNELBASE)) ? data[0] : @@ -538,7 +538,7 @@ unsigned long r6, unsigned long r7) { #ifdef CONFIG_CMDLINE - strcpy(cmd_line, CONFIG_CMDLINE); + strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line)); #endif /* CONFIG_CMDLINE */ #ifdef CONFIG_6xx @@ -676,7 +676,7 @@ init_mm.brk = (unsigned long) klimit; /* Save unparsed command line copy for /proc/cmdline */ - strcpy(saved_command_line, cmd_line); + strlcpy(saved_command_line, cmd_line, sizeof(saved_command_line)); *cmdline_p = cmd_line; /* set up the bootmem stuff with available memory */ diff -Nru a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c --- a/arch/ppc/kernel/time.c Thu Feb 19 23:44:27 2004 +++ b/arch/ppc/kernel/time.c Thu Feb 19 23:44:27 2004 @@ -294,6 +294,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irqrestore(&xtime_lock, flags); + clock_was_set(); return 0; } diff -Nru a/arch/ppc64/kernel/iSeries_irq.c b/arch/ppc64/kernel/iSeries_irq.c --- a/arch/ppc64/kernel/iSeries_irq.c Thu Feb 19 23:44:27 2004 +++ b/arch/ppc64/kernel/iSeries_irq.c Thu Feb 19 23:44:27 2004 @@ -57,6 +57,7 @@ void iSeries_init_irq_desc(irq_desc_t *desc) { + desc->handler = &iSeries_IRQ_handler; } /* This is called by init_IRQ. set in ppc_md.init_IRQ by iSeries_setup.c */ @@ -87,22 +88,6 @@ #define IRQ_TO_IDSEL(irq) (((((irq) - 1) >> 3) & 7) + 1) #define IRQ_TO_FUNC(irq) (((irq) - 1) & 7) -/* - * This is called out of iSeries_scan_slot to assign the EADS slot - * to its IRQ number - */ -int __init iSeries_assign_IRQ(int irq, HvBusNumber busNumber, - HvSubBusNumber subBusNumber, HvAgentId deviceId) -{ - irq_desc_t *desc = get_real_irq_desc(irq); - - if (desc == NULL) - return -1; - desc->handler = &iSeries_IRQ_handler; - return 0; -} - - /* This is called by iSeries_activate_IRQs */ static unsigned int iSeries_startup_IRQ(unsigned int irq) { @@ -123,6 +108,11 @@ bus, subBus, deviceId, irq); return 0; } + +/* + * Temporary hack + */ +#define get_irq_desc(irq) &irq_desc[(irq)] /* * This is called out of iSeries_fixup to activate interrupt diff -Nru a/arch/ppc64/kernel/iSeries_pci.c b/arch/ppc64/kernel/iSeries_pci.c --- a/arch/ppc64/kernel/iSeries_pci.c Thu Feb 19 23:44:28 2004 +++ b/arch/ppc64/kernel/iSeries_pci.c Thu Feb 19 23:44:28 2004 @@ -406,7 +406,6 @@ /* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */ Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel); - iSeries_assign_IRQ(Irq, Bus, 0, EADsIdSel); PPCDBG(PPCDBG_BUSWALK, "PCI:- allocate and assign IRQ 0x%02X.%02X.%02X = 0x%02X\n", Bus, 0, EADsIdSel, Irq); diff -Nru a/arch/ppc64/kernel/iSeries_setup.c b/arch/ppc64/kernel/iSeries_setup.c --- a/arch/ppc64/kernel/iSeries_setup.c Thu Feb 19 23:44:27 2004 +++ b/arch/ppc64/kernel/iSeries_setup.c Thu Feb 19 23:44:27 2004 @@ -315,7 +315,6 @@ ppc_md.setup_residual = iSeries_setup_residual; ppc_md.get_cpuinfo = iSeries_get_cpuinfo; ppc_md.init_IRQ = iSeries_init_IRQ; - ppc_md.init_irq_desc = iSeries_init_irq_desc; ppc_md.get_irq = iSeries_get_irq; ppc_md.init = NULL; diff -Nru a/arch/ppc64/kernel/irq.c b/arch/ppc64/kernel/irq.c --- a/arch/ppc64/kernel/irq.c Thu Feb 19 23:44:24 2004 +++ b/arch/ppc64/kernel/irq.c Thu Feb 19 23:44:24 2004 @@ -664,7 +664,7 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, irq_affinity[(long)data]); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -702,7 +702,7 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, *(cpumask_t *)data); + int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/ppc64/kernel/lparcfg.c b/arch/ppc64/kernel/lparcfg.c --- a/arch/ppc64/kernel/lparcfg.c Thu Feb 19 23:44:23 2004 +++ b/arch/ppc64/kernel/lparcfg.c Thu Feb 19 23:44:23 2004 @@ -134,7 +134,7 @@ memset(buf, 0, size); shared = (int)(lpaca->xLpPacaPtr->xSharedProc); - n += snprintf(buf, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf, LPARCFG_BUFF_SIZE - n, "serial_number=%c%c%c%c%c%c%c\n", e2a(xItExtVpdPanel.mfgID[2]), e2a(xItExtVpdPanel.mfgID[3]), @@ -144,7 +144,7 @@ e2a(xItExtVpdPanel.systemSerial[4]), e2a(xItExtVpdPanel.systemSerial[5])); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_type=%c%c%c%c\n", e2a(xItExtVpdPanel.machineType[0]), e2a(xItExtVpdPanel.machineType[1]), @@ -152,23 +152,23 @@ e2a(xItExtVpdPanel.machineType[3])); lp_index = HvLpConfig_getLpIndex(); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_id=%d\n", (int)lp_index); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_active_processors=%d\n", (int)HvLpConfig_getSystemPhysicalProcessors()); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_potential_processors=%d\n", (int)HvLpConfig_getSystemPhysicalProcessors()); processors = (int)HvLpConfig_getPhysicalProcessors(); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_active_processors=%d\n", processors); max_processors = (int)HvLpConfig_getMaxPhysicalProcessors(); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_potential_processors=%d\n", max_processors); if(shared) { @@ -178,22 +178,22 @@ entitled_capacity = processors * 100; max_entitled_capacity = max_processors * 100; } - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_entitled_capacity=%d\n", entitled_capacity); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_max_entitled_capacity=%d\n", max_entitled_capacity); if(shared) { pool_id = HvLpConfig_getSharedPoolIndex(); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, "pool=%d\n", + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "pool=%d\n", (int)pool_id); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "pool_capacity=%d\n", (int)(HvLpConfig_getNumProcsInSharedPool(pool_id)*100)); } - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "shared_processor_mode=%d\n", shared); return 0; @@ -297,13 +297,13 @@ if(lp_index_ptr) lp_index = *lp_index_ptr; } - n = snprintf(buf, LPARCFG_BUFF_SIZE - n, + n = scnprintf(buf, LPARCFG_BUFF_SIZE - n, "serial_number=%s\n", system_id); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_type=%s\n", model); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_id=%d\n", (int)lp_index); rtas_node = find_path_device("/rtas"); @@ -317,74 +317,74 @@ if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { h_get_ppp(&h_entitled,&h_unallocated,&h_aggregation,&h_resource); #ifdef DEBUG - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "R4=0x%lx\n", h_entitled); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "R5=0x%lx\n", h_unallocated); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "R6=0x%lx\n", h_aggregation); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "R7=0x%lx\n", h_resource); #endif /* DEBUG */ } if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { system_potential_processors = get_splpar_potential_characteristics(); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_active_processors=%ld\n", (h_resource >> 2*8) & 0xffff); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_potential_processors=%d\n", system_potential_processors); } else { system_potential_processors = system_active_processors; - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_active_processors=%d\n", system_active_processors); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "system_potential_processors=%d\n", system_potential_processors); } processors = systemcfg->processorCount; - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_active_processors=%d\n", processors); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_potential_processors=%d\n", system_active_processors); /* max_entitled_capacity will come out of get_splpar_potential_characteristics() when that function is complete */ max_entitled_capacity = system_active_processors * 100; if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_entitled_capacity=%ld\n", h_entitled); } else { - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_entitled_capacity=%d\n", system_active_processors*100); } - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "partition_max_entitled_capacity=%d\n", max_entitled_capacity); shared = 0; - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "shared_processor_mode=%d\n", shared); if (cur_cpu_spec->firmware_features & FW_FEATURE_SPLPAR) { - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "pool=%ld\n", (h_aggregation >> 0*8)&0xffff); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "pool_capacity=%ld\n", (h_resource >> 3*8) &0xffff); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "group=%ld\n", (h_aggregation >> 2*8)&0xffff); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "capped=%ld\n", (h_resource >> 6*8)&0x40); - n += snprintf(buf+n, LPARCFG_BUFF_SIZE - n, + n += scnprintf(buf+n, LPARCFG_BUFF_SIZE - n, "capacity_weight=%d\n", (int)(h_resource>>5*8)&0xFF); } return 0; diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c --- a/arch/ppc64/kernel/prom.c Thu Feb 19 23:44:27 2004 +++ b/arch/ppc64/kernel/prom.c Thu Feb 19 23:44:27 2004 @@ -186,12 +186,13 @@ extern char cmd_line[512]; /* XXX */ unsigned long dev_tree_size; +unsigned long _get_PIR(void); #ifdef CONFIG_HMT struct { unsigned int pir; unsigned int threadid; -} hmt_thread_data[NR_CPUS] = {0}; +} hmt_thread_data[NR_CPUS]; #endif /* CONFIG_HMT */ char testString[] = "LINUX\n"; diff -Nru a/arch/ppc64/kernel/rtas-proc.c b/arch/ppc64/kernel/rtas-proc.c --- a/arch/ppc64/kernel/rtas-proc.c Thu Feb 19 23:44:25 2004 +++ b/arch/ppc64/kernel/rtas-proc.c Thu Feb 19 23:44:25 2004 @@ -287,9 +287,9 @@ char stkbuf[40]; /* its small, its on stack */ int n, sn; if (power_on_time == 0) - n = snprintf(stkbuf, 40, "Power on time not set\n"); + n = scnprintf(stkbuf,sizeof(stkbuf),"Power on time not set\n"); else - n = snprintf(stkbuf, 40, "%lu\n", power_on_time); + n = scnprintf(stkbuf,sizeof(stkbuf),"%lu\n",power_on_time); sn = strlen (stkbuf) +1; if (*ppos >= sn) @@ -410,9 +410,10 @@ if (error != 0){ printk(KERN_WARNING "error: reading the clock returned: %s\n", ppc_rtas_process_error(error)); - n = snprintf (stkbuf, 40, "0"); + n = scnprintf (stkbuf, sizeof(stkbuf), "0"); } else { - n = snprintf (stkbuf, 40, "%lu\n", mktime(year, mon, day, hour, min, sec)); + n = scnprintf (stkbuf, sizeof(stkbuf), "%lu\n", + mktime(year, mon, day, hour, min, sec)); } kfree(ret); @@ -819,7 +820,7 @@ n += check_location_string(ret, buffer + n); n += sprintf ( buffer+n, " "); /* see how many characters we have printed */ - snprintf ( t, 50, "%s ", ret); + scnprintf(t, sizeof(t), "%s ", ret); pos += strlen(t); if (pos >= llen) pos=0; @@ -863,7 +864,7 @@ int n, sn; char stkbuf[40]; /* its small, its on stack */ - n = snprintf(stkbuf, 40, "%lu\n", rtas_tone_frequency); + n = scnprintf(stkbuf, 40, "%lu\n", rtas_tone_frequency); sn = strlen (stkbuf) +1; if (*ppos >= sn) @@ -917,7 +918,7 @@ int n, sn; char stkbuf[40]; /* its small, its on stack */ - n = snprintf(stkbuf, 40, "%lu\n", rtas_tone_volume); + n = scnprintf(stkbuf, 40, "%lu\n", rtas_tone_volume); sn = strlen (stkbuf) +1; if (*ppos >= sn) diff -Nru a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c --- a/arch/ppc64/kernel/setup.c Thu Feb 19 23:44:25 2004 +++ b/arch/ppc64/kernel/setup.c Thu Feb 19 23:44:25 2004 @@ -80,7 +80,7 @@ int powersave_nap; -char saved_command_line[256]; +char saved_command_line[COMMAND_LINE_SIZE]; unsigned char aux_device_present; void parse_cmd_line(unsigned long r3, unsigned long r4, unsigned long r5, @@ -536,7 +536,7 @@ for ( ; rec->tag != BI_LAST ; rec = bi_rec_next(rec) ) { switch (rec->tag) { case BI_CMD_LINE: - memcpy(cmd_line, (void *)rec->data, rec->size); + strlcpy(cmd_line, (void *)rec->data, sizeof(cmd_line)); break; case BI_SYSMAP: sysmap = __va(rec->data[0]); @@ -620,7 +620,7 @@ init_mm.brk = klimit; /* Save unparsed command line copy for /proc/cmdline */ - strcpy(saved_command_line, cmd_line); + strlcpy(saved_command_line, cmd_line, sizeof(saved_command_line)); *cmdline_p = cmd_line; /* set up the bootmem stuff with available memory */ diff -Nru a/arch/ppc64/kernel/time.c b/arch/ppc64/kernel/time.c --- a/arch/ppc64/kernel/time.c Thu Feb 19 23:44:28 2004 +++ b/arch/ppc64/kernel/time.c Thu Feb 19 23:44:28 2004 @@ -418,6 +418,7 @@ } write_sequnlock_irqrestore(&xtime_lock, flags); + clock_was_set(); return 0; } diff -Nru a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c --- a/arch/s390/kernel/compat_linux.c Thu Feb 19 23:44:27 2004 +++ b/arch/s390/kernel/compat_linux.c Thu Feb 19 23:44:27 2004 @@ -190,40 +190,81 @@ return sys_setfsgid((gid_t)gid); } +static int groups16_to_user(u16 *grouplist, struct group_info *group_info) +{ + int i; + u16 group; + + for (i = 0; i < group_info->ngroups; i++) { + group = (u16)GROUP_AT(group_info, i); + if (put_user(group, grouplist+i)) + return -EFAULT; + } + + return 0; +} + +static int groups16_from_user(struct group_info *group_info, u16 *grouplist) +{ + int i; + u16 group; + + for (i = 0; i < group_info->ngroups; i++) { + if (get_user(group, grouplist+i)) + return -EFAULT; + GROUP_AT(group_info, i) = (gid_t)group; + } + + return 0; +} + asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist) { - u16 groups[NGROUPS]; - int i,j; + int i; if (gidsetsize < 0) return -EINVAL; - i = current->ngroups; + + get_group_info(current->group_info); + i = current->group_info->ngroups; if (gidsetsize) { - if (i > gidsetsize) - return -EINVAL; - for(j=0;jgroups[j]; - if (copy_to_user(grouplist, groups, sizeof(u16)*i)) - return -EFAULT; + if (i > gidsetsize) { + i = -EINVAL; + goto out; + } + if (groups16_to_user(grouplist, current->group_info)) { + i = -EFAULT; + goto out; + } } +out: + put_group_info(current->group_info); return i; } asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist) { - u16 groups[NGROUPS]; - int i; + struct group_info *group_info; + int retval; if (!capable(CAP_SETGID)) return -EPERM; - if ((unsigned) gidsetsize > NGROUPS) + if ((unsigned)gidsetsize > NGROUPS_MAX) return -EINVAL; - if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16))) - return -EFAULT; - for (i = 0 ; i < gidsetsize ; i++) - current->groups[i] = (gid_t)groups[i]; - current->ngroups = gidsetsize; - return 0; + + group_info = groups_alloc(gidsetsize); + if (!group_info) + return -ENOMEM; + retval = groups16_from_user(group_info, grouplist); + if (retval) { + put_group_info(group_info); + return retval; + } + + retval = set_current_groups(group_info); + put_group_info(group_info); + + return retval; } asmlinkage long sys32_getuid16(void) diff -Nru a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c --- a/arch/s390/kernel/time.c Thu Feb 19 23:44:22 2004 +++ b/arch/s390/kernel/time.c Thu Feb 19 23:44:22 2004 @@ -142,6 +142,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } diff -Nru a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c --- a/arch/sparc/kernel/time.c Thu Feb 19 23:44:25 2004 +++ b/arch/sparc/kernel/time.c Thu Feb 19 23:44:25 2004 @@ -535,6 +535,7 @@ write_seqlock_irq(&xtime_lock); ret = bus_do_settimeofday(tv); write_sequnlock_irq(&xtime_lock); + clock_was_set(); return ret; } diff -Nru a/arch/sparc/prom/printf.c b/arch/sparc/prom/printf.c --- a/arch/sparc/prom/printf.c Thu Feb 19 23:44:23 2004 +++ b/arch/sparc/prom/printf.c Thu Feb 19 23:44:23 2004 @@ -39,7 +39,7 @@ int i; va_start(args, fmt); - i = vsnprintf(ppbuf, sizeof(ppbuf), fmt, args); + i = vscnprintf(ppbuf, sizeof(ppbuf), fmt, args); va_end(args); prom_write(ppbuf, i); diff -Nru a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c --- a/arch/sparc64/kernel/irq.c Thu Feb 19 23:44:28 2004 +++ b/arch/sparc64/kernel/irq.c Thu Feb 19 23:44:28 2004 @@ -1211,7 +1211,7 @@ if (cpus_empty(mask)) mask = cpu_online_map; - len = cpumask_snprintf(page, count, mask); + len = cpumask_scnprintf(page, count, mask); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c --- a/arch/sparc64/kernel/sys_sparc32.c Thu Feb 19 23:44:26 2004 +++ b/arch/sparc64/kernel/sys_sparc32.c Thu Feb 19 23:44:26 2004 @@ -179,40 +179,81 @@ return sys_setfsgid((gid_t)gid); } +static int groups16_to_user(u16 *grouplist, struct group_info *group_info) +{ + int i; + u16 group; + + for (i = 0; i < group_info->ngroups; i++) { + group = (u16)GROUP_AT(group_info, i); + if (put_user(group, grouplist+i)) + return -EFAULT; + } + + return 0; +} + +static int groups16_from_user(struct group_info *group_info, u16 *grouplist) +{ + int i; + u16 group; + + for (i = 0; i < group_info->ngroups; i++) { + if (get_user(group, grouplist+i)) + return -EFAULT; + GROUP_AT(group_info, i) = (gid_t)group; + } + + return 0; +} + asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist) { - u16 groups[NGROUPS]; - int i,j; + int i; if (gidsetsize < 0) return -EINVAL; - i = current->ngroups; + + get_group_info(current->group_info); + i = current->group_info->ngroups; if (gidsetsize) { - if (i > gidsetsize) - return -EINVAL; - for(j=0;jgroups[j]; - if (copy_to_user(grouplist, groups, sizeof(u16)*i)) - return -EFAULT; + if (i > gidsetsize) { + i = -EINVAL; + goto out; + } + if (groups16_to_user(grouplist, current->group_info)) { + i = -EFAULT; + goto out; + } } +out: + put_group_info(current->group_info); return i; } asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist) { - u16 groups[NGROUPS]; - int i; + struct group_info *group_info; + int retval; if (!capable(CAP_SETGID)) return -EPERM; - if ((unsigned) gidsetsize > NGROUPS) + if ((unsigned)gidsetsize > NGROUPS_MAX) return -EINVAL; - if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16))) - return -EFAULT; - for (i = 0 ; i < gidsetsize ; i++) - current->groups[i] = (gid_t)groups[i]; - current->ngroups = gidsetsize; - return 0; + + group_info = groups_alloc(gidsetsize); + if (!group_info) + return -ENOMEM; + retval = groups16_from_user(group_info, grouplist); + if (retval) { + put_group_info(group_info); + return retval; + } + + retval = set_current_groups(group_info); + put_group_info(group_info); + + return retval; } asmlinkage long sys32_getuid16(void) diff -Nru a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c --- a/arch/sparc64/kernel/time.c Thu Feb 19 23:44:25 2004 +++ b/arch/sparc64/kernel/time.c Thu Feb 19 23:44:25 2004 @@ -1126,6 +1126,7 @@ time_maxerror = NTP_PHASE_LIMIT; time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq(&xtime_lock); + clock_was_set(); return 0; } diff -Nru a/arch/sparc64/prom/printf.c b/arch/sparc64/prom/printf.c --- a/arch/sparc64/prom/printf.c Thu Feb 19 23:44:25 2004 +++ b/arch/sparc64/prom/printf.c Thu Feb 19 23:44:25 2004 @@ -40,7 +40,7 @@ int i; va_start(args, fmt); - i = vsnprintf(ppbuf, sizeof(ppbuf), fmt, args); + i = vscnprintf(ppbuf, sizeof(ppbuf), fmt, args); va_end(args); prom_write(ppbuf, i); diff -Nru a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c --- a/arch/um/drivers/net_kern.c Thu Feb 19 23:44:25 2004 +++ b/arch/um/drivers/net_kern.c Thu Feb 19 23:44:25 2004 @@ -358,8 +358,12 @@ rtnl_lock(); err = register_netdevice(dev); rtnl_unlock(); - if (err) + if (err) { + device->dev = NULL; + /* XXX: should we call ->remove() here? */ + free_netdev(dev); return 1; + } lp = dev->priv; INIT_LIST_HEAD(&lp->list); diff -Nru a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c --- a/arch/um/kernel/irq.c Thu Feb 19 23:44:27 2004 +++ b/arch/um/kernel/irq.c Thu Feb 19 23:44:27 2004 @@ -575,7 +575,7 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, irq_affinity[(long)data]); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -613,7 +613,7 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, *(cpumask_t *)data); + int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/um/kernel/time.c b/arch/um/kernel/time.c --- a/arch/um/kernel/time.c Thu Feb 19 23:44:23 2004 +++ b/arch/um/kernel/time.c Thu Feb 19 23:44:23 2004 @@ -93,6 +93,7 @@ gettimeofday(tv, NULL); timeradd(tv, &local_offset, tv); time_unlock(flags); + clock_was_set(); } EXPORT_SYMBOL(do_gettimeofday); diff -Nru a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c --- a/arch/v850/kernel/ptrace.c Thu Feb 19 23:44:25 2004 +++ b/arch/v850/kernel/ptrace.c Thu Feb 19 23:44:25 2004 @@ -141,7 +141,7 @@ rval = -EPERM; if (pid == 1) /* you may not mess with init */ - goto out; + goto out_tsk; if (request == PTRACE_ATTACH) { rval = ptrace_attach(child); diff -Nru a/arch/v850/kernel/time.c b/arch/v850/kernel/time.c --- a/arch/v850/kernel/time.c Thu Feb 19 23:44:26 2004 +++ b/arch/v850/kernel/time.c Thu Feb 19 23:44:26 2004 @@ -193,6 +193,7 @@ time_esterror = NTP_PHASE_LIMIT; write_sequnlock_irq (&xtime_lock); + clock_was_set(); return 0; } diff -Nru a/arch/x86_64/Kconfig b/arch/x86_64/Kconfig --- a/arch/x86_64/Kconfig Thu Feb 19 23:44:27 2004 +++ b/arch/x86_64/Kconfig Thu Feb 19 23:44:27 2004 @@ -48,12 +48,14 @@ bool default y help - Write kernel log output directly into the VGA buffer. This is useful - for kernel debugging when your machine crashes very early before - the console code is initialized. For normal operation it is not - recommended because it looks ugly and doesn't cooperate with - klogd/syslogd or the X server. You should normally N here, unless - you want to debug such a crash. + Write kernel log output directly into the VGA buffer or to a serial + port. + + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. For normal operation + it is not recommended because it looks ugly and doesn't cooperate + with klogd/syslogd or the X server. You should normally N here, + unless you want to debug such a crash. config HPET_TIMER bool @@ -89,6 +91,9 @@ help Optimize for AMD Opteron/Athlon64/Hammer/K8 CPUs. +config MPSC + bool "Prescott/Nocona" + config GENERIC_CPU bool "Generic-x86-64" help @@ -101,11 +106,13 @@ # config X86_L1_CACHE_BYTES int - default "64" + default "128" if GENERIC_CPU || MPSC + default "64" if MK8 config X86_L1_CACHE_SHIFT int - default "6" + default "7" if GENERIC_CPU || MPSC + default "6" if MK8 config X86_TSC bool @@ -115,6 +122,23 @@ bool default y +config MICROCODE + tristate "/dev/cpu/microcode - Intel CPU microcode support" + ---help--- + If you say Y here the 'File systems' section, you will be + able to update the microcode on Intel processors. You will + obviously need the actual microcode binary data itself which is + not shipped with the Linux kernel. + + For latest news and information on obtaining all the required + ingredients for this driver, check: + . + + To compile this driver as a module, choose M here: the + module will be called microcode. + If you use modprobe or kmod you may also want to add the line + 'alias char-major-10-184 microcode' to your /etc/modules.conf file. + config X86_MSR tristate "/dev/cpu/*/msr - Model-specific register support" help @@ -132,6 +156,11 @@ with major 203 and minors 0 to 31 for /dev/cpu/0/cpuid to /dev/cpu/31/cpuid. +config X86_HT + bool + depends on SMP + default y + config MATH_EMULATION bool @@ -256,9 +285,13 @@ Normally the kernel will take the right choice by itself. If unsure say Y +config SWIOTLB + select GART_IOMMU + bool "Software IOTLB support" + config DUMMY_IOMMU bool - depends on !GART_IOMMU + depends on !GART_IOMMU && !SWIOTLB default y help Don't use IOMMU code. This will cause problems when you have more than 4GB diff -Nru a/arch/x86_64/Makefile b/arch/x86_64/Makefile --- a/arch/x86_64/Makefile Thu Feb 19 23:44:27 2004 +++ b/arch/x86_64/Makefile Thu Feb 19 23:44:27 2004 @@ -39,6 +39,10 @@ check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1 ; then echo "$(1)"; else echo "$(2)"; fi) +cflags-$(CONFIG_MK8) += $(call check_gcc,-march=k8,) +cflags-$(CONFIG_MPSC) += $(call check_gcc,-march=pentium4,) +CFLAGS += $(cflags-y) + CFLAGS += -mno-red-zone CFLAGS += -mcmodel=kernel CFLAGS += -pipe @@ -52,7 +56,10 @@ ifneq ($(CONFIG_DEBUG_INFO),y) CFLAGS += -fno-asynchronous-unwind-tables endif -#CFLAGS += $(call check_gcc,-funit-at-a-time,) + +# Enable unit-at-a-time mode when possible. It shrinks the +# kernel considerably. +CFLAGS += $(call check_gcc,-funit-at-a-time,) head-y := arch/x86_64/kernel/head.o arch/x86_64/kernel/head64.o arch/x86_64/kernel/init_task.o diff -Nru a/arch/x86_64/boot/setup.S b/arch/x86_64/boot/setup.S --- a/arch/x86_64/boot/setup.S Thu Feb 19 23:44:28 2004 +++ b/arch/x86_64/boot/setup.S Thu Feb 19 23:44:28 2004 @@ -292,8 +292,9 @@ /* minimum CPUID flags for x86-64 */ /* see http://www.x86-64.org/lists/discuss/msg02971.html */ #define SSE_MASK ((1<<25)|(1<<26)) -#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|(1<<11)| \ - (1<<13)|(1<<15)|(1<<24)|(1<<29)) +#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|\ + (1<<13)|(1<<15)|(1<<24)) +#define REQUIRED_MASK2 (1<<29) pushfl /* standard way to check for cpuid */ popl %eax @@ -305,10 +306,10 @@ popl %eax cmpl %eax,%ebx jz no_longmode /* cpu has no cpuid */ - movl $0x80000000,%eax + movl $0x0,%eax cpuid - cmpl $0x80000001,%eax - jb no_longmode /* no extended cpuid */ + cmpl $0x1,%eax + jb no_longmode /* no cpuid 1 */ xor %di,%di cmpl $0x68747541,%ebx /* AuthenticAMD */ jnz noamd @@ -318,11 +319,20 @@ jnz noamd mov $1,%di /* cpu is from AMD */ noamd: - movl $0x80000001,%eax + movl $0x1,%eax cpuid andl $REQUIRED_MASK1,%edx xorl $REQUIRED_MASK1,%edx jnz no_longmode + movl $0x80000000,%eax + cpuid + cmpl $0x80000001,%eax + jb no_longmode /* no extended cpuid */ + movl $0x80000001,%eax + cpuid + andl $REQUIRED_MASK2,%edx + xorl $REQUIRED_MASK2,%edx + jnz no_longmode sse_test: movl $1,%eax cpuid diff -Nru a/arch/x86_64/kernel/Makefile b/arch/x86_64/kernel/Makefile --- a/arch/x86_64/kernel/Makefile Thu Feb 19 23:44:27 2004 +++ b/arch/x86_64/kernel/Makefile Thu Feb 19 23:44:27 2004 @@ -12,6 +12,7 @@ obj-$(CONFIG_MTRR) += ../../i386/kernel/cpu/mtrr/ obj-$(CONFIG_ACPI) += acpi/ obj-$(CONFIG_X86_MSR) += msr.o +obj-$(CONFIG_MICROCODE) += microcode.o obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_SMP) += smp.o smpboot.o trampoline.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o @@ -22,6 +23,7 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-$(CONFIG_GART_IOMMU) += pci-gart.o aperture.o obj-$(CONFIG_DUMMY_IOMMU) += pci-nommu.o pci-dma.o +obj-$(CONFIG_SWIOTLB) += swiotlb.o obj-$(CONFIG_MODULES) += module.o @@ -30,4 +32,5 @@ bootflag-y += ../../i386/kernel/bootflag.o cpuid-$(subst m,y,$(CONFIG_X86_CPUID)) += ../../i386/kernel/cpuid.o topology-y += ../../i386/mach-default/topology.o - +swiotlb-$(CONFIG_SWIOTLB) += ../../ia64/lib/swiotlb.o +microcode-$(subst m,y,$(CONFIG_X86_CPUID)) += ../../i386/kernel/microcode.o diff -Nru a/arch/x86_64/kernel/aperture.c b/arch/x86_64/kernel/aperture.c --- a/arch/x86_64/kernel/aperture.c Thu Feb 19 23:44:27 2004 +++ b/arch/x86_64/kernel/aperture.c Thu Feb 19 23:44:27 2004 @@ -24,6 +24,8 @@ #include #include +int iommu_aperture; + int fallback_aper_order __initdata = 1; /* 64MB */ int fallback_aper_force __initdata = 0; @@ -205,6 +207,8 @@ char name[30]; if (read_pci_config(0, num, 3, 0x00) != NB_ID_3) continue; + + iommu_aperture = 1;; aper_order = (read_pci_config(0, num, 3, 0x90) >> 1) & 7; aper_size = (32 * 1024 * 1024) << aper_order; diff -Nru a/arch/x86_64/kernel/early_printk.c b/arch/x86_64/kernel/early_printk.c --- a/arch/x86_64/kernel/early_printk.c Thu Feb 19 23:44:26 2004 +++ b/arch/x86_64/kernel/early_printk.c Thu Feb 19 23:44:26 2004 @@ -7,7 +7,11 @@ /* Simple VGA output */ +#ifdef __i386__ +#define VGABASE __pa(__PAGE_OFFSET + 0xb8000UL) +#else #define VGABASE 0xffffffff800b8000UL +#endif #define MAX_YPOS 25 #define MAX_XPOS 80 @@ -22,15 +26,14 @@ while ((c = *str++) != '\0' && n-- > 0) { if (current_ypos >= MAX_YPOS) { /* scroll 1 line up */ - for(k = 1, j = 0; k < MAX_YPOS; k++, j++) { - for(i = 0; i < MAX_XPOS; i++) { + for (k = 1, j = 0; k < MAX_YPOS; k++, j++) { + for (i = 0; i < MAX_XPOS; i++) { writew(readw(VGABASE + 2*(MAX_XPOS*k + i)), VGABASE + 2*(MAX_XPOS*j + i)); } } - for(i = 0; i < MAX_XPOS; i++) { + for (i = 0; i < MAX_XPOS; i++) writew(0x720, VGABASE + 2*(MAX_XPOS*j + i)); - } current_ypos = MAX_YPOS-1; } if (c == '\n') { @@ -38,7 +41,8 @@ current_ypos++; } else if (c != '\r') { writew(((0x7 << 8) | (unsigned short) c), - VGABASE + 2*(MAX_XPOS*current_ypos + current_xpos++)); + VGABASE + 2*(MAX_XPOS*current_ypos + + current_xpos++)); if (current_xpos >= MAX_XPOS) { current_xpos = 0; current_ypos++; @@ -78,7 +82,7 @@ { unsigned timeout = 0xffff; while ((inb(early_serial_base + LSR) & XMTRDY) == 0 && --timeout) - rep_nop(); + cpu_relax(); outb(ch, early_serial_base + TXR); return timeout ? 0 : -1; } @@ -93,10 +97,13 @@ } } +#define DEFAULT_BAUD 9600 + static __init void early_serial_init(char *opt) { unsigned char c; - unsigned divisor, baud = 38400; + unsigned divisor; + unsigned baud = DEFAULT_BAUD; char *s, *e; if (*opt == ',') @@ -109,25 +116,26 @@ early_serial_base = simple_strtoul(s, &e, 16); } else { static int bases[] = { 0x3f8, 0x2f8 }; - if (!strncmp(s,"ttyS",4)) - s+=4; - port = simple_strtoul(s, &e, 10); - if (port > 1 || s == e) - port = 0; - early_serial_base = bases[port]; - } + + if (!strncmp(s,"ttyS",4)) + s += 4; + port = simple_strtoul(s, &e, 10); + if (port > 1 || s == e) + port = 0; + early_serial_base = bases[port]; + } } - outb(0x3, early_serial_base + LCR); /* 8n1 */ - outb(0, early_serial_base + IER); /* no interrupt */ - outb(0, early_serial_base + FCR); /* no fifo */ - outb(0x3, early_serial_base + MCR); /* DTR + RTS */ + outb(0x3, early_serial_base + LCR); /* 8n1 */ + outb(0, early_serial_base + IER); /* no interrupt */ + outb(0, early_serial_base + FCR); /* no fifo */ + outb(0x3, early_serial_base + MCR); /* DTR + RTS */ s = strsep(&opt, ","); if (s != NULL) { baud = simple_strtoul(s, &e, 0); if (baud == 0 || s == e) - baud = 38400; + baud = DEFAULT_BAUD; } divisor = 115200 / baud; @@ -154,8 +162,9 @@ char buf[512]; int n; va_list ap; + va_start(ap,fmt); - n = vsnprintf(buf,512,fmt,ap); + n = vscnprintf(buf,512,fmt,ap); early_console->write(early_console,buf,n); va_end(ap); } @@ -170,6 +179,8 @@ if (early_console_initialized) return -1; + opt = strchr(opt, '=') + 1; + strlcpy(buf,opt,sizeof(buf)); space = strchr(buf, ' '); if (space) @@ -200,19 +211,12 @@ if (!early_console_initialized || !early_console) return; if (!keep_early) { - printk("disabling early console...\n"); + printk("disabling early console\n"); unregister_console(early_console); early_console_initialized = 0; } else { - printk("keeping early console.\n"); + printk("keeping early console\n"); } } -/* syntax: earlyprintk=vga - earlyprintk=serial[,ttySn[,baudrate]] - Append ,keep to not disable it when the real console takes over. - Only vga or serial at a time, not both. - Currently only ttyS0 and ttyS1 are supported. - Interaction with the standard serial driver is not very good. - The VGA output is eventually overwritten by the real console. */ -__setup("earlyprintk=", setup_early_printk); +__setup("earlyprintk=", setup_early_printk); diff -Nru a/arch/x86_64/kernel/head.S b/arch/x86_64/kernel/head.S --- a/arch/x86_64/kernel/head.S Thu Feb 19 23:44:26 2004 +++ b/arch/x86_64/kernel/head.S Thu Feb 19 23:44:26 2004 @@ -16,6 +16,7 @@ #include #include #include +#include /* we are not able to switch in one step to the final KERNEL ADRESS SPACE * because we need identity-mapped pages on setup so define __START_KERNEL to @@ -322,7 +323,6 @@ .endr #endif -.align 64 /* cacheline aligned */ ENTRY(gdt_table32) .quad 0x0000000000000000 /* This one is magic */ .quad 0x0000000000000000 /* unused */ @@ -334,7 +334,7 @@ * Also sysret mandates a special GDT layout */ -.align 64 /* cacheline aligned, keep this synchronized with asm/desc.h */ +.align L1_CACHE_BYTES /* The TLS descriptors are currently at a different place compared to i386. Hopefully nobody expects them at a fixed place (Wine?) */ @@ -354,18 +354,13 @@ .quad 0 /* unused now */ .quad 0x00009a000000ffff /* __KERNEL16_CS - 16bit PM for S3 wakeup. */ /* base must be patched for real base address. */ - /* This should be a multiple of the cache line size */ gdt_end: - .globl gdt_end - - /* GDTs of other CPUs */ -#ifdef CONFIG_SMP - .rept NR_CPUS-1 - .quad 0,0,0,0,0,0,0,0,0,0,0 - .endr -#endif + /* asm/segment.h:GDT_ENTRIES must match this */ + /* This should be a multiple of the cache line size */ + /* GDTs of other CPUs: */ + .fill (L1_CACHE_BYTES * NR_CPUS) - (gdt_end - cpu_gdt_table) - .align 64 + .align L1_CACHE_BYTES ENTRY(idt_table) .rept 256 .quad 0 diff -Nru a/arch/x86_64/kernel/head64.c b/arch/x86_64/kernel/head64.c --- a/arch/x86_64/kernel/head64.c Thu Feb 19 23:44:24 2004 +++ b/arch/x86_64/kernel/head64.c Thu Feb 19 23:44:24 2004 @@ -83,9 +83,9 @@ /* default console: */ if (!strstr(saved_command_line, "console=")) strcat(saved_command_line, " console=tty0"); - s = strstr(saved_command_line, "earlyprintk="); + s = strstr(saved_command_line, "earlyprintk="); if (s != NULL) - setup_early_printk(s+12); + setup_early_printk(s); #ifdef CONFIG_DISCONTIGMEM s = strstr(saved_command_line, "numa="); if (s != NULL) diff -Nru a/arch/x86_64/kernel/irq.c b/arch/x86_64/kernel/irq.c --- a/arch/x86_64/kernel/irq.c Thu Feb 19 23:44:24 2004 +++ b/arch/x86_64/kernel/irq.c Thu Feb 19 23:44:24 2004 @@ -826,7 +826,7 @@ static int irq_affinity_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, irq_affinity[(long)data]); + int len = cpumask_scnprintf(page, count, irq_affinity[(long)data]); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); @@ -864,7 +864,7 @@ static int prof_cpu_mask_read_proc (char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = cpumask_snprintf(page, count, *(cpumask_t *)data); + int len = cpumask_scnprintf(page, count, *(cpumask_t *)data); if (count - len < 2) return -EINVAL; len += sprintf(page + len, "\n"); diff -Nru a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c --- a/arch/x86_64/kernel/nmi.c Thu Feb 19 23:44:25 2004 +++ b/arch/x86_64/kernel/nmi.c Thu Feb 19 23:44:25 2004 @@ -39,7 +39,7 @@ * be enabled * -1: the lapic NMI watchdog is disabled, but can be enabled */ -static int nmi_active; +int nmi_active; /* oprofile uses this */ static int panic_on_timeout; unsigned int nmi_watchdog = NMI_LOCAL_APIC; @@ -380,6 +380,7 @@ nmi_callback = dummy_nmi_callback; } +EXPORT_SYMBOL(nmi_active); EXPORT_SYMBOL(nmi_watchdog); EXPORT_SYMBOL(disable_lapic_nmi_watchdog); EXPORT_SYMBOL(enable_lapic_nmi_watchdog); diff -Nru a/arch/x86_64/kernel/pci-gart.c b/arch/x86_64/kernel/pci-gart.c --- a/arch/x86_64/kernel/pci-gart.c Thu Feb 19 23:44:24 2004 +++ b/arch/x86_64/kernel/pci-gart.c Thu Feb 19 23:44:24 2004 @@ -354,6 +354,11 @@ BUG_ON(dir == PCI_DMA_NONE); +#ifdef CONFIG_SWIOTLB + if (swiotlb) + return swiotlb_map_single(&dev->dev,addr,size,dir); +#endif + phys_mem = virt_to_phys(addr); if (!need_iommu(dev, phys_mem, size)) return phys_mem; @@ -460,6 +465,12 @@ BUG_ON(dir == PCI_DMA_NONE); if (nents == 0) return 0; + +#ifdef CONFIG_SWIOTLB + if (swiotlb) + return swiotlb_map_sg(&dev->dev,sg,nents,dir); +#endif + out = 0; start = 0; for (i = 0; i < nents; i++) { @@ -520,6 +531,14 @@ unsigned long iommu_page; int npages; int i; + +#ifdef CONFIG_SWIOTLB + if (swiotlb) { + swiotlb_unmap_single(&hwdev->dev,dma_addr,size,direction); + return; + } +#endif + if (dma_addr < iommu_bus_base + EMERGENCY_PAGES*PAGE_SIZE || dma_addr >= iommu_bus_base + iommu_size) return; @@ -570,7 +589,7 @@ return 0; } - if (no_iommu && (mask < (end_pfn << PAGE_SHIFT))) + if (no_iommu && (mask < (end_pfn << PAGE_SHIFT)) && !swiotlb) return 0; return 1; @@ -680,6 +699,7 @@ return 0; nommu: + /* Should not happen anymore */ printk(KERN_ERR "PCI-DMA: More than 4GB of RAM and no IOMMU\n" KERN_ERR "PCI-DMA: 32bit PCI IO may malfunction."); return -1; @@ -694,6 +714,7 @@ unsigned long iommu_start; struct pci_dev *dev; + #ifndef CONFIG_AGP_AMD64 no_agp = 1; #else @@ -704,7 +725,14 @@ (agp_copy_info(&info) < 0); #endif - if (no_iommu || (!force_iommu && end_pfn < 0xffffffff>>PAGE_SHIFT)) { + if (swiotlb) { + no_iommu = 1; + printk(KERN_INFO "PCI-DMA: Using SWIOTLB :-(\n"); + return -1; + } + + if (no_iommu || (!force_iommu && end_pfn < 0xffffffff>>PAGE_SHIFT) || + !iommu_aperture) { printk(KERN_INFO "PCI-DMA: Disabling IOMMU.\n"); no_iommu = 1; return -1; diff -Nru a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c --- a/arch/x86_64/kernel/process.c Thu Feb 19 23:44:25 2004 +++ b/arch/x86_64/kernel/process.c Thu Feb 19 23:44:25 2004 @@ -140,6 +140,52 @@ } } +/* + * This uses new MONITOR/MWAIT instructions on P4 processors with PNI, + * which can obviate IPI to trigger checking of need_resched. + * We execute MONITOR against need_resched and enter optimized wait state + * through MWAIT. Whenever someone changes need_resched, we would be woken + * up from MWAIT (without an IPI). + */ +static void mwait_idle(void) +{ + local_irq_enable(); + + if (!need_resched()) { + set_thread_flag(TIF_POLLING_NRFLAG); + do { + __monitor((void *)¤t_thread_info()->flags, 0, 0); + if (need_resched()) + break; + __mwait(0, 0); + } while (!need_resched()); + clear_thread_flag(TIF_POLLING_NRFLAG); + } +} + +void __init select_idle_routine(const struct cpuinfo_x86 *c) +{ + static int printed; + if (cpu_has(c, X86_FEATURE_MWAIT)) { + /* + * Skip, if setup has overridden idle. + * Also, take care of system with asymmetric CPUs. + * Use, mwait_idle only if all cpus support it. + * If not, we fallback to default_idle() + */ + if (!pm_idle) { + if (!printed) { + printk("using mwait in idle threads.\n"); + printed = 1; + } + pm_idle = mwait_idle; + } + return; + } + pm_idle = default_idle; + return; +} + static int __init idle_setup (char *str) { if (!strncmp(str, "poll", 4)) { diff -Nru a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c --- a/arch/x86_64/kernel/setup.c Thu Feb 19 23:44:22 2004 +++ b/arch/x86_64/kernel/setup.c Thu Feb 19 23:44:22 2004 @@ -76,6 +76,9 @@ unsigned long saved_video_mode; +int swiotlb; +EXPORT_SYMBOL(swiotlb); + /* * Setup options */ @@ -440,7 +443,6 @@ } } #endif - paging_init(); #ifndef CONFIG_SMP @@ -584,6 +586,193 @@ return r; } +static void __init detect_ht(void) +{ +#ifdef CONFIG_SMP + extern int phys_proc_id[NR_CPUS]; + + u32 eax, ebx, ecx, edx; + int index_lsb, index_msb, tmp; + int initial_apic_id; + int cpu = smp_processor_id(); + + cpuid(1, &eax, &ebx, &ecx, &edx); + smp_num_siblings = (ebx & 0xff0000) >> 16; + + if (smp_num_siblings == 1) { + printk(KERN_INFO "CPU: Hyper-Threading is disabled\n"); + } else if (smp_num_siblings > 1) { + index_lsb = 0; + index_msb = 31; + /* + * At this point we only support two siblings per + * processor package. + */ +#define NR_SIBLINGS 2 + if (smp_num_siblings != NR_SIBLINGS) { + printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); + smp_num_siblings = 1; + return; + } + tmp = smp_num_siblings; + while ((tmp & 1) == 0) { + tmp >>=1 ; + index_lsb++; + } + tmp = smp_num_siblings; + while ((tmp & 0x80000000 ) == 0) { + tmp <<=1 ; + index_msb--; + } + if (index_lsb != index_msb ) + index_msb++; + initial_apic_id = ebx >> 24 & 0xff; + phys_proc_id[cpu] = initial_apic_id >> index_msb; + + printk(KERN_INFO "CPU: Physical Processor ID: %d\n", + phys_proc_id[cpu]); + } +#endif +} + +#define LVL_1_INST 1 +#define LVL_1_DATA 2 +#define LVL_2 3 +#define LVL_3 4 +#define LVL_TRACE 5 + +struct _cache_table +{ + unsigned char descriptor; + char cache_type; + short size; +}; + +/* all the cache descriptor types we care about (no TLB or trace cache entries) */ +static struct _cache_table cache_table[] __initdata = +{ + { 0x06, LVL_1_INST, 8 }, + { 0x08, LVL_1_INST, 16 }, + { 0x0a, LVL_1_DATA, 8 }, + { 0x0c, LVL_1_DATA, 16 }, + { 0x22, LVL_3, 512 }, + { 0x23, LVL_3, 1024 }, + { 0x25, LVL_3, 2048 }, + { 0x29, LVL_3, 4096 }, + { 0x2c, LVL_1_DATA, 32 }, + { 0x30, LVL_1_INST, 32 }, + { 0x39, LVL_2, 128 }, + { 0x3b, LVL_2, 128 }, + { 0x3c, LVL_2, 256 }, + { 0x41, LVL_2, 128 }, + { 0x42, LVL_2, 256 }, + { 0x43, LVL_2, 512 }, + { 0x44, LVL_2, 1024 }, + { 0x45, LVL_2, 2048 }, + { 0x66, LVL_1_DATA, 8 }, + { 0x67, LVL_1_DATA, 16 }, + { 0x68, LVL_1_DATA, 32 }, + { 0x70, LVL_TRACE, 12 }, + { 0x71, LVL_TRACE, 16 }, + { 0x72, LVL_TRACE, 32 }, + { 0x79, LVL_2, 128 }, + { 0x7a, LVL_2, 256 }, + { 0x7b, LVL_2, 512 }, + { 0x7c, LVL_2, 1024 }, + { 0x82, LVL_2, 256 }, + { 0x83, LVL_2, 512 }, + { 0x84, LVL_2, 1024 }, + { 0x85, LVL_2, 2048 }, + { 0x86, LVL_2, 512 }, + { 0x87, LVL_2, 1024 }, + { 0x00, 0, 0} +}; + +static void __init init_intel(struct cpuinfo_x86 *c) +{ + /* Cache sizes */ + unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; + unsigned n; + + select_idle_routine(c); + if (c->cpuid_level > 1) { + /* supports eax=2 call */ + int i, j, n; + int regs[4]; + unsigned char *dp = (unsigned char *)regs; + + /* Number of times to iterate */ + n = cpuid_eax(2) & 0xFF; + + for ( i = 0 ; i < n ; i++ ) { + cpuid(2, ®s[0], ®s[1], ®s[2], ®s[3]); + + /* If bit 31 is set, this is an unknown format */ + for ( j = 0 ; j < 3 ; j++ ) { + if ( regs[j] < 0 ) regs[j] = 0; + } + + /* Byte 0 is level count, not a descriptor */ + for ( j = 1 ; j < 16 ; j++ ) { + unsigned char des = dp[j]; + unsigned char k = 0; + + /* look up this descriptor in the table */ + while (cache_table[k].descriptor != 0) + { + if (cache_table[k].descriptor == des) { + switch (cache_table[k].cache_type) { + case LVL_1_INST: + l1i += cache_table[k].size; + break; + case LVL_1_DATA: + l1d += cache_table[k].size; + break; + case LVL_2: + l2 += cache_table[k].size; + break; + case LVL_3: + l3 += cache_table[k].size; + break; + case LVL_TRACE: + trace += cache_table[k].size; + break; + } + + break; + } + + k++; + } + } + } + + if (trace) + printk (KERN_INFO "CPU: Trace cache: %dK uops", trace); + else if (l1i) + printk (KERN_INFO "CPU: L1 I cache: %dK", l1i); + if (l1d) + printk(", L1 D cache: %dK\n", l1d); + else + printk("\n"); + if (l2) + printk(KERN_INFO "CPU: L2 cache: %dK\n", l2); + if (l3) + printk(KERN_INFO "CPU: L3 cache: %dK\n", l3); + + c->x86_cache_size = l2 ? l2 : (l1i+l1d); + } + + if (cpu_has(c, X86_FEATURE_HT)) + detect_ht(); + + n = cpuid_eax(0x80000000); + if (n >= 0x80000008) { + unsigned eax = cpuid_eax(0x80000008); + c->x86_virt_bits = (eax >> 8) & 0xff; + c->x86_phys_bits = eax & 0xff; + } +} void __init get_cpu_vendor(struct cpuinfo_x86 *c) { @@ -591,6 +780,8 @@ if (!strcmp(v, "AuthenticAMD")) c->x86_vendor = X86_VENDOR_AMD; + else if (!strcmp(v, "GenuineIntel")) + c->x86_vendor = X86_VENDOR_INTEL; else c->x86_vendor = X86_VENDOR_UNKNOWN; } @@ -606,7 +797,7 @@ */ void __init identify_cpu(struct cpuinfo_x86 *c) { - int junk, i; + int i; u32 xlvl, tfms; c->loops_per_jiffy = loops_per_jiffy; @@ -630,7 +821,7 @@ /* Intel-defined flags: level 0x00000001 */ if (c->cpuid_level >= 0x00000001) { __u32 misc; - cpuid(0x00000001, &tfms, &misc, &junk, + cpuid(0x00000001, &tfms, &misc, &c->x86_capability[4], &c->x86_capability[0]); c->x86 = (tfms >> 8) & 0xf; c->x86_model = (tfms >> 4) & 0xf; @@ -679,9 +870,13 @@ init_amd(c); break; + case X86_VENDOR_INTEL: + init_intel(c); + break; + case X86_VENDOR_UNKNOWN: default: - /* Not much we can do here... */ + display_cacheinfo(c); break; } @@ -732,7 +927,7 @@ "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce", "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov", "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx", - "fxsr", "sse", "sse2", "ss", NULL, "tm", "ia64", NULL, + "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", NULL, /* AMD-defined */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, @@ -751,6 +946,12 @@ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + + /* Intel-defined (#2) */ + "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "tm2", + "est", NULL, "cid", NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; static char *x86_power_flags[] = { "ts", /* temperature sensor */ @@ -790,6 +991,14 @@ if (c->x86_cache_size >= 0) seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size); +#ifdef CONFIG_X86_HT + if (cpu_has_ht) { + extern int phys_proc_id[NR_CPUS]; + seq_printf(m, "physical id\t: %d\n", phys_proc_id[c - cpu_data]); + seq_printf(m, "siblings\t: %d\n", smp_num_siblings); + } +#endif + seq_printf(m, "fpu\t\t: yes\n" "fpu_exception\t: yes\n" diff -Nru a/arch/x86_64/kernel/smpboot.c b/arch/x86_64/kernel/smpboot.c --- a/arch/x86_64/kernel/smpboot.c Thu Feb 19 23:44:28 2004 +++ b/arch/x86_64/kernel/smpboot.c Thu Feb 19 23:44:28 2004 @@ -53,6 +53,10 @@ #include #include +/* Number of siblings per CPU package */ +int smp_num_siblings = 1; +int phys_proc_id[NR_CPUS]; /* Package ID of each logical CPU */ + /* Bitmask of currently online CPUs */ cpumask_t cpu_online_map; @@ -66,6 +70,8 @@ /* Set when the idlers are all forked */ int smp_threads_ready; +int cpu_sibling_map[NR_CPUS] __cacheline_aligned; + /* * Trampoline 80x86 program as an array. */ @@ -855,6 +861,34 @@ bogosum/(500000/HZ), (bogosum/(5000/HZ))%100); Dprintk("Before bogocount - setting activated=1.\n"); + } + + /* + * If Hyper-Threading is avaialble, construct cpu_sibling_map[], so + * that we can tell the sibling CPU efficiently. + */ + if (cpu_has_ht && smp_num_siblings > 1) { + for (cpu = 0; cpu < NR_CPUS; cpu++) + cpu_sibling_map[cpu] = NO_PROC_ID; + + for (cpu = 0; cpu < NR_CPUS; cpu++) { + int i; + if (!cpu_isset(cpu, cpu_callout_map)) + continue; + + for (i = 0; i < NR_CPUS; i++) { + if (i == cpu || !cpu_isset(i, cpu_callout_map)) + continue; + if (phys_proc_id[cpu] == phys_proc_id[i]) { + cpu_sibling_map[cpu] = i; + break; + } + } + if (cpu_sibling_map[cpu] == NO_PROC_ID) { + smp_num_siblings = 1; + printk(KERN_WARNING "WARNING: No sibling found for CPU %d.\n", cpu); + } + } } Dprintk("Boot done.\n"); diff -Nru a/arch/x86_64/kernel/x8664_ksyms.c b/arch/x86_64/kernel/x8664_ksyms.c --- a/arch/x86_64/kernel/x8664_ksyms.c Thu Feb 19 23:44:23 2004 +++ b/arch/x86_64/kernel/x8664_ksyms.c Thu Feb 19 23:44:23 2004 @@ -194,6 +194,10 @@ EXPORT_SYMBOL(die_chain); +#ifdef CONFIG_SMP +EXPORT_SYMBOL(cpu_sibling_map); +#endif + extern void do_softirq_thunk(void); EXPORT_SYMBOL_NOVERS(do_softirq_thunk); diff -Nru a/arch/x86_64/lib/copy_page.S b/arch/x86_64/lib/copy_page.S --- a/arch/x86_64/lib/copy_page.S Thu Feb 19 23:44:24 2004 +++ b/arch/x86_64/lib/copy_page.S Thu Feb 19 23:44:24 2004 @@ -8,11 +8,6 @@ .globl copy_page .p2align 4 copy_page: - prefetch (%rsi) - prefetch 1*64(%rsi) - prefetchw (%rdi) - prefetchw 1*64(%rdi) - subq $3*8,%rsp movq %rbx,(%rsp) movq %r12,1*8(%rsp) @@ -32,7 +27,7 @@ movq 48 (%rsi), %r11 movq 56 (%rsi), %r12 - prefetch 5*64(%rsi) + prefetcht0 5*64(%rsi) movq %rax, (%rdi) movq %rbx, 8 (%rdi) @@ -42,8 +37,6 @@ movq %r10, 40 (%rdi) movq %r11, 48 (%rdi) movq %r12, 56 (%rdi) - - prefetchw 5*64(%rdi) leaq 64 (%rsi), %rsi leaq 64 (%rdi), %rdi diff -Nru a/arch/x86_64/lib/csum-copy.S b/arch/x86_64/lib/csum-copy.S --- a/arch/x86_64/lib/csum-copy.S Thu Feb 19 23:44:27 2004 +++ b/arch/x86_64/lib/csum-copy.S Thu Feb 19 23:44:27 2004 @@ -59,15 +59,6 @@ cmpl $3*64,%edx jle .Lignore - ignore - prefetch (%rdi) - ignore - prefetch 1*64(%rdi) - ignore - prefetchw (%rsi) - ignore - prefetchw 1*64(%rsi) - .Lignore: subq $7*8,%rsp movq %rbx,2*8(%rsp) @@ -115,7 +106,7 @@ movq 56(%rdi),%r13 ignore 2f - prefetch 5*64(%rdi) + prefetcht0 5*64(%rdi) 2: adcq %rbx,%rax adcq %r8,%rax @@ -146,8 +137,6 @@ dest movq %r13,56(%rsi) - ignore 3f - prefetchw 5*64(%rsi) 3: leaq 64(%rdi),%rdi diff -Nru a/arch/x86_64/mm/init.c b/arch/x86_64/mm/init.c --- a/arch/x86_64/mm/init.c Thu Feb 19 23:44:23 2004 +++ b/arch/x86_64/mm/init.c Thu Feb 19 23:44:23 2004 @@ -402,6 +402,13 @@ int codesize, reservedpages, datasize, initsize; int tmp; +#ifdef CONFIG_SWIOTLB + if (!iommu_aperture && end_pfn >= 0xffffffff>>PAGE_SHIFT) { + swiotlb_init(); + swiotlb = 1; + } +#endif + /* How many end-of-memory variables you have, grandma! */ max_low_pfn = end_pfn; max_pfn = end_pfn; diff -Nru a/arch/x86_64/oprofile/Makefile b/arch/x86_64/oprofile/Makefile --- a/arch/x86_64/oprofile/Makefile Thu Feb 19 23:44:23 2004 +++ b/arch/x86_64/oprofile/Makefile Thu Feb 19 23:44:23 2004 @@ -1,7 +1,6 @@ # # oprofile for x86-64. -# Just reuse the one from i386. The Hammer performance counters -# are similar to Athlon. +# Just reuse the one from i386. # obj-$(CONFIG_OPROFILE) += oprofile.o @@ -13,7 +12,8 @@ timer_int.o ) OPROFILE-y := init.o -OPROFILE-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o +OPROFILE-$(CONFIG_X86_LOCAL_APIC) += nmi_int.o op_model_athlon.o op_model_p4.o \ + op_model_ppro.o OPROFILE-$(CONFIG_X86_IO_APIC) += nmi_timer_int.o oprofile-y = $(DRIVER_OBJS) $(addprefix ../../i386/oprofile/, $(OPROFILE-y)) diff -Nru a/drivers/Makefile b/drivers/Makefile --- a/drivers/Makefile Thu Feb 19 23:44:27 2004 +++ b/drivers/Makefile Thu Feb 19 23:44:27 2004 @@ -45,7 +45,7 @@ obj-$(CONFIG_PHONE) += telephony/ obj-$(CONFIG_MD) += md/ obj-$(CONFIG_BT) += bluetooth/ -obj-$(CONFIG_ISDN_BOOL) += isdn/ +obj-$(CONFIG_ISDN) += isdn/ obj-$(CONFIG_MCA) += mca/ obj-$(CONFIG_EISA) += eisa/ obj-$(CONFIG_CPU_FREQ) += cpufreq/ diff -Nru a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig --- a/drivers/acpi/Kconfig Thu Feb 19 23:44:28 2004 +++ b/drivers/acpi/Kconfig Thu Feb 19 23:44:28 2004 @@ -263,5 +263,23 @@ particular, many Toshiba laptops require this for correct operation of the AC module. +config X86_PM_TIMER + bool "Power Management Timer Support" + depends on X86 && ACPI + depends on ACPI_BOOT && EXPERIMENTAL + default n + help + The Power Management Timer is available on all ACPI-capable, + in most cases even if ACPI is unusable or blacklisted. + + This timing source is not affected by powermanagement features + like aggressive processor idling, throttling, frequency and/or + voltage scaling, unlike the commonly used Time Stamp Counter + (TSC) timing source. + + So, if you see messages like 'Losing too many ticks!' in the + kernel logs, and/or you are using a this on a notebook which + does not yet have an HPET, you should say "Y" here. + endmenu diff -Nru a/drivers/base/dmapool.c b/drivers/base/dmapool.c --- a/drivers/base/dmapool.c Thu Feb 19 23:44:28 2004 +++ b/drivers/base/dmapool.c Thu Feb 19 23:44:28 2004 @@ -52,7 +52,7 @@ next = buf; size = PAGE_SIZE; - temp = snprintf (next, size, "poolinfo - 0.1\n"); + temp = scnprintf(next, size, "poolinfo - 0.1\n"); size -= temp; next += temp; @@ -67,7 +67,7 @@ } /* per-pool info, no real statistics yet */ - temp = snprintf (next, size, "%-16s %4u %4Zu %4Zu %2u\n", + temp = scnprintf(next, size, "%-16s %4u %4Zu %4Zu %2u\n", pool->name, blocks, pages * pool->blocks_per_page, pool->size, pages); diff -Nru a/drivers/base/node.c b/drivers/base/node.c --- a/drivers/base/node.c Thu Feb 19 23:44:23 2004 +++ b/drivers/base/node.c Thu Feb 19 23:44:23 2004 @@ -23,7 +23,7 @@ /* FIXME - someone should pass us a buffer size (count) or * use seq_file or something to avoid buffer overrun risk. */ - len = cpumask_snprintf(buf, 99 /* XXX FIXME */, mask); + len = cpumask_scnprintf(buf, 99 /* XXX FIXME */, mask); len += sprintf(buf + len, "\n"); return len; } diff -Nru a/drivers/block/cryptoloop.c b/drivers/block/cryptoloop.c --- a/drivers/block/cryptoloop.c Thu Feb 19 23:44:26 2004 +++ b/drivers/block/cryptoloop.c Thu Feb 19 23:44:26 2004 @@ -87,43 +87,49 @@ static int -cryptoloop_transfer_ecb(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size, sector_t IV) +cryptoloop_transfer_ecb(struct loop_device *lo, int cmd, + struct page *raw_page, unsigned raw_off, + struct page *loop_page, unsigned loop_off, + int size, sector_t IV) { struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; struct scatterlist sg_out = { 0, }; struct scatterlist sg_in = { 0, }; encdec_ecb_t encdecfunc; - char const *in; - char *out; + struct page *in_page, *out_page; + unsigned in_offs, out_offs; if (cmd == READ) { - in = raw_buf; - out = loop_buf; + in_page = raw_page; + in_offs = raw_off; + out_page = loop_page; + out_offs = loop_off; encdecfunc = tfm->crt_u.cipher.cit_decrypt; } else { - in = loop_buf; - out = raw_buf; + in_page = loop_page; + in_offs = loop_off; + out_page = raw_page; + out_offs = raw_off; encdecfunc = tfm->crt_u.cipher.cit_encrypt; } while (size > 0) { const int sz = min(size, LOOP_IV_SECTOR_SIZE); - sg_in.page = virt_to_page(in); - sg_in.offset = (unsigned long)in & ~PAGE_MASK; + sg_in.page = in_page; + sg_in.offset = in_offs; sg_in.length = sz; - sg_out.page = virt_to_page(out); - sg_out.offset = (unsigned long)out & ~PAGE_MASK; + sg_out.page = out_page; + sg_out.offset = out_offs; sg_out.length = sz; encdecfunc(tfm, &sg_out, &sg_in, sz); size -= sz; - in += sz; - out += sz; + in_offs += sz; + out_offs += sz; } return 0; @@ -135,24 +141,30 @@ unsigned int nsg, u8 *iv); static int -cryptoloop_transfer_cbc(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size, sector_t IV) +cryptoloop_transfer_cbc(struct loop_device *lo, int cmd, + struct page *raw_page, unsigned raw_off, + struct page *loop_page, unsigned loop_off, + int size, sector_t IV) { struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; struct scatterlist sg_out = { 0, }; struct scatterlist sg_in = { 0, }; encdec_cbc_t encdecfunc; - char const *in; - char *out; + struct page *in_page, *out_page; + unsigned in_offs, out_offs; if (cmd == READ) { - in = raw_buf; - out = loop_buf; + in_page = raw_page; + in_offs = raw_off; + out_page = loop_page; + out_offs = loop_off; encdecfunc = tfm->crt_u.cipher.cit_decrypt_iv; } else { - in = loop_buf; - out = raw_buf; + in_page = loop_page; + in_offs = loop_off; + out_page = raw_page; + out_offs = raw_off; encdecfunc = tfm->crt_u.cipher.cit_encrypt_iv; } @@ -161,39 +173,43 @@ u32 iv[4] = { 0, }; iv[0] = cpu_to_le32(IV & 0xffffffff); - sg_in.page = virt_to_page(in); - sg_in.offset = offset_in_page(in); + sg_in.page = in_page; + sg_in.offset = in_offs; sg_in.length = sz; - sg_out.page = virt_to_page(out); - sg_out.offset = offset_in_page(out); + sg_out.page = out_page; + sg_out.offset = out_offs; sg_out.length = sz; encdecfunc(tfm, &sg_out, &sg_in, sz, (u8 *)iv); IV++; size -= sz; - in += sz; - out += sz; + in_offs += sz; + out_offs += sz; } return 0; } static int -cryptoloop_transfer(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size, sector_t IV) +cryptoloop_transfer(struct loop_device *lo, int cmd, + struct page *raw_page, unsigned raw_off, + struct page *loop_page, unsigned loop_off, + int size, sector_t IV) { struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data; if(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB) { lo->transfer = cryptoloop_transfer_ecb; - return cryptoloop_transfer_ecb(lo, cmd, raw_buf, loop_buf, size, IV); + return cryptoloop_transfer_ecb(lo, cmd, raw_page, raw_off, + loop_page, loop_off, size, IV); } if(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_CBC) { lo->transfer = cryptoloop_transfer_cbc; - return cryptoloop_transfer_cbc(lo, cmd, raw_buf, loop_buf, size, IV); + return cryptoloop_transfer_cbc(lo, cmd, raw_page, raw_off, + loop_page, loop_off, size, IV); } /* This is not supposed to happen */ diff -Nru a/drivers/block/genhd.c b/drivers/block/genhd.c --- a/drivers/block/genhd.c Thu Feb 19 23:44:25 2004 +++ b/drivers/block/genhd.c Thu Feb 19 23:44:25 2004 @@ -262,8 +262,9 @@ /* Don't show non-partitionable removeable devices or empty devices */ if (!get_capacity(sgp) || - (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE)) - ) + (sgp->minors == 1 && (sgp->flags & GENHD_FL_REMOVABLE))) + return 0; + if (sgp->flags & GENHD_FL_SUPPRESS_PARTITION_INFO) return 0; /* show the full disk and all non-0 size partitions of it */ diff -Nru a/drivers/block/loop.c b/drivers/block/loop.c --- a/drivers/block/loop.c Thu Feb 19 23:44:26 2004 +++ b/drivers/block/loop.c Thu Feb 19 23:44:26 2004 @@ -76,24 +76,34 @@ /* * Transfer functions */ -static int transfer_none(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size, sector_t real_block) +static int transfer_none(struct loop_device *lo, int cmd, + struct page *raw_page, unsigned raw_off, + struct page *loop_page, unsigned loop_off, + int size, sector_t real_block) { - if (raw_buf != loop_buf) { - if (cmd == READ) - memcpy(loop_buf, raw_buf, size); - else - memcpy(raw_buf, loop_buf, size); - } + char *raw_buf = kmap_atomic(raw_page, KM_USER0) + raw_off; + char *loop_buf = kmap_atomic(loop_page, KM_USER1) + loop_off; + + if (cmd == READ) + memcpy(loop_buf, raw_buf, size); + else + memcpy(raw_buf, loop_buf, size); + kunmap_atomic(raw_buf, KM_USER0); + kunmap_atomic(loop_buf, KM_USER1); + cond_resched(); return 0; } -static int transfer_xor(struct loop_device *lo, int cmd, char *raw_buf, - char *loop_buf, int size, sector_t real_block) +static int transfer_xor(struct loop_device *lo, int cmd, + struct page *raw_page, unsigned raw_off, + struct page *loop_page, unsigned loop_off, + int size, sector_t real_block) { - char *in, *out, *key; - int i, keysize; + char *raw_buf = kmap_atomic(raw_page, KM_USER0) + raw_off; + char *loop_buf = kmap_atomic(loop_page, KM_USER1) + loop_off; + char *in, *out, *key; + int i, keysize; if (cmd == READ) { in = raw_buf; @@ -107,6 +117,10 @@ keysize = lo->lo_encrypt_key_size; for (i = 0; i < size; i++) *out++ = *in++ ^ key[(i & 511) % keysize]; + + kunmap_atomic(raw_buf, KM_USER0); + kunmap_atomic(loop_buf, KM_USER1); + cond_resched(); return 0; } @@ -162,13 +176,15 @@ } static inline int -lo_do_transfer(struct loop_device *lo, int cmd, char *rbuf, - char *lbuf, int size, sector_t rblock) +lo_do_transfer(struct loop_device *lo, int cmd, + struct page *rpage, unsigned roffs, + struct page *lpage, unsigned loffs, + int size, sector_t rblock) { if (!lo->transfer) return 0; - return lo->transfer(lo, cmd, rbuf, lbuf, size, rblock); + return lo->transfer(lo, cmd, rpage, roffs, lpage, loffs, size, rblock); } static int @@ -178,16 +194,15 @@ struct address_space *mapping = file->f_mapping; struct address_space_operations *aops = mapping->a_ops; struct page *page; - char *kaddr, *data; pgoff_t index; - unsigned size, offset; + unsigned size, offset, bv_offs; int len; int ret = 0; down(&mapping->host->i_sem); index = pos >> PAGE_CACHE_SHIFT; offset = pos & ((pgoff_t)PAGE_CACHE_SIZE - 1); - data = kmap(bvec->bv_page) + bvec->bv_offset; + bv_offs = bvec->bv_offset; len = bvec->bv_len; while (len > 0) { sector_t IV; @@ -204,25 +219,28 @@ goto fail; if (aops->prepare_write(file, page, offset, offset+size)) goto unlock; - kaddr = kmap(page); - transfer_result = lo_do_transfer(lo, WRITE, kaddr + offset, - data, size, IV); + transfer_result = lo_do_transfer(lo, WRITE, page, offset, + bvec->bv_page, bv_offs, + size, IV); if (transfer_result) { + char *kaddr; + /* * The transfer failed, but we still write the data to * keep prepare/commit calls balanced. */ printk(KERN_ERR "loop: transfer error block %llu\n", (unsigned long long)index); + kaddr = kmap_atomic(page, KM_USER0); memset(kaddr + offset, 0, size); + kunmap_atomic(kaddr, KM_USER0); } flush_dcache_page(page); - kunmap(page); if (aops->commit_write(file, page, offset, offset+size)) goto unlock; if (transfer_result) goto unlock; - data += size; + bv_offs += size; len -= size; offset = 0; index++; @@ -232,7 +250,6 @@ } up(&mapping->host->i_sem); out: - kunmap(bvec->bv_page); return ret; unlock: @@ -247,12 +264,10 @@ static int lo_send(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos) { - unsigned vecnr; - int ret = 0; - - for (vecnr = 0; vecnr < bio->bi_vcnt; vecnr++) { - struct bio_vec *bvec = &bio->bi_io_vec[vecnr]; + struct bio_vec *bvec; + int i, ret = 0; + bio_for_each_segment(bvec, bio, i) { ret = do_lo_send(lo, bvec, bsize, pos); if (ret < 0) break; @@ -263,7 +278,8 @@ struct lo_read_data { struct loop_device *lo; - char *data; + struct page *page; + unsigned offset; int bsize; }; @@ -271,7 +287,6 @@ lo_read_actor(read_descriptor_t *desc, struct page *page, unsigned long offset, unsigned long size) { - char *kaddr; unsigned long count = desc->count; struct lo_read_data *p = (struct lo_read_data*)desc->buf; struct loop_device *lo = p->lo; @@ -282,18 +297,16 @@ if (size > count) size = count; - kaddr = kmap(page); - if (lo_do_transfer(lo, READ, kaddr + offset, p->data, size, IV)) { + if (lo_do_transfer(lo, READ, page, offset, p->page, p->offset, size, IV)) { size = 0; printk(KERN_ERR "loop: transfer error block %ld\n", page->index); desc->error = -EINVAL; } - kunmap(page); desc->count = count - size; desc->written += size; - p->data += size; + p->offset += size; return size; } @@ -306,24 +319,22 @@ int retval; cookie.lo = lo; - cookie.data = kmap(bvec->bv_page) + bvec->bv_offset; + cookie.page = bvec->bv_page; + cookie.offset = bvec->bv_offset; cookie.bsize = bsize; file = lo->lo_backing_file; retval = file->f_op->sendfile(file, &pos, bvec->bv_len, lo_read_actor, &cookie); - kunmap(bvec->bv_page); return (retval < 0)? retval: 0; } static int lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos) { - unsigned vecnr; - int ret = 0; - - for (vecnr = 0; vecnr < bio->bi_vcnt; vecnr++) { - struct bio_vec *bvec = &bio->bi_io_vec[vecnr]; + struct bio_vec *bvec; + int i, ret = 0; + bio_for_each_segment(bvec, bio, i) { ret = do_lo_receive(lo, bvec, bsize, pos); if (ret < 0) break; @@ -345,23 +356,6 @@ return ret; } -static int loop_end_io_transfer(struct bio *, unsigned int, int); - -static void loop_put_buffer(struct bio *bio) -{ - /* - * check bi_end_io, may just be a remapped bio - */ - if (bio && bio->bi_end_io == loop_end_io_transfer) { - int i; - - for (i = 0; i < bio->bi_vcnt; i++) - __free_page(bio->bi_io_vec[i].bv_page); - - bio_put(bio); - } -} - /* * Add bio to back of pending list */ @@ -399,129 +393,8 @@ return bio; } -/* - * if this was a WRITE lo->transfer stuff has already been done. for READs, - * queue it for the loop thread and let it do the transfer out of - * bi_end_io context (we don't want to do decrypt of a page with irqs - * disabled) - */ -static int loop_end_io_transfer(struct bio *bio, unsigned int bytes_done, int err) -{ - struct bio *rbh = bio->bi_private; - struct loop_device *lo = rbh->bi_bdev->bd_disk->private_data; - - if (bio->bi_size) - return 1; - - if (err || bio_rw(bio) == WRITE) { - bio_endio(rbh, rbh->bi_size, err); - if (atomic_dec_and_test(&lo->lo_pending)) - up(&lo->lo_bh_mutex); - loop_put_buffer(bio); - } else - loop_add_bio(lo, bio); - - return 0; -} - -static struct bio *loop_copy_bio(struct bio *rbh) -{ - struct bio *bio; - struct bio_vec *bv; - int i; - - bio = bio_alloc(__GFP_NOWARN, rbh->bi_vcnt); - if (!bio) - return NULL; - - /* - * iterate iovec list and alloc pages - */ - __bio_for_each_segment(bv, rbh, i, 0) { - struct bio_vec *bbv = &bio->bi_io_vec[i]; - - bbv->bv_page = alloc_page(__GFP_NOWARN|__GFP_HIGHMEM); - if (bbv->bv_page == NULL) - goto oom; - - bbv->bv_len = bv->bv_len; - bbv->bv_offset = bv->bv_offset; - } - - bio->bi_vcnt = rbh->bi_vcnt; - bio->bi_size = rbh->bi_size; - - return bio; - -oom: - while (--i >= 0) - __free_page(bio->bi_io_vec[i].bv_page); - - bio_put(bio); - return NULL; -} - -static struct bio *loop_get_buffer(struct loop_device *lo, struct bio *rbh) -{ - struct bio *bio; - - /* - * When called on the page reclaim -> writepage path, this code can - * trivially consume all memory. So we drop PF_MEMALLOC to avoid - * stealing all the page reserves and throttle to the writeout rate. - * pdflush will have been woken by page reclaim. Let it do its work. - */ - do { - int flags = current->flags; - - current->flags &= ~PF_MEMALLOC; - bio = loop_copy_bio(rbh); - if (flags & PF_MEMALLOC) - current->flags |= PF_MEMALLOC; - - if (bio == NULL) - blk_congestion_wait(WRITE, HZ/10); - } while (bio == NULL); - - bio->bi_end_io = loop_end_io_transfer; - bio->bi_private = rbh; - bio->bi_sector = rbh->bi_sector + (lo->lo_offset >> 9); - bio->bi_rw = rbh->bi_rw; - bio->bi_bdev = lo->lo_device; - - return bio; -} - -static int loop_transfer_bio(struct loop_device *lo, - struct bio *to_bio, struct bio *from_bio) -{ - sector_t IV; - struct bio_vec *from_bvec, *to_bvec; - char *vto, *vfrom; - int ret = 0, i; - - IV = from_bio->bi_sector + (lo->lo_offset >> 9); - - __bio_for_each_segment(from_bvec, from_bio, i, 0) { - to_bvec = &to_bio->bi_io_vec[i]; - - kmap(from_bvec->bv_page); - kmap(to_bvec->bv_page); - vfrom = page_address(from_bvec->bv_page) + from_bvec->bv_offset; - vto = page_address(to_bvec->bv_page) + to_bvec->bv_offset; - ret |= lo_do_transfer(lo, bio_data_dir(to_bio), vto, vfrom, - from_bvec->bv_len, IV); - kunmap(from_bvec->bv_page); - kunmap(to_bvec->bv_page); - IV += from_bvec->bv_len >> 9; - } - - return ret; -} - static int loop_make_request(request_queue_t *q, struct bio *old_bio) { - struct bio *new_bio = NULL; struct loop_device *lo = q->queuedata; int rw = bio_rw(old_bio); @@ -543,31 +416,11 @@ printk(KERN_ERR "loop: unknown command (%x)\n", rw); goto err; } - - /* - * file backed, queue for loop_thread to handle - */ - if (lo->lo_flags & LO_FLAGS_DO_BMAP) { - loop_add_bio(lo, old_bio); - return 0; - } - - /* - * piggy old buffer on original, and submit for I/O - */ - new_bio = loop_get_buffer(lo, old_bio); - if (rw == WRITE) { - if (loop_transfer_bio(lo, new_bio, old_bio)) - goto err; - } - - generic_make_request(new_bio); + loop_add_bio(lo, old_bio); return 0; - err: if (atomic_dec_and_test(&lo->lo_pending)) up(&lo->lo_bh_mutex); - loop_put_buffer(new_bio); out: bio_io_error(old_bio, old_bio->bi_size); return 0; @@ -580,20 +433,8 @@ { int ret; - /* - * For block backed loop, we know this is a READ - */ - if (lo->lo_flags & LO_FLAGS_DO_BMAP) { - ret = do_bio_filebacked(lo, bio); - bio_endio(bio, bio->bi_size, ret); - } else { - struct bio *rbh = bio->bi_private; - - ret = loop_transfer_bio(lo, bio, rbh); - - bio_endio(rbh, rbh->bi_size, ret); - loop_put_buffer(bio); - } + ret = do_bio_filebacked(lo, bio); + bio_endio(bio, bio->bi_size, ret); } /* @@ -684,31 +525,23 @@ lo_flags |= LO_FLAGS_READ_ONLY; error = -EINVAL; - if (S_ISBLK(inode->i_mode)) { - lo_device = I_BDEV(inode); - if (lo_device == bdev) { - error = -EBUSY; - goto out_putf; - } - lo_blocksize = block_size(lo_device); - if (bdev_read_only(lo_device)) - lo_flags |= LO_FLAGS_READ_ONLY; - } else if (S_ISREG(inode->i_mode)) { + if (S_ISREG(inode->i_mode) || S_ISBLK(inode->i_mode)) { struct address_space_operations *aops = mapping->a_ops; /* * If we can't read - sorry. If we only can't write - well, * it's going to be read-only. */ - if (!inode->i_fop->sendfile) + if (!lo_file->f_op->sendfile) goto out_putf; if (!aops->prepare_write || !aops->commit_write) lo_flags |= LO_FLAGS_READ_ONLY; lo_blocksize = inode->i_blksize; - lo_flags |= LO_FLAGS_DO_BMAP; - } else + error = 0; + } else { goto out_putf; + } if (!(lo_file->f_mode & FMODE_WRITE)) lo_flags |= LO_FLAGS_READ_ONLY; @@ -738,21 +571,6 @@ blk_queue_make_request(lo->lo_queue, loop_make_request); lo->lo_queue->queuedata = lo; - /* - * we remap to a block device, make sure we correctly stack limits - */ - if (S_ISBLK(inode->i_mode)) { - request_queue_t *q = bdev_get_queue(lo_device); - - blk_queue_max_sectors(lo->lo_queue, q->max_sectors); - blk_queue_max_phys_segments(lo->lo_queue,q->max_phys_segments); - blk_queue_max_hw_segments(lo->lo_queue, q->max_hw_segments); - blk_queue_hardsect_size(lo->lo_queue, queue_hardsect_size(q)); - blk_queue_max_segment_size(lo->lo_queue, q->max_segment_size); - blk_queue_segment_boundary(lo->lo_queue, q->seg_boundary_mask); - blk_queue_merge_bvec(lo->lo_queue, q->merge_bvec_fn); - } - set_blocksize(bdev, lo_blocksize); kernel_thread(loop_thread, lo, CLONE_KERNEL); @@ -1196,7 +1014,6 @@ lo->lo_queue = blk_alloc_queue(GFP_KERNEL); if (!lo->lo_queue) goto out_mem4; - disks[i]->queue = lo->lo_queue; init_MUTEX(&lo->lo_ctl_mutex); init_MUTEX_LOCKED(&lo->lo_sem); init_MUTEX_LOCKED(&lo->lo_bh_mutex); @@ -1209,14 +1026,18 @@ sprintf(disk->devfs_name, "loop/%d", i); disk->private_data = lo; disk->queue = lo->lo_queue; - add_disk(disk); } + + /* We cannot fail after we call this, so another loop!*/ + for (i = 0; i < max_loop; i++) + add_disk(disks[i]); printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop); return 0; out_mem4: while (i--) blk_put_queue(loop_dev[i].lo_queue); + devfs_remove("loop"); i = max_loop; out_mem3: while (i--) diff -Nru a/drivers/block/nbd.c b/drivers/block/nbd.c --- a/drivers/block/nbd.c Thu Feb 19 23:44:23 2004 +++ b/drivers/block/nbd.c Thu Feb 19 23:44:23 2004 @@ -741,6 +741,7 @@ disk->first_minor = i; disk->fops = &nbd_fops; disk->private_data = &nbd_dev[i]; + disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO; sprintf(disk->disk_name, "nbd%d", i); sprintf(disk->devfs_name, "nbd/%d", i); set_capacity(disk, 0x3ffffe); diff -Nru a/drivers/block/rd.c b/drivers/block/rd.c --- a/drivers/block/rd.c Thu Feb 19 23:44:26 2004 +++ b/drivers/block/rd.c Thu Feb 19 23:44:26 2004 @@ -1,15 +1,15 @@ /* * ramdisk.c - Multiple RAM disk driver - gzip-loading version - v. 0.8 beta. - * - * (C) Chad Page, Theodore Ts'o, et. al, 1995. + * + * (C) Chad Page, Theodore Ts'o, et. al, 1995. * * This RAM disk is designed to have filesystems created on it and mounted - * just like a regular floppy disk. - * + * just like a regular floppy disk. + * * It also does something suggested by Linus: use the buffer cache as the * RAM disk data. This makes it possible to dynamically allocate the RAM disk - * buffer - with some consequences I have to deal with as I write this. - * + * buffer - with some consequences I have to deal with as I write this. + * * This code is based on the original ramdisk.c, written mostly by * Theodore Ts'o (TYT) in 1991. The code was largely rewritten by * Chad Page to use the buffer cache to store the RAM disk data in @@ -33,7 +33,7 @@ * * Added initrd: Werner Almesberger & Hans Lermen, Feb '96 * - * 4/25/96 : Made RAM disk size a parameter (default is now 4 MB) + * 4/25/96 : Made RAM disk size a parameter (default is now 4 MB) * - Chad Page * * Add support for fs images split across >1 disk, Paul Gortmaker, Mar '98 @@ -60,7 +60,7 @@ #include /* The RAM disk size is now a parameter */ -#define NUM_RAMDISKS 16 /* This cannot be overridden (yet) */ +#define NUM_RAMDISKS 16 /* This cannot be overridden (yet) */ /* Various static variables go here. Most are used only in the RAM disk code. */ @@ -73,7 +73,7 @@ * Parameters for the boot-loading of the RAM disk. These are set by * init/main.c (from arguments to the kernel command line) or from the * architecture-specific setup routine (from the stored boot sector - * information). + * information). */ int rd_size = CONFIG_BLK_DEV_RAM_SIZE; /* Size of the RAM disks */ /* @@ -94,7 +94,7 @@ * 2000 Transmeta Corp. * aops copied from ramfs. */ -static int ramdisk_readpage(struct file *file, struct page * page) +static int ramdisk_readpage(struct file *file, struct page *page) { if (!PageUptodate(page)) { void *kaddr = kmap_atomic(page, KM_USER0); @@ -108,7 +108,8 @@ return 0; } -static int ramdisk_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) +static int ramdisk_prepare_write(struct file *file, struct page *page, + unsigned offset, unsigned to) { if (!PageUptodate(page)) { void *kaddr = kmap_atomic(page, KM_USER0); @@ -122,7 +123,8 @@ return 0; } -static int ramdisk_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to) +static int ramdisk_commit_write(struct file *file, struct page *page, + unsigned offset, unsigned to) { return 0; } @@ -212,7 +214,7 @@ * 19-JAN-1998 Richard Gooch Added devfs support * */ -static int rd_make_request(request_queue_t * q, struct bio *bio) +static int rd_make_request(request_queue_t *q, struct bio *bio) { struct block_device *bdev = bio->bi_bdev; struct address_space * mapping = bdev->bd_inode->i_mapping; @@ -242,7 +244,8 @@ return 0; } -static int rd_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +static int rd_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) { int error; struct block_device *bdev = inode->i_bdev; @@ -250,9 +253,11 @@ if (cmd != BLKFLSBUF) return -EINVAL; - /* special: we want to release the ramdisk memory, - it's not like with the other blockdevices where - this ioctl only flushes away the buffer cache. */ + /* + * special: we want to release the ramdisk memory, it's not like with + * the other blockdevices where this ioctl only flushes away the buffer + * cache + */ error = -EBUSY; down(&bdev->bd_sem); if (bdev->bd_openers <= 2) { @@ -268,7 +273,7 @@ .memory_backed = 1, /* Does not contribute to dirty memory */ }; -static int rd_open(struct inode * inode, struct file * filp) +static int rd_open(struct inode *inode, struct file *filp) { unsigned unit = iminor(inode); @@ -295,33 +300,37 @@ .ioctl = rd_ioctl, }; -/* Before freeing the module, invalidate all of the protected buffers! */ -static void __exit rd_cleanup (void) +/* + * Before freeing the module, invalidate all of the protected buffers! + */ +static void __exit rd_cleanup(void) { int i; - for (i = 0 ; i < NUM_RAMDISKS; i++) { + for (i = 0; i < NUM_RAMDISKS; i++) { struct block_device *bdev = rd_bdev[i]; rd_bdev[i] = NULL; if (bdev) { invalidate_bdev(bdev, 1); - blkdev_put(bdev, BDEV_FILE); + blkdev_put(bdev); } del_gendisk(rd_disks[i]); put_disk(rd_disks[i]); } devfs_remove("rd"); - unregister_blkdev(RAMDISK_MAJOR, "ramdisk" ); + unregister_blkdev(RAMDISK_MAJOR, "ramdisk"); } -/* This is the registration and initialization section of the RAM disk driver */ -static int __init rd_init (void) +/* + * This is the registration and initialization section of the RAM disk driver + */ +static int __init rd_init(void) { int i; int err = -ENOMEM; if (rd_blocksize > PAGE_SIZE || rd_blocksize < 512 || - (rd_blocksize & (rd_blocksize-1))) { + (rd_blocksize & (rd_blocksize-1))) { printk("RAMDISK: wrong blocksize %d, reverting to defaults\n", rd_blocksize); rd_blocksize = BLOCK_SIZE; @@ -354,6 +363,7 @@ disk->first_minor = i; disk->fops = &rd_bd_op; disk->queue = rd_queue[i]; + disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO; sprintf(disk->disk_name, "ram%d", i); sprintf(disk->devfs_name, "rd/%d", i); set_capacity(disk, rd_size * 2); @@ -362,8 +372,8 @@ /* rd_size is given in kB */ printk("RAMDISK driver initialized: " - "%d RAM disks of %dK size %d blocksize\n", - NUM_RAMDISKS, rd_size, rd_blocksize); + "%d RAM disks of %dK size %d blocksize\n", + NUM_RAMDISKS, rd_size, rd_blocksize); return 0; out_queue: diff -Nru a/drivers/char/Kconfig b/drivers/char/Kconfig --- a/drivers/char/Kconfig Thu Feb 19 23:44:22 2004 +++ b/drivers/char/Kconfig Thu Feb 19 23:44:22 2004 @@ -794,8 +794,7 @@ precision in some cases. To compile this driver as a module, choose M here: the - module will be called genrtc. To load the module automatically - add 'alias char-major-10-135 genrtc' to your /etc/modules.conf + module will be called genrtc. config GEN_RTC_X bool "Extended RTC operation" diff -Nru a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig --- a/drivers/char/agp/Kconfig Thu Feb 19 23:44:25 2004 +++ b/drivers/char/agp/Kconfig Thu Feb 19 23:44:25 2004 @@ -77,7 +77,7 @@ config AGP_INTEL tristate "Intel 440LX/BX/GX, I8xx and E7x05 chipset support" - depends on AGP && X86 && !X86_64 + depends on AGP && X86 help This option gives you AGP support for the GLX component of XFree86 4.x on Intel 440LX/BX/GX, 815, 820, 830, 840, 845, 850, 860, 875, @@ -150,4 +150,14 @@ help This option gives you AGP support for Apple machines with a UniNorth bridge. + +config AGP_EFFICEON + tristate "Transmeta Efficeon support" + depends on AGP && X86 && !X86_64 + help + This option fives you AGP support for the Transmeta Efficeon + series processors with integrated northbridges. + + You should say Y here if you use XFree86 3.3.6 or 4.x and want to + use GLX or DRI. If unsure, say Y. diff -Nru a/drivers/char/agp/Makefile b/drivers/char/agp/Makefile --- a/drivers/char/agp/Makefile Thu Feb 19 23:44:24 2004 +++ b/drivers/char/agp/Makefile Thu Feb 19 23:44:24 2004 @@ -6,6 +6,7 @@ obj-$(CONFIG_AGP_AMD) += amd-k7-agp.o obj-$(CONFIG_AGP_AMD64) += amd64-agp.o obj-$(CONFIG_AGP_ALPHA_CORE) += alpha-agp.o +obj-$(CONFIG_AGP_EFFICEON) += efficeon-agp.o obj-$(CONFIG_AGP_HP_ZX1) += hp-agp.o obj-$(CONFIG_AGP_I460) += i460-agp.o obj-$(CONFIG_AGP_INTEL) += intel-agp.o diff -Nru a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/char/agp/efficeon-agp.c Thu Feb 19 23:44:29 2004 @@ -0,0 +1,467 @@ +/* + * Transmeta's Efficeon AGPGART driver. + * + * Based upon a diff by Linus around November '02. + * + * Ported to the 2.6 kernel by Carlos Puchol + * and H. Peter Anvin . + */ + +/* + * NOTE-cpg-040217: + * + * - when compiled as a module, after loading the module, + * it will refuse to unload, indicating it is in use, + * when it is not. + * - no s3 (suspend to ram) testing. + * - tested on the efficeon integrated nothbridge for tens + * of iterations of starting x and glxgears. + * - tested with radeon 9000 and radeon mobility m9 cards + * - tested with c3/c4 enabled (with the mobility m9 card) + */ + +#include +#include +#include +#include +#include +#include +#include +#include "agp.h" + +/* + * The real differences to the generic AGP code is + * in the GART mappings - a two-level setup with the + * first level being an on-chip 64-entry table. + * + * The page array is filled through the ATTPAGE register + * (Aperture Translation Table Page Register) at 0xB8. Bits: + * 31:20: physical page address + * 11:9: Page Attribute Table Index (PATI) + * must match the PAT index for the + * mapped pages (the 2nd level page table pages + * themselves should be just regular WB-cacheable, + * so this is normally zero.) + * 8: Present + * 7:6: reserved, write as zero + * 5:0: GATT directory index: which 1st-level entry + * + * The Efficeon AGP spec requires pages to be WB-cacheable + * but to be explicitly CLFLUSH'd after any changes. + */ +#define EFFICEON_ATTPAGE 0xb8 +#define EFFICEON_L1_SIZE 64 /* Number of PDE pages */ + +#define EFFICEON_PATI (0 << 9) +#define EFFICEON_PRESENT (1 << 8) + +static struct _efficeon_private { + unsigned long l1_table[EFFICEON_L1_SIZE]; +} efficeon_private; + +static struct gatt_mask efficeon_generic_masks[] = +{ + {.mask = 0x00000001, .type = 0} +}; + +static struct aper_size_info_lvl2 efficeon_generic_sizes[4] = +{ + {256, 65536, 0}, + {128, 32768, 32}, + {64, 16384, 48}, + {32, 8192, 56} +}; + +/* + * Control interfaces are largely identical to + * the legacy Intel 440BX.. + */ + +static int efficeon_fetch_size(void) +{ + int i; + u16 temp; + struct aper_size_info_lvl2 *values; + + pci_read_config_word(agp_bridge->dev, INTEL_APSIZE, &temp); + values = A_SIZE_LVL2(agp_bridge->driver->aperture_sizes); + + for (i = 0; i < agp_bridge->driver->num_aperture_sizes; i++) { + if (temp == values[i].size_value) { + agp_bridge->previous_size = + agp_bridge->current_size = (void *) (values + i); + agp_bridge->aperture_size_idx = i; + return values[i].size; + } + } + + return 0; +} + +static void efficeon_tlbflush(struct agp_memory * mem) +{ + printk(KERN_DEBUG PFX "efficeon_tlbflush()\n"); + pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2200); + pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280); +} + +static void efficeon_cleanup(void) +{ + u16 temp; + struct aper_size_info_lvl2 *previous_size; + + printk(KERN_DEBUG PFX "efficeon_cleanup()\n"); + previous_size = A_SIZE_LVL2(agp_bridge->previous_size); + pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp); + pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, temp & ~(1 << 9)); + pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, + previous_size->size_value); +} + +static int efficeon_configure(void) +{ + u32 temp; + u16 temp2; + struct aper_size_info_lvl2 *current_size; + + printk(KERN_DEBUG PFX "efficeon_configure()\n"); + + current_size = A_SIZE_LVL2(agp_bridge->current_size); + + /* aperture size */ + pci_write_config_word(agp_bridge->dev, INTEL_APSIZE, + current_size->size_value); + + /* address to map to */ + pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); + agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); + + /* agpctrl */ + pci_write_config_dword(agp_bridge->dev, INTEL_AGPCTRL, 0x2280); + + /* paccfg/nbxcfg */ + pci_read_config_word(agp_bridge->dev, INTEL_NBXCFG, &temp2); + pci_write_config_word(agp_bridge->dev, INTEL_NBXCFG, + (temp2 & ~(1 << 10)) | (1 << 9) | (1 << 11)); + /* clear any possible error conditions */ + pci_write_config_byte(agp_bridge->dev, INTEL_ERRSTS + 1, 7); + return 0; +} + +static int efficeon_free_gatt_table(void) +{ + int index, freed = 0; + + for (index = 0; index < EFFICEON_L1_SIZE; index++) { + unsigned long page = efficeon_private.l1_table[index]; + if (page) { + efficeon_private.l1_table[index] = 0; + ClearPageReserved(virt_to_page((char *)page)); + free_page(page); + freed++; + } + printk(KERN_DEBUG PFX "efficeon_free_gatt_table(%p, %02x, %08x)\n", + agp_bridge->dev, EFFICEON_ATTPAGE, index); + pci_write_config_dword(agp_bridge->dev, + EFFICEON_ATTPAGE, index); + } + printk(KERN_DEBUG PFX "efficeon_free_gatt_table() freed %d pages\n", freed); + return 0; +} + + +/* + * Since we don't need contigious memory we just try + * to get the gatt table once + */ + +#define GET_PAGE_DIR_OFF(addr) (addr >> 22) +#define GET_PAGE_DIR_IDX(addr) (GET_PAGE_DIR_OFF(addr) - \ + GET_PAGE_DIR_OFF(agp_bridge->gart_bus_addr)) +#define GET_GATT_OFF(addr) ((addr & 0x003ff000) >> 12) +#undef GET_GATT +#define GET_GATT(addr) (efficeon_private.gatt_pages[\ + GET_PAGE_DIR_IDX(addr)]->remapped) + +static int efficeon_create_gatt_table(void) +{ + int index; + const int pati = EFFICEON_PATI; + const int present = EFFICEON_PRESENT; + const int clflush_chunk = ((cpuid_ebx(1) >> 8) & 0xff) << 3; + int num_entries, l1_pages; + + num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries; + + printk(KERN_DEBUG PFX "efficeon_create_gatt_table(%d)\n", num_entries); + + /* There are 2^10 PTE pages per PDE page */ + BUG_ON(num_entries & 0x3ff); + l1_pages = num_entries >> 10; + + for (index = 0 ; index < l1_pages ; index++) { + int offset; + unsigned long page; + unsigned long value; + + page = efficeon_private.l1_table[index]; + BUG_ON(page); + + page = get_zeroed_page(GFP_KERNEL); + if (!page) { + efficeon_free_gatt_table(); + return -ENOMEM; + } + SetPageReserved(virt_to_page((char *)page)); + + for (offset = 0; offset < PAGE_SIZE; offset += clflush_chunk) + asm volatile("clflush %0" : : "m" (*(char *)(page+offset))); + + efficeon_private.l1_table[index] = page; + + value = __pa(page) | pati | present | index; + + pci_write_config_dword(agp_bridge->dev, + EFFICEON_ATTPAGE, value); + } + + return 0; +} + +static int efficeon_insert_memory(struct agp_memory * mem, off_t pg_start, int type) +{ + int i, count = mem->page_count, num_entries; + unsigned int *page, *last_page; + const int clflush_chunk = ((cpuid_ebx(1) >> 8) & 0xff) << 3; + const unsigned long clflush_mask = ~(clflush_chunk-1); + + printk(KERN_DEBUG PFX "efficeon_insert_memory(%lx, %d)\n", pg_start, count); + + num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries; + if ((pg_start + mem->page_count) > num_entries) + return -EINVAL; + if (type != 0 || mem->type != 0) + return -EINVAL; + + if (mem->is_flushed == FALSE) { + global_cache_flush(); + mem->is_flushed = TRUE; + } + + last_page = NULL; + for (i = 0; i < count; i++) { + int index = pg_start + i; + unsigned long insert = mem->memory[i]; + + page = (unsigned int *) efficeon_private.l1_table[index >> 10]; + + if (!page) + continue; + + page += (index & 0x3ff); + *page = insert; + + /* clflush is slow, so don't clflush until we have to */ + if ( last_page && + ((unsigned long)page^(unsigned long)last_page) & clflush_mask ) + asm volatile("clflush %0" : : "m" (*last_page)); + + last_page = page; + } + + if ( last_page ) + asm volatile("clflush %0" : : "m" (*last_page)); + + agp_bridge->driver->tlb_flush(mem); + return 0; +} + +static int efficeon_remove_memory(struct agp_memory * mem, off_t pg_start, int type) +{ + int i, count = mem->page_count, num_entries; + + printk(KERN_DEBUG PFX "efficeon_remove_memory(%lx, %d)\n", pg_start, count); + + num_entries = A_SIZE_LVL2(agp_bridge->current_size)->num_entries; + + if ((pg_start + mem->page_count) > num_entries) + return -EINVAL; + if (type != 0 || mem->type != 0) + return -EINVAL; + + for (i = 0; i < count; i++) { + int index = pg_start + i; + unsigned int *page = (unsigned int *) efficeon_private.l1_table[index >> 10]; + + if (!page) + continue; + page += (index & 0x3ff); + *page = 0; + } + agp_bridge->driver->tlb_flush(mem); + return 0; +} + +/* GATT entry: (physical address | 1) */ +static unsigned long efficeon_mask_memory(unsigned long addr, int type) +{ + /* Memory type is ignored */ + + return addr | agp_bridge->driver->masks[0].mask; +} + +struct agp_bridge_driver efficeon_driver = { + .owner = THIS_MODULE, + .aperture_sizes = efficeon_generic_sizes, + .size_type = LVL2_APER_SIZE, + .num_aperture_sizes = 4, + .configure = efficeon_configure, + .fetch_size = efficeon_fetch_size, + .cleanup = efficeon_cleanup, + .tlb_flush = efficeon_tlbflush, + .mask_memory = efficeon_mask_memory, + .masks = efficeon_generic_masks, + .agp_enable = agp_generic_enable, + .cache_flush = global_cache_flush, + + // Efficeon-specific GATT table setup / populate / teardown + .create_gatt_table = efficeon_create_gatt_table, + .free_gatt_table = efficeon_free_gatt_table, + .insert_memory = efficeon_insert_memory, + .remove_memory = efficeon_remove_memory, + .cant_use_aperture = 0, // 1 might be faster? + + // Generic + .alloc_by_type = agp_generic_alloc_by_type, + .free_by_type = agp_generic_free_by_type, + .agp_alloc_page = agp_generic_alloc_page, + .agp_destroy_page = agp_generic_destroy_page, +}; + + +static int agp_efficeon_resume(struct pci_dev *pdev) +{ + printk(KERN_DEBUG PFX "agp_efficeon_resume()\n"); + return efficeon_configure(); +} + +static int __devinit agp_efficeon_probe(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + struct agp_bridge_data *bridge; + u8 cap_ptr; + struct resource *r; + + cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); + if (!cap_ptr) + return -ENODEV; + + /* Probe for Efficeon controller */ + if (pdev->device != PCI_DEVICE_ID_EFFICEON) { + printk(KERN_ERR PFX "Unsupported Efficeon chipset (device id: %04x)\n", + pdev->device); + return -ENODEV; + } + + printk(KERN_INFO PFX "Detected Transmeta Efficeon TM8000 series chipset\n"); + + bridge = agp_alloc_bridge(); + if (!bridge) + return -ENOMEM; + + bridge->driver = &efficeon_driver; + bridge->dev = pdev; + bridge->capndx = cap_ptr; + + /* + * The following fixes the case where the BIOS has "forgotten" to + * provide an address range for the GART. + * 20030610 - hamish@zot.org + */ + r = &pdev->resource[0]; + if (!r->start && r->end) { + if(pci_assign_resource(pdev, 0)) { + printk(KERN_ERR PFX "could not assign resource 0\n"); + return (-ENODEV); + } + } + + /* + * If the device has not been properly setup, the following will catch + * the problem and should stop the system from crashing. + * 20030610 - hamish@zot.org + */ + if (pci_enable_device(pdev)) { + printk(KERN_ERR PFX "Unable to Enable PCI device\n"); + return (-ENODEV); + } + + /* Fill in the mode register */ + if (cap_ptr) { + pci_read_config_dword(pdev, + bridge->capndx+PCI_AGP_STATUS, + &bridge->mode); + } + + pci_set_drvdata(pdev, bridge); + return agp_add_bridge(bridge); +} + +static void __devexit agp_efficeon_remove(struct pci_dev *pdev) +{ + struct agp_bridge_data *bridge = pci_get_drvdata(pdev); + + agp_remove_bridge(bridge); + agp_put_bridge(bridge); +} + +static int agp_efficeon_suspend(struct pci_dev *dev, u32 state) +{ + return 0; +} + + +static struct pci_device_id agp_efficeon_pci_table[] = { + { + .class = (PCI_CLASS_BRIDGE_HOST << 8), + .class_mask = ~0, + .vendor = PCI_VENDOR_ID_TRANSMETA, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + }, + { } +}; + +MODULE_DEVICE_TABLE(pci, agp_efficeon_pci_table); + +static struct pci_driver agp_efficeon_pci_driver = { + .name = "agpgart-efficeon", + .id_table = agp_efficeon_pci_table, + .probe = agp_efficeon_probe, + .remove = agp_efficeon_remove, + .suspend = agp_efficeon_suspend, + .resume = agp_efficeon_resume, +}; + +static int __init agp_efficeon_init(void) +{ + static int agp_initialised=0; + + if (agp_initialised == 1) + return 0; + agp_initialised=1; + + return pci_module_init(&agp_efficeon_pci_driver); +} + +static void __exit agp_efficeon_cleanup(void) +{ + pci_unregister_driver(&agp_efficeon_pci_driver); +} + +module_init(agp_efficeon_init); +module_exit(agp_efficeon_cleanup); + +MODULE_AUTHOR("Carlos Puchol "); +MODULE_LICENSE("GPL and additional rights"); diff -Nru a/drivers/char/ftape/compressor/zftape-compress.c b/drivers/char/ftape/compressor/zftape-compress.c --- a/drivers/char/ftape/compressor/zftape-compress.c Thu Feb 19 23:44:27 2004 +++ b/drivers/char/ftape/compressor/zftape-compress.c Thu Feb 19 23:44:27 2004 @@ -60,8 +60,6 @@ /* local variables */ -static int keep_module_locked = 1; - static void *zftc_wrk_mem = NULL; static __u8 *zftc_buf = NULL; static void *zftc_scratch_buf = NULL; @@ -268,10 +266,6 @@ static void zftc_lock(void) { - MOD_INC_USE_COUNT; /* sets MOD_VISITED and MOD_USED_ONCE, - * locking is done with can_unload() - */ - keep_module_locked = 1; } /* this function is needed for zftape_reset_position in zftape-io.c @@ -282,7 +276,6 @@ memset((void *)&cseg, '\0', sizeof(cseg)); zftc_stats(); - keep_module_locked = 0; TRACE_EXIT; } @@ -555,10 +548,6 @@ int buf_pos_write = pos->seg_byte_pos; TRACE_FUN(ft_t_flow); - keep_module_locked = 1; - MOD_INC_USE_COUNT; /* sets MOD_VISITED and MOD_USED_ONCE, - * locking is done with can_unload() - */ /* Note: we do not unlock the module because * there are some values cached in that `cseg' variable. We * don't don't want to use this information when being @@ -676,10 +665,6 @@ int remaining = to_do; TRACE_FUN(ft_t_flow); - keep_module_locked = 1; - MOD_INC_USE_COUNT; /* sets MOD_VISITED and MOD_USED_ONCE, - * locking is done with can_unload() - */ TRACE_CATCH(zft_allocate_cmpr_mem(volume->blk_sz),); if (pos->seg_byte_pos == 0) { /* new segment just read @@ -800,10 +785,6 @@ int fast_seek_trials = 0; TRACE_FUN(ft_t_flow); - keep_module_locked = 1; - MOD_INC_USE_COUNT; /* sets MOD_VISITED and MOD_USED_ONCE, - * locking is done with can_unload() - */ if (new_block_pos == 0) { pos->seg_pos = volume->start_seg; pos->seg_byte_pos = 0; @@ -1222,31 +1203,7 @@ */ int init_module(void) { - int result; - -#if 0 /* FIXME --RR */ - if (!mod_member_present(&__this_module, can_unload)) - return -EBUSY; - __this_module.can_unload = can_unload; -#endif - result = zft_compressor_init(); - keep_module_locked = 0; - return result; + return zft_compressor_init(); } -/* Called by modules package when removing the driver - */ -void cleanup_module(void) -{ - TRACE_FUN(ft_t_flow); - - if (zft_cmpr_unregister() != &cmpr_ops) { - TRACE(ft_t_info, "failed"); - } else { - TRACE(ft_t_info, "successful"); - } - zftc_cleanup(); - printk(KERN_INFO "zft-compressor successfully unloaded.\n"); - TRACE_EXIT; -} #endif /* MODULE */ diff -Nru a/drivers/char/genrtc.c b/drivers/char/genrtc.c --- a/drivers/char/genrtc.c Thu Feb 19 23:44:28 2004 +++ b/drivers/char/genrtc.c Thu Feb 19 23:44:28 2004 @@ -523,4 +523,4 @@ MODULE_AUTHOR("Richard Zidlicky"); MODULE_LICENSE("GPL"); - +MODULE_ALIAS_MISCDEV(RTC_MINOR); diff -Nru a/drivers/char/ip2/ip2.h b/drivers/char/ip2/ip2.h --- a/drivers/char/ip2/ip2.h Thu Feb 19 23:44:24 2004 +++ b/drivers/char/ip2/ip2.h Thu Feb 19 23:44:24 2004 @@ -59,7 +59,7 @@ * console warning. * When the driver is loaded as a module these setting can be overridden on the - * modprobe command line or on an option line in /etc/modules.conf. + * modprobe command line or on an option line in /etc/modprobe.conf. * If the driver is built-in the configuration must be * set here for ISA cards and address set to 1 and 2 for PCI and EISA. * @@ -80,7 +80,7 @@ /* this structure is zeroed out because the suggested method is to configure * the driver as a module, set up the parameters with an options line in - * /etc/modules.conf and load with modprobe, kerneld or kmod, the kernel + * /etc/modprobe.conf and load with modprobe or kmod, the kernel * module loader */ diff -Nru a/drivers/char/isicom.c b/drivers/char/isicom.c --- a/drivers/char/isicom.c Thu Feb 19 23:44:22 2004 +++ b/drivers/char/isicom.c Thu Feb 19 23:44:22 2004 @@ -29,7 +29,7 @@ * You can find the original tools for this direct from Multitech * ftp://ftp.multitech.com/ISI-Cards/ * - * Having installed the cards the module options (/etc/modules.conf) + * Having installed the cards the module options (/etc/modprobe.conf) * * options isicom io=card1,card2,card3,card4 irq=card1,card2,card3,card4 * diff -Nru a/drivers/char/mem.c b/drivers/char/mem.c --- a/drivers/char/mem.c Thu Feb 19 23:44:25 2004 +++ b/drivers/char/mem.c Thu Feb 19 23:44:25 2004 @@ -11,8 +11,6 @@ #include #include #include -#include -#include #include #include #include diff -Nru a/drivers/char/raw.c b/drivers/char/raw.c --- a/drivers/char/raw.c Thu Feb 19 23:44:26 2004 +++ b/drivers/char/raw.c Thu Feb 19 23:44:26 2004 @@ -60,7 +60,7 @@ if (!bdev) goto out; igrab(bdev->bd_inode); - err = blkdev_get(bdev, filp->f_mode, 0, BDEV_RAW); + err = blkdev_get(bdev, filp->f_mode, 0); if (err) goto out; err = bd_claim(bdev, raw_open); @@ -81,7 +81,7 @@ out2: bd_release(bdev); out1: - blkdev_put(bdev, BDEV_RAW); + blkdev_put(bdev); out: up(&raw_mutex); return err; @@ -106,7 +106,7 @@ up(&raw_mutex); bd_release(bdev); - blkdev_put(bdev, BDEV_RAW); + blkdev_put(bdev); return 0; } diff -Nru a/drivers/char/sn_serial.c b/drivers/char/sn_serial.c --- a/drivers/char/sn_serial.c Thu Feb 19 23:44:28 2004 +++ b/drivers/char/sn_serial.c Thu Feb 19 23:44:28 2004 @@ -259,7 +259,7 @@ va_list args; va_start(args, fmt); - printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args); + printed_len = vscnprintf(printk_buf, sizeof(printk_buf), fmt, args); early_printk_sn_sal(printk_buf, printed_len); va_end(args); return printed_len; diff -Nru a/drivers/char/viocons.c b/drivers/char/viocons.c --- a/drivers/char/viocons.c Thu Feb 19 23:44:22 2004 +++ b/drivers/char/viocons.c Thu Feb 19 23:44:22 2004 @@ -149,7 +149,7 @@ spin_lock_irqsave(&consoleloglock, flags); va_start(args, fmt); - i = vsnprintf(buf, sizeof(buf) - 1, fmt, args); + i = vscnprintf(buf, sizeof(buf) - 1, fmt, args); va_end(args); buf[i++] = '\r'; HvCall_writeLogBuffer(buf, i); diff -Nru a/drivers/char/vt.c b/drivers/char/vt.c --- a/drivers/char/vt.c Thu Feb 19 23:44:27 2004 +++ b/drivers/char/vt.c Thu Feb 19 23:44:27 2004 @@ -1883,14 +1883,24 @@ int c, tc, ok, n = 0, draw_x = -1; unsigned int currcons; unsigned long draw_from = 0, draw_to = 0; - struct vt_struct *vt = (struct vt_struct *)tty->driver_data; + struct vt_struct *vt; u16 himask, charmask; const unsigned char *orig_buf = NULL; int orig_count; if (in_interrupt()) return count; - + + might_sleep(); + + acquire_console_sem(); + vt = (struct vt_struct *)tty->driver_data; + if (vt == NULL) { + printk(KERN_ERR "vt: argh, driver_data is NULL !\n"); + release_console_sem(); + return 0; + } + currcons = vt->vc_num; if (!vc_cons_allocated(currcons)) { /* could this happen? */ @@ -1899,13 +1909,16 @@ error = 1; printk("con_write: tty %d not allocated\n", currcons+1); } + release_console_sem(); return 0; } + release_console_sem(); orig_buf = buf; orig_count = count; if (from_user) { + down(&con_buf_sem); again: @@ -1929,6 +1942,13 @@ acquire_console_sem(); + vt = (struct vt_struct *)tty->driver_data; + if (vt == NULL) { + printk(KERN_ERR "vt: argh, driver_data _became_ NULL !\n"); + release_console_sem(); + goto out; + } + himask = hi_font_mask; charmask = himask ? 0x1ff : 0xff; @@ -2442,14 +2462,16 @@ acquire_console_sem(); i = vc_allocate(currcons); - release_console_sem(); - if (i) + if (i) { + release_console_sem(); return i; - + } vt_cons[currcons]->vc_num = currcons; tty->driver_data = vt_cons[currcons]; vc_cons[currcons].d->vc_tty = tty; + release_console_sem(); + if (!tty->winsize.ws_row && !tty->winsize.ws_col) { tty->winsize.ws_row = video_num_lines; tty->winsize.ws_col = video_num_columns; @@ -2467,10 +2489,12 @@ return; vcs_remove_devfs(tty); + acquire_console_sem(); vt = (struct vt_struct*)tty->driver_data; if (vt) vc_cons[vt->vc_num].d->vc_tty = NULL; tty->driver_data = 0; + release_console_sem(); } static void vc_init(unsigned int currcons, unsigned int rows, unsigned int cols, int do_clear) diff -Nru a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c --- a/drivers/cpufreq/cpufreq.c Thu Feb 19 23:44:23 2004 +++ b/drivers/cpufreq/cpufreq.c Thu Feb 19 23:44:23 2004 @@ -198,7 +198,7 @@ else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) return sprintf(buf, "performance\n"); else if (policy->governor) - return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name); + return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name); return -EINVAL; } @@ -234,7 +234,7 @@ */ static ssize_t show_scaling_driver (struct cpufreq_policy * policy, char *buf) { - return snprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name); + return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name); } /** @@ -254,7 +254,7 @@ list_for_each_entry(t, &cpufreq_governor_list, governor_list) { if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2))) goto out; - i += snprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name); + i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name); } out: i += sprintf(&buf[i], "\n"); diff -Nru a/drivers/cpufreq/proc_intf.c b/drivers/cpufreq/proc_intf.c --- a/drivers/cpufreq/proc_intf.c Thu Feb 19 23:44:23 2004 +++ b/drivers/cpufreq/proc_intf.c Thu Feb 19 23:44:23 2004 @@ -139,7 +139,7 @@ break; } } else - p += snprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name); + p += scnprintf(p, CPUFREQ_NAME_LEN, "%s\n", policy.governor->name); } end: len = (p - page); diff -Nru a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c --- a/drivers/ide/ide-cd.c Thu Feb 19 23:44:25 2004 +++ b/drivers/ide/ide-cd.c Thu Feb 19 23:44:25 2004 @@ -3517,7 +3517,7 @@ printk("%s: Can't allocate a cdrom structure\n", drive->name); goto failed; } - if (ide_register_subdriver(drive, &ide_cdrom_driver, IDE_SUBDRIVER_VERSION)) { + if (ide_register_subdriver(drive, &ide_cdrom_driver)) { printk("%s: Failed to register the driver with ide.c\n", drive->name); kfree(info); diff -Nru a/drivers/ide/ide-default.c b/drivers/ide/ide-default.c --- a/drivers/ide/ide-default.c Thu Feb 19 23:44:28 2004 +++ b/drivers/ide/ide-default.c Thu Feb 19 23:44:28 2004 @@ -51,8 +51,7 @@ static int idedefault_attach (ide_drive_t *drive) { - if (ide_register_subdriver(drive, - &idedefault_driver, IDE_SUBDRIVER_VERSION)) { + if (ide_register_subdriver(drive, &idedefault_driver)) { printk(KERN_ERR "ide-default: %s: Failed to register the " "driver with ide.c\n", drive->name); return 1; diff -Nru a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c --- a/drivers/ide/ide-disk.c Thu Feb 19 23:44:24 2004 +++ b/drivers/ide/ide-disk.c Thu Feb 19 23:44:24 2004 @@ -834,13 +834,6 @@ ide_end_drive_cmd(drive, stat, err); return ide_stopped; } -#if 0 - else if (rq->flags & REQ_DRIVE_TASKFILE) { - rq->errors = 1; - ide_end_taskfile(drive, stat, err); - return ide_stopped; - } -#endif #ifdef CONFIG_IDE_TASKFILE_IO /* make rq completion pointers new submission pointers */ blk_rq_prep_restart(rq); @@ -1700,7 +1693,6 @@ .busy = 0, .supports_dsc_overlap = 0, .cleanup = idedisk_cleanup, - .flushcache = do_idedisk_flushcache, .do_request = ide_do_rw_disk, .sense = idedisk_dump_status, .error = idedisk_error, @@ -1829,7 +1821,7 @@ if (drive->media != ide_disk) goto failed; - if (ide_register_subdriver (drive, &idedisk_driver, IDE_SUBDRIVER_VERSION)) { + if (ide_register_subdriver(drive, &idedisk_driver)) { printk (KERN_ERR "ide-disk: %s: Failed to register the driver with ide.c\n", drive->name); goto failed; } diff -Nru a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c --- a/drivers/ide/ide-floppy.c Thu Feb 19 23:44:25 2004 +++ b/drivers/ide/ide-floppy.c Thu Feb 19 23:44:25 2004 @@ -2055,7 +2055,7 @@ printk (KERN_ERR "ide-floppy: %s: Can't allocate a floppy structure\n", drive->name); goto failed; } - if (ide_register_subdriver (drive, &idefloppy_driver, IDE_SUBDRIVER_VERSION)) { + if (ide_register_subdriver(drive, &idefloppy_driver)) { printk (KERN_ERR "ide-floppy: %s: Failed to register the driver with ide.c\n", drive->name); kfree (floppy); goto failed; diff -Nru a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c --- a/drivers/ide/ide-io.c Thu Feb 19 23:44:27 2004 +++ b/drivers/ide/ide-io.c Thu Feb 19 23:44:27 2004 @@ -300,7 +300,6 @@ if (rq->flags & REQ_DRIVE_TASKFILE) { rq->errors = 1; ide_end_drive_cmd(drive, stat, err); -// ide_end_taskfile(drive, stat, err); return ide_stopped; } @@ -387,7 +386,6 @@ if (rq->flags & REQ_DRIVE_TASKFILE) { rq->errors = 1; ide_end_drive_cmd(drive, BUSY_STAT, 0); -// ide_end_taskfile(drive, BUSY_STAT, 0); return ide_stopped; } diff -Nru a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c --- a/drivers/ide/ide-probe.c Thu Feb 19 23:44:26 2004 +++ b/drivers/ide/ide-probe.c Thu Feb 19 23:44:26 2004 @@ -237,27 +237,9 @@ */ if (id->config & (1<<7)) drive->removable = 1; - - /* - * Prevent long system lockup probing later for non-existant - * slave drive if the hwif is actually a flash memory card of - * some variety: - */ - drive->is_flash = 0; - if (drive_is_flashcard(drive)) { -#if 0 - /* The new IDE adapter widgets don't follow this heuristic - so we must nowdays just bite the bullet and take the - probe hit */ - ide_drive_t *mate = &hwif->drives[1^drive->select.b.unit]; - ide_drive_t *mate = &hwif->drives[1^drive->select.b.unit]; - if (!mate->ata_flash) { - mate->present = 0; - mate->noprobe = 1; - } -#endif + + if (drive_is_flashcard(drive)) drive->is_flash = 1; - } drive->media = ide_disk; printk("%s DISK drive\n", (drive->is_flash) ? "CFA" : "ATA" ); QUIRK_LIST(drive); diff -Nru a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c --- a/drivers/ide/ide-proc.c Thu Feb 19 23:44:25 2004 +++ b/drivers/ide/ide-proc.c Thu Feb 19 23:44:25 2004 @@ -109,17 +109,6 @@ return -EINVAL; } -static struct proc_dir_entry * proc_ide_root = NULL; - -#ifdef CONFIG_BLK_DEV_IDEPCI -#include -/* - * This is the list of registered PCI chipset driver data structures. - */ -static ide_pci_host_proc_t * ide_pci_host_proc_list; - -#endif /* CONFIG_BLK_DEV_IDEPCI */ - static int proc_ide_write_config (struct file *file, const char *buffer, unsigned long count, void *data) { @@ -787,27 +776,16 @@ } } +EXPORT_SYMBOL(create_proc_ide_interfaces); + #ifdef CONFIG_BLK_DEV_IDEPCI -void ide_pci_register_host_proc (ide_pci_host_proc_t *p) +void ide_pci_create_host_proc(const char *name, get_info_t *get_info) { - ide_pci_host_proc_t *tmp; - - if (!p) return; - p->next = NULL; - p->set = 1; - if (ide_pci_host_proc_list) { - tmp = ide_pci_host_proc_list; - while (tmp->next) tmp = tmp->next; - tmp->next = p; - } else - ide_pci_host_proc_list = p; + create_proc_info_entry(name, 0, proc_ide_root, get_info); } -EXPORT_SYMBOL(ide_pci_register_host_proc); - -#endif /* CONFIG_BLK_DEV_IDEPCI */ - -EXPORT_SYMBOL(create_proc_ide_interfaces); +EXPORT_SYMBOL_GPL(ide_pci_create_host_proc); +#endif void destroy_proc_ide_interfaces(void) { @@ -846,45 +824,22 @@ void proc_ide_create(void) { -#ifdef CONFIG_BLK_DEV_IDEPCI - ide_pci_host_proc_t *p = ide_pci_host_proc_list; -#endif /* CONFIG_BLK_DEV_IDEPCI */ struct proc_dir_entry *entry; - proc_ide_root = proc_mkdir("ide", 0); - if (!proc_ide_root) return; + + if (!proc_ide_root) + return; create_proc_ide_interfaces(); entry = create_proc_entry("drivers", 0, proc_ide_root); if (entry) entry->proc_fops = &ide_drivers_operations; - -#ifdef CONFIG_BLK_DEV_IDEPCI - while (p != NULL) - { - if (p->name != NULL && p->set == 1 && p->get_info != NULL) - { - p->parent = proc_ide_root; - create_proc_info_entry(p->name, 0, p->parent, p->get_info); - p->set = 2; - } - p = p->next; - } -#endif /* CONFIG_BLK_DEV_IDEPCI */ } EXPORT_SYMBOL(proc_ide_create); void proc_ide_destroy(void) { -#ifdef CONFIG_BLK_DEV_IDEPCI - ide_pci_host_proc_t *p; - - for (p = ide_pci_host_proc_list; p; p = p->next) { - if (p->set == 2) - remove_proc_entry(p->name, p->parent); - } -#endif /* CONFIG_BLK_DEV_IDEPCI */ remove_proc_entry("ide/drivers", proc_ide_root); destroy_proc_ide_interfaces(); remove_proc_entry("ide", 0); diff -Nru a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c --- a/drivers/ide/ide-tape.c Thu Feb 19 23:44:24 2004 +++ b/drivers/ide/ide-tape.c Thu Feb 19 23:44:24 2004 @@ -451,18 +451,6 @@ #include /* - * OnStream support - */ -#define ONSTREAM_DEBUG (0) -#define OS_CONFIG_PARTITION (0xff) -#define OS_DATA_PARTITION (0) -#define OS_PARTITION_VERSION (1) -#define OS_EW 300 -#define OS_ADR_MINREV 2 - -#define OS_DATA_STARTFRAME1 20 -#define OS_DATA_ENDFRAME1 2980 -/* * partition */ typedef struct os_partition_s { @@ -498,87 +486,6 @@ os_dat_entry_t dat_list[16]; } os_dat_t; -/* - * Frame types - */ -#define OS_FRAME_TYPE_FILL (0) -#define OS_FRAME_TYPE_EOD (1 << 0) -#define OS_FRAME_TYPE_MARKER (1 << 1) -#define OS_FRAME_TYPE_HEADER (1 << 3) -#define OS_FRAME_TYPE_DATA (1 << 7) - -/* - * AUX - */ -typedef struct os_aux_s { - __u32 format_id; /* hardware compatibility AUX is based on */ - char application_sig[4]; /* driver used to write this media */ - __u32 hdwr; /* reserved */ - __u32 update_frame_cntr; /* for configuration frame */ - __u8 frame_type; - __u8 frame_type_reserved; - __u8 reserved_18_19[2]; - os_partition_t partition; - __u8 reserved_36_43[8]; - __u32 frame_seq_num; - __u32 logical_blk_num_high; - __u32 logical_blk_num; - os_dat_t dat; - __u8 reserved188_191[4]; - __u32 filemark_cnt; - __u32 phys_fm; - __u32 last_mark_addr; - __u8 reserved204_223[20]; - - /* - * __u8 app_specific[32]; - * - * Linux specific fields: - */ - __u32 next_mark_addr; /* when known, points to next marker */ - __u8 linux_specific[28]; - - __u8 reserved_256_511[256]; -} os_aux_t; - -typedef struct os_header_s { - char ident_str[8]; - __u8 major_rev; - __u8 minor_rev; - __u8 reserved10_15[6]; - __u8 par_num; - __u8 reserved1_3[3]; - os_partition_t partition; -} os_header_t; - -/* - * OnStream Tape Parameters Page - */ -typedef struct { - unsigned page_code :6; /* Page code - Should be 0x2b */ - unsigned reserved1_6 :1; - unsigned ps :1; - __u8 reserved2; - __u8 density; /* kbpi */ - __u8 reserved3,reserved4; - __u16 segtrk; /* segment of per track */ - __u16 trks; /* tracks per tape */ - __u8 reserved5,reserved6,reserved7,reserved8,reserved9,reserved10; -} onstream_tape_paramtr_page_t; - -/* - * OnStream ADRL frame - */ -#define OS_FRAME_SIZE (32 * 1024 + 512) -#define OS_DATA_SIZE (32 * 1024) -#define OS_AUX_SIZE (512) - -/* - * internal error codes for onstream - */ -#define OS_PART_ERROR 2 -#define OS_WRITE_ERROR 1 - #include /**************************** Tunable parameters *****************************/ @@ -842,7 +749,6 @@ struct request rq; /* The corresponding request */ struct idetape_bh *bh; /* The data buffers */ struct idetape_stage_s *next; /* Pointer to the next stage */ - os_aux_t *aux; /* OnStream aux ptr */ } idetape_stage_t; /* @@ -1037,52 +943,6 @@ char write_prot; /* - * OnStream flags - */ - /* the tape is an OnStream tape */ - int onstream; - /* OnStream raw access (32.5KB block size) */ - int raw; - /* current number of frames in internal buffer */ - int cur_frames; - /* max number of frames in internal buffer */ - int max_frames; - /* logical block number */ - int logical_blk_num; - /* write pass counter */ - __u16 wrt_pass_cntr; - /* update frame counter */ - __u32 update_frame_cntr; - struct completion *waiting; - /* write error recovery active */ - int onstream_write_error; - /* header frame verified ok */ - int header_ok; - /* reading linux-specific media */ - int linux_media; - int linux_media_version; - /* application signature */ - char application_sig[5]; - int filemark_cnt; - int first_mark_addr; - int last_mark_addr; - int eod_frame_addr; - unsigned long cmd_start_time; - unsigned long max_cmd_time; - unsigned capacity; - - /* - * Optimize the number of "buffer filling" - * mode sense commands. - */ - /* last time in which we issued fill cmd */ - unsigned long last_buffer_fill; - /* buffer fill command requested */ - int req_buffer_fill; - int writes_since_buffer_fill; - int reads_since_buffer_fill; - - /* * Limit the number of times a request can * be postponed, to avoid an infinite postpone * deadlock. @@ -1468,7 +1328,6 @@ * Function declarations * */ -static void idetape_onstream_mode_sense_tape_parameter_page(ide_drive_t *drive, int debug); static int idetape_chrdev_release (struct inode *inode, struct file *filp); static void idetape_write_release (ide_drive_t *drive, unsigned int minor); @@ -1659,13 +1518,6 @@ #endif /* IDETAPE_DEBUG_LOG_VERBOSE */ #endif /* IDETAPE_DEBUG_LOG */ - if (tape->onstream && result->sense_key == 2 && - result->asc == 0x53 && result->ascq == 2) { - clear_bit(PC_DMA_ERROR, &pc->flags); - ide_stall_queue(drive, HZ / 2); - return; - } - /* * Correct pc->actually_transferred by asking the tape. */ @@ -1706,7 +1558,7 @@ set_bit(PC_ABORT, &pc->flags); } if (!test_bit(PC_ABORT, &pc->flags) && - (tape->onstream || pc->actually_transferred)) + pc->actually_transferred) pc->retries = IDETAPE_MAX_PC_RETRIES + 1; } } @@ -1868,11 +1720,6 @@ int error; int remove_stage = 0; idetape_stage_t *active_stage; -#if ONSTREAM_DEBUG - idetape_stage_t *stage; - os_aux_t *aux; - unsigned char *p; -#endif #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 4) @@ -1897,50 +1744,11 @@ tape->active_data_request = NULL; tape->nr_pending_stages--; if (rq->cmd[0] & REQ_IDETAPE_WRITE) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) { - if (tape->onstream) { - stage = tape->first_stage; - aux = stage->aux; - p = stage->bh->b_data; - if (ntohl(aux->logical_blk_num) < 11300 && ntohl(aux->logical_blk_num) > 11100) - printk(KERN_INFO "ide-tape: finished writing logical blk %u (data %x %x %x %x)\n", ntohl(aux->logical_blk_num), *p++, *p++, *p++, *p++); - } - } -#endif - if (tape->onstream && !tape->raw) { - if (tape->first_frame_position == OS_DATA_ENDFRAME1) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk("ide-tape: %s: skipping over config partition.\n", tape->name); -#endif - tape->onstream_write_error = OS_PART_ERROR; - if (tape->waiting) { - rq->waiting = NULL; - complete(tape->waiting); - } - } - } remove_stage = 1; if (error) { set_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); if (error == IDETAPE_ERROR_EOD) idetape_abort_pipeline(drive, active_stage); - if (tape->onstream && !tape->raw && - error == IDETAPE_ERROR_GENERAL && - tape->sense.sense_key == 3) { - clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); - printk(KERN_ERR "ide-tape: %s: write error, enabling error recovery\n", tape->name); - tape->onstream_write_error = OS_WRITE_ERROR; - remove_stage = 0; - tape->nr_pending_stages++; - tape->next_stage = tape->first_stage; - rq->current_nr_sectors = rq->nr_sectors; - if (tape->waiting) { - rq->waiting = NULL; - complete(tape->waiting); - } - } } } else if (rq->cmd[0] & REQ_IDETAPE_READ) { if (error == IDETAPE_ERROR_EOD) { @@ -1948,7 +1756,7 @@ idetape_abort_pipeline(drive, active_stage); } } - if (tape->next_stage != NULL && !tape->onstream_write_error) { + if (tape->next_stage != NULL) { idetape_active_next_stage(drive); /* @@ -1956,7 +1764,6 @@ */ (void) ide_do_drive_cmd(drive, tape->active_data_request, ide_end); } else if (!error) { - if (!tape->onstream) idetape_increase_max_pipeline_stages(drive); } } @@ -2089,7 +1896,6 @@ idetape_pc_t *pc = tape->pc; unsigned int temp; - unsigned long cmd_time; #if SIMULATE_ERRORS static int error_sim_count = 0; #endif @@ -2139,8 +1945,6 @@ /* No more interrupts */ if (!status.b.drq) { - cmd_time = (jiffies - tape->cmd_start_time) * 1000 / HZ; - tape->max_cmd_time = max(cmd_time, tape->max_cmd_time); #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) printk(KERN_INFO "ide-tape: Packet command completed, %d bytes transferred\n", pc->actually_transferred); @@ -2178,8 +1982,7 @@ return idetape_retry_pc(drive); } pc->error = 0; - if (!tape->onstream && - test_bit(PC_WAIT_FOR_DSC, &pc->flags) && + if (test_bit(PC_WAIT_FOR_DSC, &pc->flags) && !status.b.dsc) { /* Media access command */ tape->dsc_polling_start = jiffies; @@ -2333,7 +2136,6 @@ "a packet command\n"); return ide_do_reset(drive); } - tape->cmd_start_time = jiffies; /* Set the interrupt routine */ ide_set_handler(drive, &idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); #ifdef CONFIG_BLK_DEV_IDEDMA @@ -2383,12 +2185,6 @@ tape->name, pc->c[0], tape->sense_key, tape->asc, tape->ascq); - if (tape->onstream && - pc->c[0] == IDETAPE_READ_CMD && - tape->sense_key == 3 && - tape->asc == 0x11) - /* AJN-1: 11 should be 0x11 */ - printk(KERN_ERR "ide-tape: %s: enabling read error recovery\n", tape->name); } /* Giving up */ pc->error = IDETAPE_ERROR_GENERAL; @@ -2482,48 +2278,6 @@ pc->callback = &idetape_pc_callback; } -static ide_startstop_t idetape_onstream_buffer_fill_callback (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - tape->max_frames = tape->pc->buffer[4 + 2]; - tape->cur_frames = tape->pc->buffer[4 + 3]; - if (tape->chrdev_direction == idetape_direction_write) - tape->tape_head = tape->buffer_head - tape->cur_frames; - else - tape->tape_head = tape->buffer_head + tape->cur_frames; - if (tape->tape_head != tape->last_tape_head) { - tape->last_tape_head = tape->tape_head; - tape->tape_still_time_begin = jiffies; - if (tape->tape_still_time > 200) - tape->measure_insert_time = 1; - } - tape->tape_still_time = (jiffies - tape->tape_still_time_begin) * 1000 / HZ; -#if USE_IOTRACE - IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, - tape->tape_head, tape->minor); -#endif -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: buffer fill callback, %d/%d\n", - tape->cur_frames, tape->max_frames); -#endif - idetape_end_request(drive, tape->pc->error ? 0 : 1, 0); - return ide_stopped; -} - -static void idetape_queue_onstream_buffer_fill (ide_drive_t *drive) -{ - idetape_pc_t *pc; - struct request *rq; - - pc = idetape_next_pc_storage(drive); - rq = idetape_next_rq_storage(drive); - idetape_create_mode_sense_cmd(pc, IDETAPE_BUFFER_FILLING_PAGE); - pc->callback = idetape_onstream_buffer_fill_callback; - idetape_queue_pc_head(drive, pc, rq); -} - static void calculate_speeds(ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; @@ -2579,8 +2333,6 @@ idetape_pc_t *pc = tape->pc; atapi_status_t status; - if (tape->onstream) - printk(KERN_INFO "ide-tape: bug: onstream, media_access_finished\n"); status.all = HWIF(drive)->INB(IDE_STATUS_REG); if (status.b.dsc) { if (status.b.check) { @@ -2641,7 +2393,6 @@ static void idetape_create_read_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh) { - struct idetape_bh *p = bh; idetape_init_pc(pc); pc->c[0] = IDETAPE_READ_CMD; put_unaligned(htonl(length), (unsigned int *) &pc->c[1]); @@ -2650,23 +2401,9 @@ pc->bh = bh; atomic_set(&bh->b_count, 0); pc->buffer = NULL; - if (tape->onstream) { - while (p) { - atomic_set(&p->b_count, 0); - p = p->b_reqnext; - } - } - if (!tape->onstream) { - pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; - if (pc->request_transfer == tape->stage_size) - set_bit(PC_DMA_RECOMMENDED, &pc->flags); - } else { - if (length) { - pc->request_transfer = pc->buffer_size = 32768 + 512; - set_bit(PC_DMA_RECOMMENDED, &pc->flags); - } else - pc->request_transfer = 0; - } + pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; + if (pc->request_transfer == tape->stage_size) + set_bit(PC_DMA_RECOMMENDED, &pc->flags); } static void idetape_create_read_buffer_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh) @@ -2692,35 +2429,19 @@ static void idetape_create_write_cmd(idetape_tape_t *tape, idetape_pc_t *pc, unsigned int length, struct idetape_bh *bh) { - struct idetape_bh *p = bh; - idetape_init_pc(pc); pc->c[0] = IDETAPE_WRITE_CMD; put_unaligned(htonl(length), (unsigned int *) &pc->c[1]); pc->c[1] = 1; pc->callback = &idetape_rw_callback; set_bit(PC_WRITING, &pc->flags); - if (tape->onstream) { - while (p) { - atomic_set(&p->b_count, p->b_size); - p = p->b_reqnext; - } - } pc->bh = bh; pc->b_data = bh->b_data; pc->b_count = atomic_read(&bh->b_count); pc->buffer = NULL; - if (!tape->onstream) { - pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; - if (pc->request_transfer == tape->stage_size) - set_bit(PC_DMA_RECOMMENDED, &pc->flags); - } else { - if (length) { - pc->request_transfer = pc->buffer_size = 32768 + 512; - set_bit(PC_DMA_RECOMMENDED, &pc->flags); - } else - pc->request_transfer = 0; - } + pc->request_transfer = pc->buffer_size = length * tape->tape_block_size; + if (pc->request_transfer == tape->stage_size) + set_bit(PC_DMA_RECOMMENDED, &pc->flags); } /* @@ -2782,65 +2503,14 @@ */ status.all = HWIF(drive)->INB(IDE_STATUS_REG); - /* - * The OnStream tape drive doesn't support DSC. Assume - * that DSC is always set. - */ - if (tape->onstream) - status.b.dsc = 1; if (!drive->dsc_overlap && !(rq->cmd[0] & REQ_IDETAPE_PC2)) set_bit(IDETAPE_IGNORE_DSC, &tape->flags); - /* - * For the OnStream tape, check the current status of the tape - * internal buffer using data gathered from the buffer fill - * mode page, and postpone our request, effectively "disconnecting" - * from the IDE bus, in case the buffer is full (writing) or - * empty (reading), and there is a danger that our request will - * hold the IDE bus during actual media access. - */ if (tape->tape_still_time > 100 && tape->tape_still_time < 200) tape->measure_insert_time = 1; - if (tape->req_buffer_fill && - (rq->cmd[0] & (REQ_IDETAPE_WRITE | REQ_IDETAPE_READ))) { - tape->req_buffer_fill = 0; - tape->writes_since_buffer_fill = 0; - tape->reads_since_buffer_fill = 0; - tape->last_buffer_fill = jiffies; - idetape_queue_onstream_buffer_fill(drive); - if (time_after(jiffies, tape->insert_time)) - tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time); - return ide_stopped; - } if (time_after(jiffies, tape->insert_time)) tape->insert_speed = tape->insert_size / 1024 * HZ / (jiffies - tape->insert_time); calculate_speeds(drive); - if (tape->onstream && tape->max_frames && - (((rq->cmd[0] & REQ_IDETAPE_WRITE) && - ( tape->cur_frames == tape->max_frames || - ( tape->speed_control && tape->cur_frames > 5 && - (tape->insert_speed > tape->max_insert_speed || - (0 /* tape->cur_frames > 30 && tape->tape_still_time > 200 */) ) ) ) ) || - ((rq->cmd[0] & REQ_IDETAPE_READ) && - ( tape->cur_frames == 0 || - ( tape->speed_control && (tape->cur_frames < tape->max_frames - 5) && - tape->insert_speed > tape->max_insert_speed ) ) && rq->nr_sectors) ) ) { -#if IDETAPE_DEBUG_LOG - if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: postponing request, " - "cmd %ld, cur %d, max %d\n", - rq->cmd[0], tape->cur_frames, tape->max_frames); -#endif - if (tape->postpone_cnt++ < 500) { - status.b.dsc = 0; - tape->req_buffer_fill = 1; - } -#if ONSTREAM_DEBUG - else if (tape->debug_level >= 4) - printk(KERN_INFO "ide-tape: %s: postpone_cnt %d\n", - tape->name, tape->postpone_cnt); -#endif - } if (!test_and_clear_bit(IDETAPE_IGNORE_DSC, &tape->flags) && !status.b.dsc) { if (postponed_rq == NULL) { @@ -2867,13 +2537,6 @@ IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); #endif tape->postpone_cnt = 0; - tape->reads_since_buffer_fill++; - if (tape->onstream) { - if (tape->cur_frames - tape->reads_since_buffer_fill <= 0) - tape->req_buffer_fill = 1; - if (time_after(jiffies, tape->last_buffer_fill + 5 * HZ / 100)) - tape->req_buffer_fill = 1; - } pc = idetape_next_pc_storage(drive); idetape_create_read_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special); goto out; @@ -2884,14 +2547,6 @@ IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); #endif tape->postpone_cnt = 0; - tape->writes_since_buffer_fill++; - if (tape->onstream) { - if (tape->cur_frames + tape->writes_since_buffer_fill >= tape->max_frames) - tape->req_buffer_fill = 1; - if (time_after(jiffies, tape->last_buffer_fill + 5 * HZ / 100)) - tape->req_buffer_fill = 1; - calculate_speeds(drive); - } pc = idetape_next_pc_storage(drive); idetape_create_write_cmd(tape, pc, rq->current_nr_sectors, (struct idetape_bh *)rq->special); goto out; @@ -2995,8 +2650,6 @@ bh->b_size -= tape->excess_bh_size; if (full) atomic_sub(tape->excess_bh_size, &bh->b_count); - if (tape->onstream) - stage->aux = (os_aux_t *) (bh->b_data + bh->b_size - OS_AUX_SIZE); return stage; abort: __idetape_kfree_stage(stage); @@ -3093,14 +2746,10 @@ static void idetape_switch_buffers (idetape_tape_t *tape, idetape_stage_t *stage) { struct idetape_bh *tmp; - os_aux_t *tmp_aux; tmp = stage->bh; - tmp_aux = stage->aux; stage->bh = tape->merge_stage->bh; - stage->aux = tape->merge_stage->aux; tape->merge_stage->bh = tmp; - tape->merge_stage->aux = tmp_aux; idetape_init_merge_stage(tape); } @@ -3131,68 +2780,6 @@ } /* - * Initialize the OnStream AUX - */ -static void idetape_init_stage (ide_drive_t *drive, idetape_stage_t *stage, int frame_type, int logical_blk_num) -{ - idetape_tape_t *tape = drive->driver_data; - os_aux_t *aux = stage->aux; - os_partition_t *par = &aux->partition; - os_dat_t *dat = &aux->dat; - - if (!tape->onstream || tape->raw) - return; - memset(aux, 0, sizeof(*aux)); - aux->format_id = htonl(0); - memcpy(aux->application_sig, "LIN3", 4); - aux->hdwr = htonl(0); - aux->frame_type = frame_type; - - if (frame_type == OS_FRAME_TYPE_HEADER) { - aux->update_frame_cntr = htonl(tape->update_frame_cntr); - par->partition_num = OS_CONFIG_PARTITION; - par->par_desc_ver = OS_PARTITION_VERSION; - par->wrt_pass_cntr = htons(0xffff); - par->first_frame_addr = htonl(0); - par->last_frame_addr = htonl(0xbb7); /* 2999 */ - aux->frame_seq_num = htonl(0); - aux->logical_blk_num_high = htonl(0); - aux->logical_blk_num = htonl(0); - aux->next_mark_addr = htonl(tape->first_mark_addr); - } else { - aux->update_frame_cntr = htonl(0); - par->partition_num = OS_DATA_PARTITION; - par->par_desc_ver = OS_PARTITION_VERSION; - par->wrt_pass_cntr = htons(tape->wrt_pass_cntr); - par->first_frame_addr = htonl(OS_DATA_STARTFRAME1); - par->last_frame_addr = htonl(tape->capacity); - aux->frame_seq_num = htonl(logical_blk_num); - aux->logical_blk_num_high = htonl(0); - aux->logical_blk_num = htonl(logical_blk_num); - dat->dat_sz = 8; - dat->reserved1 = 0; - dat->entry_cnt = 1; - dat->reserved3 = 0; - if (frame_type == OS_FRAME_TYPE_DATA) - dat->dat_list[0].blk_sz = htonl(32 * 1024); - else - dat->dat_list[0].blk_sz = 0; - dat->dat_list[0].blk_cnt = htons(1); - if (frame_type == OS_FRAME_TYPE_MARKER) - dat->dat_list[0].flags = OS_DAT_FLAGS_MARK; - else - dat->dat_list[0].flags = OS_DAT_FLAGS_DATA; - dat->dat_list[0].reserved = 0; - } - /* shouldn't this be htonl ?? */ - aux->filemark_cnt = ntohl(tape->filemark_cnt); - /* shouldn't this be htonl ?? */ - aux->phys_fm = ntohl(0xffffffff); - /* shouldn't this be htonl ?? */ - aux->last_mark_addr = ntohl(tape->last_mark_addr); -} - -/* * idetape_wait_for_request installs a completion in a pending request * and sleeps until it is serviced. * @@ -3211,11 +2798,9 @@ } #endif /* IDETAPE_DEBUG_BUGS */ rq->waiting = &wait; - tape->waiting = &wait; spin_unlock_irq(&tape->spinlock); wait_for_completion(&wait); /* The stage and its struct request have been deallocated */ - tape->waiting = NULL; spin_lock_irq(&tape->spinlock); } @@ -3269,13 +2854,9 @@ */ static void idetape_create_write_filemark_cmd (ide_drive_t *drive, idetape_pc_t *pc,int write_filemark) { - idetape_tape_t *tape = drive->driver_data; - idetape_init_pc(pc); pc->c[0] = IDETAPE_WRITE_FILEMARK_CMD; - if (tape->onstream) - pc->c[1] = 1; /* Immed bit */ - pc->c[4] = write_filemark; /* not used for OnStream ?? */ + pc->c[4] = write_filemark; set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; } @@ -3318,16 +2899,9 @@ static void idetape_create_load_unload_cmd (ide_drive_t *drive, idetape_pc_t *pc,int cmd) { - idetape_tape_t *tape = drive->driver_data; - idetape_init_pc(pc); pc->c[0] = IDETAPE_LOAD_UNLOAD_CMD; pc->c[4] = cmd; - if (tape->onstream) { - pc->c[1] = 1; - if (cmd == !IDETAPE_LU_LOAD_MASK) - pc->c[4] = 4; - } set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; } @@ -3366,20 +2940,7 @@ static int idetape_queue_pc_tail (ide_drive_t *drive,idetape_pc_t *pc) { - idetape_tape_t *tape = drive->driver_data; - int rc; - - rc = __idetape_queue_pc_tail(drive, pc); - if (rc) - return rc; - if (tape->onstream && test_bit(PC_WAIT_FOR_DSC, &pc->flags)) { - /* AJN-4: Changed from 5 to 10 minutes; - * because retension takes approx. - * 8:20 with Onstream 30GB tape - */ - rc = idetape_wait_ready(drive, 60 * 10 * HZ); - } - return rc; + return __idetape_queue_pc_tail(drive, pc); } static int idetape_flush_tape_buffers (ide_drive_t *drive) @@ -3422,23 +2983,11 @@ static void idetape_create_locate_cmd (ide_drive_t *drive, idetape_pc_t *pc, unsigned int block, u8 partition, int skip) { - idetape_tape_t *tape = drive->driver_data; - idetape_init_pc(pc); pc->c[0] = IDETAPE_LOCATE_CMD; - if (tape->onstream) - pc->c[1] = 1; /* Immediate bit */ - else - pc->c[1] = 2; + pc->c[1] = 2; put_unaligned(htonl(block), (unsigned int *) &pc->c[3]); pc->c[8] = partition; - if (tape->onstream) - /* - * Set SKIP bit. - * In case of write error this will write buffered - * data in the drive to this new position! - */ - pc->c[9] = skip << 7; set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; } @@ -3539,10 +3088,6 @@ cnt = __idetape_discard_read_pipeline(drive); if (restore_position) { position = idetape_read_position(drive); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: address %u, nr_stages %d\n", position, cnt); -#endif seek = position > cnt ? position - cnt : 0; if (idetape_position_tape(drive, seek, 0, 0)) { printk(KERN_INFO "ide-tape: %s: position_tape failed in discard_pipeline()\n", tape->name); @@ -3551,15 +3096,6 @@ } } -static void idetape_update_stats (ide_drive_t *drive) -{ - idetape_pc_t pc; - - idetape_create_mode_sense_cmd(&pc, IDETAPE_BUFFER_FILLING_PAGE); - pc.callback = idetape_onstream_buffer_fill_callback; - (void) idetape_queue_pc_tail(drive, &pc); -} - /* * idetape_queue_rw_tail generates a read/write request for the block * device interface and wait for it to be serviced. @@ -3584,8 +3120,6 @@ rq.special = (void *)bh; rq.sector = tape->first_frame_position; rq.nr_sectors = rq.current_nr_sectors = blocks; - if (tape->onstream) - tape->postpone_cnt = 600; (void) ide_do_drive_cmd(drive, &rq, ide_wait); if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0) @@ -3599,108 +3133,6 @@ } /* - * Read back the drive's internal buffer contents, as a part - * of the write error recovery mechanism for old OnStream - * firmware revisions. - */ -static void idetape_onstream_read_back_buffer (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int frames, i, logical_blk_num; - idetape_stage_t *stage, *first = NULL, *last = NULL; - os_aux_t *aux; - struct request *rq; - unsigned char *p; - unsigned long flags; - - idetape_update_stats(drive); - frames = tape->cur_frames; - logical_blk_num = ntohl(tape->first_stage->aux->logical_blk_num) - frames; - printk(KERN_INFO "ide-tape: %s: reading back %d frames from the drive's internal buffer\n", tape->name, frames); - for (i = 0; i < frames; i++) { - stage = __idetape_kmalloc_stage(tape, 0, 0); - if (!first) - first = stage; - aux = stage->aux; - p = stage->bh->b_data; - idetape_queue_rw_tail(drive, REQ_IDETAPE_READ_BUFFER, tape->capabilities.ctl, stage->bh); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: read back logical block %d, data %x %x %x %x\n", tape->name, logical_blk_num, *p++, *p++, *p++, *p++); -#endif - rq = &stage->rq; - idetape_init_rq(rq, REQ_IDETAPE_WRITE); - rq->sector = tape->first_frame_position; - rq->nr_sectors = rq->current_nr_sectors = tape->capabilities.ctl; - idetape_init_stage(drive, stage, OS_FRAME_TYPE_DATA, logical_blk_num++); - stage->next = NULL; - if (last) - last->next = stage; - last = stage; - } - if (frames) { - spin_lock_irqsave(&tape->spinlock, flags); - last->next = tape->first_stage; - tape->next_stage = tape->first_stage = first; - tape->nr_stages += frames; - tape->nr_pending_stages += frames; - spin_unlock_irqrestore(&tape->spinlock, flags); - } - idetape_update_stats(drive); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: frames left in buffer: %d\n", tape->name, tape->cur_frames); -#endif -} - -/* - * Error recovery algorithm for the OnStream tape. - */ -static void idetape_onstream_write_error_recovery (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned int block; - - if (tape->onstream_write_error == OS_WRITE_ERROR) { - printk(KERN_ERR "ide-tape: %s: onstream_write_error_recovery: detected physical bad block at %u, logical %u first frame %u last_frame %u bufblocks %u stages %u skipping %u frames\n", - tape->name, ntohl(tape->sense.information), tape->logical_blk_num, - tape->first_frame_position, tape->last_frame_position, - tape->blocks_in_buffer, tape->nr_stages, - (ntohl(tape->sense.command_specific) >> 16) & 0xff ); - block = ntohl(tape->sense.information) + ((ntohl(tape->sense.command_specific) >> 16) & 0xff); - idetape_update_stats(drive); - printk(KERN_ERR "ide-tape: %s: relocating %d buffered logical blocks to physical block %u\n", tape->name, tape->cur_frames, block); -#if 0 /* isn't once enough ??? MM */ - idetape_update_stats(drive); -#endif - if (tape->firmware_revision_num >= 106) - idetape_position_tape(drive, block, 0, 1); - else { - idetape_onstream_read_back_buffer(drive); - idetape_position_tape(drive, block, 0, 0); - } -#if 0 /* already done in idetape_position_tape MM */ - idetape_read_position(drive); -#endif -#if ONSTREAM_DEBUG - if (tape->debug_level >= 1) - printk(KERN_ERR "ide-tape: %s: positioning complete, cur_frames %d, pos %d, tape pos %d\n", tape->name, tape->cur_frames, tape->first_frame_position, tape->last_frame_position); -#endif - } else if (tape->onstream_write_error == OS_PART_ERROR) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: %s: skipping over config partition\n", tape->name); -#endif - idetape_flush_tape_buffers(drive); - block = idetape_read_position(drive); - if (block != OS_DATA_ENDFRAME1) - printk(KERN_ERR "ide-tape: warning, current position %d, expected %d\n", block, OS_DATA_ENDFRAME1); - idetape_position_tape(drive, 0xbb8, 0, 0); /* 3000 */ - } - tape->onstream_write_error = 0; -} - -/* * idetape_insert_pipeline_into_queue is used to start servicing the * pipeline stages, starting from tape->next_stage. */ @@ -3711,8 +3143,6 @@ if (tape->next_stage == NULL) return; if (!idetape_pipeline_active(tape)) { - if (tape->onstream_write_error) - idetape_onstream_write_error_recovery(drive); set_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags); idetape_active_next_stage(drive); (void) ide_do_drive_cmd(drive, tape->active_data_request, ide_end); @@ -3729,16 +3159,13 @@ static void idetape_create_rewind_cmd (ide_drive_t *drive, idetape_pc_t *pc) { - idetape_tape_t *tape = drive->driver_data; - idetape_init_pc(pc); pc->c[0] = IDETAPE_REWIND_CMD; - if (tape->onstream) - pc->c[1] = 1; set_bit(PC_WAIT_FOR_DSC, &pc->flags); pc->callback = &idetape_pc_callback; } +#if 0 static void idetape_create_mode_select_cmd (idetape_pc_t *pc, int length) { idetape_init_pc(pc); @@ -3749,6 +3176,7 @@ pc->request_transfer = 255; pc->callback = &idetape_pc_callback; } +#endif static void idetape_create_erase_cmd (idetape_pc_t *pc) { @@ -3769,82 +3197,6 @@ pc->callback = &idetape_pc_callback; } -/* - * Verify that we have the correct tape frame - */ -static int idetape_verify_stage (ide_drive_t *drive, idetape_stage_t *stage, int logical_blk_num, int quiet) -{ - idetape_tape_t *tape = drive->driver_data; - os_aux_t *aux = stage->aux; - os_partition_t *par = &aux->partition; - struct request *rq = &stage->rq; - struct idetape_bh *bh; - - if (!tape->onstream) - return 1; - if (tape->raw) { - if (rq->errors) { - bh = stage->bh; - while (bh) { - memset(bh->b_data, 0, bh->b_size); - bh = bh->b_reqnext; - } - strcpy(stage->bh->b_data, "READ ERROR ON FRAME"); - } - return 1; - } - if (rq->errors == IDETAPE_ERROR_GENERAL) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, read error\n", tape->name, tape->first_frame_position); - return 0; - } - if (rq->errors == IDETAPE_ERROR_EOD) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, eod\n", tape->name, tape->first_frame_position); - return 0; - } - if (ntohl(aux->format_id) != 0) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, format_id %u\n", tape->name, tape->first_frame_position, ntohl(aux->format_id)); - return 0; - } - if (memcmp(aux->application_sig, tape->application_sig, 4) != 0) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, incorrect application signature\n", tape->name, tape->first_frame_position); - return 0; - } - if (aux->frame_type != OS_FRAME_TYPE_DATA && - aux->frame_type != OS_FRAME_TYPE_EOD && - aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, frame type %x\n", tape->name, tape->first_frame_position, aux->frame_type); - return 0; - } - if (par->partition_num != OS_DATA_PARTITION) { - if (!tape->linux_media || tape->linux_media_version != 2) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, partition num %d\n", tape->name, tape->first_frame_position, par->partition_num); - return 0; - } - } - if (par->par_desc_ver != OS_PARTITION_VERSION) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, partition version %d\n", tape->name, tape->first_frame_position, par->par_desc_ver); - return 0; - } - if (ntohs(par->wrt_pass_cntr) != tape->wrt_pass_cntr) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, wrt_pass_cntr %d (expected %d)(logical_blk_num %u)\n", tape->name, tape->first_frame_position, ntohs(par->wrt_pass_cntr), tape->wrt_pass_cntr, ntohl(aux->logical_blk_num)); - return 0; - } - if (aux->frame_seq_num != aux->logical_blk_num) { - printk(KERN_INFO "ide-tape: %s: skipping frame %d, seq != logical\n", tape->name, tape->first_frame_position); - return 0; - } - if (logical_blk_num != -1 && ntohl(aux->logical_blk_num) != logical_blk_num) { - if (!quiet) - printk(KERN_INFO "ide-tape: %s: skipping frame %d, logical_blk_num %u (expected %d)\n", tape->name, tape->first_frame_position, ntohl(aux->logical_blk_num), logical_blk_num); - return 0; - } - if (aux->frame_type == OS_FRAME_TYPE_MARKER) { - rq->errors = IDETAPE_ERROR_FILEMARK; - rq->current_nr_sectors = rq->nr_sectors; - } - return 1; -} - static void idetape_wait_first_stage (ide_drive_t *drive) { idetape_tape_t *tape = drive->driver_data; @@ -3909,8 +3261,6 @@ rq->nr_sectors = rq->current_nr_sectors = blocks; idetape_switch_buffers(tape, new_stage); - idetape_init_stage(drive, new_stage, OS_FRAME_TYPE_DATA, tape->logical_blk_num); - tape->logical_blk_num++; idetape_add_stage_tail(drive, new_stage); tape->pipeline_head++; #if USE_IOTRACE @@ -3924,15 +3274,6 @@ * writing anymore, wait for the pipeline to be full enough * (90%) before starting to service requests, so that we will * be able to keep up with the higher speeds of the tape. - * - * For the OnStream drive, we can query the number of pending - * frames in the drive's internal buffer. As long as the tape - * is still writing, it is better to write frames immediately - * rather than gather them in the pipeline. This will give the - * tape's firmware the ability to sense the current incoming - * data rate more accurately, and since the OnStream tape - * supports variable speeds, it can try to adjust itself to the - * incoming data rate. */ if (!idetape_pipeline_active(tape)) { if (tape->nr_stages >= tape->max_stages * 9 / 10 || @@ -3942,10 +3283,6 @@ tape->insert_size = 0; tape->insert_speed = 0; idetape_insert_pipeline_into_queue(drive); - } else if (tape->onstream) { - idetape_update_stats(drive); - if (tape->cur_frames > 5) - idetape_insert_pipeline_into_queue(drive); } } if (test_and_clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags)) @@ -4052,7 +3389,6 @@ tape->restart_speed_control_req = 0; tape->pipeline_head = 0; - tape->buffer_head = tape->tape_head = tape->cur_frames; tape->controlled_last_pipeline_head = tape->uncontrolled_last_pipeline_head = 0; tape->controlled_previous_pipeline_head = tape->uncontrolled_previous_pipeline_head = 0; tape->pipeline_head_speed = tape->controlled_pipeline_head_speed = 5000; @@ -4084,7 +3420,6 @@ if ((tape->merge_stage = __idetape_kmalloc_stage(tape, 0, 0)) == NULL) return -ENOMEM; tape->chrdev_direction = idetape_direction_read; - tape->logical_blk_num = 0; /* * Issue a read 0 command to ensure that DSC handshake @@ -4126,89 +3461,11 @@ tape->insert_size = 0; tape->insert_speed = 0; idetape_insert_pipeline_into_queue(drive); - } else if (tape->onstream) { - idetape_update_stats(drive); - if (tape->cur_frames < tape->max_frames - 5) - idetape_insert_pipeline_into_queue(drive); } } return 0; } -static int idetape_get_logical_blk (ide_drive_t *drive, int logical_blk_num, int max_stages, int quiet) -{ - idetape_tape_t *tape = drive->driver_data; - unsigned long flags; - int cnt = 0, x, position; - - /* - * Search and wait for the next logical tape block - */ - while (1) { - if (cnt++ > 1000) { /* AJN: was 100 */ - printk(KERN_INFO "ide-tape: %s: couldn't find logical block %d, aborting\n", tape->name, logical_blk_num); - return 0; - } - idetape_initiate_read(drive, max_stages); - if (tape->first_stage == NULL) { - if (tape->onstream) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: %s: first_stage == NULL, pipeline error %ld\n", tape->name, (long)test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags)); -#endif - clear_bit(IDETAPE_PIPELINE_ERROR, &tape->flags); - position = idetape_read_position(drive); - printk(KERN_INFO "ide-tape: %s: blank block detected at %d\n", tape->name, position); - if (position >= 3000 && position < 3080) - /* Why is this check and number ??? MM */ - position += 32; - if (position >= OS_DATA_ENDFRAME1 && - position < 3000) - position = 3000; - else - /* - * compensate for write errors that - * generally skip 80 frames, expect - * around 20 read errors in a row... - */ - position += 60; - if (position >= OS_DATA_ENDFRAME1 && - position < 3000) - position = 3000; - printk(KERN_INFO "ide-tape: %s: positioning tape to block %d\n", tape->name, position); - - /* seems to be needed to correctly position - * at block 3000 MM - */ - if (position == 3000) - idetape_position_tape(drive, 0, 0, 0); - idetape_position_tape(drive, position, 0, 0); - cnt += 40; - continue; - } else - return 0; - } - idetape_wait_first_stage(drive); - if (idetape_verify_stage(drive, tape->first_stage, logical_blk_num, quiet)) - break; - if (tape->first_stage->rq.errors == IDETAPE_ERROR_EOD) - cnt--; - if (idetape_verify_stage(drive, tape->first_stage, -1, quiet)) { - x = ntohl(tape->first_stage->aux->logical_blk_num); - if (x > logical_blk_num) { - printk(KERN_ERR "ide-tape: %s: couldn't find logical block %d, aborting (block %d found)\n", tape->name, logical_blk_num, x); - return 0; - } - } - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head(drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - } - if (tape->onstream) - tape->logical_blk_num = ntohl(tape->first_stage->aux->logical_blk_num); - return 1; -} - /* * idetape_add_chrdev_read_request is called from idetape_chrdev_read * to service a character device read request and add read-ahead @@ -4233,48 +3490,30 @@ return 0; /* - * Wait for the next logical block to be available at the head + * Wait for the next block to be available at the head * of the pipeline */ - if (!idetape_get_logical_blk(drive, tape->logical_blk_num, tape->max_stages, 0)) { - if (tape->onstream) { - set_bit(IDETAPE_READ_ERROR, &tape->flags); - return 0; - } + idetape_initiate_read(drive, tape->max_stages); + if (tape->first_stage == NULL) { if (test_bit(IDETAPE_PIPELINE_ERROR, &tape->flags)) - return 0; + return 0; return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks, tape->merge_stage->bh); } + idetape_wait_first_stage(drive); rq_ptr = &tape->first_stage->rq; bytes_read = tape->tape_block_size * (rq_ptr->nr_sectors - rq_ptr->current_nr_sectors); rq_ptr->nr_sectors = rq_ptr->current_nr_sectors = 0; - if (tape->onstream && !tape->raw && - tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: EOD reached\n", - tape->name); -#endif - return 0; - } if (rq_ptr->errors == IDETAPE_ERROR_EOD) return 0; else { idetape_switch_buffers(tape, tape->first_stage); - if (rq_ptr->errors == IDETAPE_ERROR_GENERAL) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 1) - printk(KERN_INFO "ide-tape: error detected, bytes_read %d\n", bytes_read); -#endif - } if (rq_ptr->errors == IDETAPE_ERROR_FILEMARK) set_bit(IDETAPE_FILEMARK, &tape->flags); spin_lock_irqsave(&tape->spinlock, flags); idetape_remove_stage_head(drive); spin_unlock_irqrestore(&tape->spinlock, flags); - tape->logical_blk_num++; tape->pipeline_head++; #if USE_IOTRACE IO_trace(IO_IDETAPE_FIFO, tape->pipeline_head, tape->buffer_head, tape->tape_head, tape->minor); @@ -4342,8 +3581,8 @@ { int retval; idetape_pc_t pc; - idetape_tape_t *tape = drive->driver_data; #if IDETAPE_DEBUG_LOG + idetape_tape_t *tape = drive->driver_data; if (tape->debug_level >= 2) printk(KERN_INFO "ide-tape: Reached idetape_rewind_tape\n"); #endif /* IDETAPE_DEBUG_LOG */ @@ -4357,7 +3596,6 @@ retval = idetape_queue_pc_tail(drive, &pc); if (retval) return retval; - tape->logical_blk_num = 0; return 0; } @@ -4406,168 +3644,6 @@ set_bit(IDETAPE_IGNORE_DSC, &tape->flags); } -static int idetape_onstream_space_over_filemarks_backward (ide_drive_t *drive,short mt_op,int mt_count) -{ - idetape_tape_t *tape = drive->driver_data; - int cnt = 0; - int last_mark_addr; - unsigned long flags; - - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_bwd\n", tape->name); - return -EIO; - } - while (cnt != mt_count) { - last_mark_addr = ntohl(tape->first_stage->aux->last_mark_addr); - if (last_mark_addr == -1) - return -EIO; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: positioning to last mark at %d\n", last_mark_addr); -#endif - idetape_position_tape(drive, last_mark_addr, 0, 0); - cnt++; - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name); - return -EIO; - } - if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find marker at block %d, not found\n", tape->name, last_mark_addr); - return -EIO; - } - } - if (mt_op == MTBSFM) { - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head(drive); - tape->logical_blk_num++; - spin_unlock_irqrestore(&tape->spinlock, flags); - } - return 0; -} - -/* - * ADRL 1.1 compatible "slow" space filemarks fwd version - * - * Just scans for the filemark sequentially. - */ -static int idetape_onstream_space_over_filemarks_forward_slow (ide_drive_t *drive,short mt_op,int mt_count) -{ - idetape_tape_t *tape = drive->driver_data; - int cnt = 0; - unsigned long flags; - - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd\n", tape->name); - return -EIO; - } - while (1) { - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name); - return -EIO; - } - if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_MARKER) - cnt++; - if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: space_fwd: EOD reached\n", tape->name); -#endif - return -EIO; - } - if (cnt == mt_count) - break; - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head(drive); - spin_unlock_irqrestore(&tape->spinlock, flags); - } - if (mt_op == MTFSF) { - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head(drive); - tape->logical_blk_num++; - spin_unlock_irqrestore(&tape->spinlock, flags); - } - return 0; -} - - -/* - * Fast linux specific version of OnStream FSF - */ -static int idetape_onstream_space_over_filemarks_forward_fast (ide_drive_t *drive,short mt_op,int mt_count) -{ - idetape_tape_t *tape = drive->driver_data; - int cnt = 0, next_mark_addr; - unsigned long flags; - - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd\n", tape->name); - return -EIO; - } - - /* - * Find nearest (usually previous) marker - */ - while (1) { - if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_MARKER) - break; - if (tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: space_fwd: EOD reached\n", tape->name); -#endif - return -EIO; - } - if (ntohl(tape->first_stage->aux->filemark_cnt) == 0) { - if (tape->first_mark_addr == -1) { - printk(KERN_INFO "ide-tape: %s: reverting to slow filemark space\n", tape->name); - return idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count); - } - idetape_position_tape(drive, tape->first_mark_addr, 0, 0); - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks_fwd_fast\n", tape->name); - return -EIO; - } - if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find filemark at %d\n", tape->name, tape->first_mark_addr); - return -EIO; - } - } else { - if (idetape_onstream_space_over_filemarks_backward(drive, MTBSF, 1) < 0) - return -EIO; - mt_count++; - } - } - cnt++; - while (cnt != mt_count) { - next_mark_addr = ntohl(tape->first_stage->aux->next_mark_addr); - if (!next_mark_addr || next_mark_addr > tape->eod_frame_addr) { - printk(KERN_INFO "ide-tape: %s: reverting to slow filemark space\n", tape->name); - return idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count - cnt); -#if ONSTREAM_DEBUG - } else if (tape->debug_level >= 2) { - printk(KERN_INFO "ide-tape: positioning to next mark at %d\n", next_mark_addr); -#endif - } - idetape_position_tape(drive, next_mark_addr, 0, 0); - cnt++; - if (!idetape_get_logical_blk(drive, -1, 10, 0)) { - printk(KERN_INFO "ide-tape: %s: couldn't get logical blk num in space_filemarks\n", tape->name); - return -EIO; - } - if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find marker at block %d, not found\n", tape->name, next_mark_addr); - return -EIO; - } - } - if (mt_op == MTFSF) { - spin_lock_irqsave(&tape->spinlock, flags); - idetape_remove_stage_head(drive); - tape->logical_blk_num++; - spin_unlock_irqrestore(&tape->spinlock, flags); - } - return 0; -} - /* * idetape_space_over_filemarks is now a bit more complicated than just * passing the command to the tape since we may have crossed some @@ -4583,25 +3659,7 @@ idetape_pc_t pc; unsigned long flags; int retval,count=0; - int speed_control; - if (tape->onstream) { - if (tape->raw) - return -EIO; - speed_control = tape->speed_control; - tape->speed_control = 0; - if (mt_op == MTFSF || mt_op == MTFSFM) { - if (tape->linux_media) - retval = idetape_onstream_space_over_filemarks_forward_fast(drive, mt_op, mt_count); - else - retval = idetape_onstream_space_over_filemarks_forward_slow(drive, mt_op, mt_count); - } else - retval = idetape_onstream_space_over_filemarks_backward(drive, mt_op, mt_count); - tape->speed_control = speed_control; - tape->restart_speed_control_req = 1; - return retval; - } - if (mt_count == 0) return 0; if (MTBSF == mt_op || MTBSFM == mt_op) { @@ -4700,10 +3758,6 @@ /* "A request was outside the capabilities of the device." */ return -ENXIO; } - if (tape->onstream && (count != tape->tape_block_size)) { - printk(KERN_ERR "ide-tape: %s: use %d bytes as block size (%Zd used)\n", tape->name, tape->tape_block_size, count); - return -EINVAL; - } #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 3) printk(KERN_INFO "ide-tape: Reached idetape_chrdev_read, count %Zd\n", count); @@ -4753,179 +3807,15 @@ idetape_space_over_filemarks(drive, MTFSF, 1); return 0; } - if (tape->onstream && !actually_read && - test_and_clear_bit(IDETAPE_READ_ERROR, &tape->flags)) { - printk(KERN_ERR "ide-tape: %s: unrecovered read error on " - "logical block number %d, skipping\n", - tape->name, tape->logical_blk_num); - tape->logical_blk_num++; - return -EIO; - } return actually_read; } -static void idetape_update_last_marker (ide_drive_t *drive, int last_mark_addr, int next_mark_addr) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - os_aux_t *aux; - int position; - - if (!tape->onstream || tape->raw) - return; - if (last_mark_addr == -1) - return; - stage = __idetape_kmalloc_stage(tape, 0, 0); - if (stage == NULL) - return; - idetape_flush_tape_buffers(drive); - position = idetape_read_position(drive); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: current position (2) %d, " - "lblk %d\n", position, tape->logical_blk_num); - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: current position (2) " - "tape block %d\n", tape->last_frame_position); -#endif - idetape_position_tape(drive, last_mark_addr, 0, 0); - if (!idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: couldn't read last marker\n", - tape->name); - __idetape_kfree_stage(stage); - idetape_position_tape(drive, position, 0, 0); - return; - } - aux = stage->aux; - if (aux->frame_type != OS_FRAME_TYPE_MARKER) { - printk(KERN_INFO "ide-tape: %s: expected to find marker " - "at addr %d\n", tape->name, last_mark_addr); - __idetape_kfree_stage(stage); - idetape_position_tape(drive, position, 0, 0); - return; - } -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: writing back marker\n"); -#endif - aux->next_mark_addr = htonl(next_mark_addr); - idetape_position_tape(drive, last_mark_addr, 0, 0); - if (!idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: couldn't write back marker " - "frame at %d\n", tape->name, last_mark_addr); - __idetape_kfree_stage(stage); - idetape_position_tape(drive, position, 0, 0); - return; - } - __idetape_kfree_stage(stage); - idetape_flush_tape_buffers(drive); - idetape_position_tape(drive, position, 0, 0); - return; -} - -static void idetape_write_filler (ide_drive_t *drive, int block, int cnt) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - int rc; - - if (!tape->onstream || tape->raw) - return; - stage = __idetape_kmalloc_stage(tape, 1, 1); - if (stage == NULL) - return; - idetape_init_stage(drive, stage, OS_FRAME_TYPE_FILL, 0); - idetape_wait_ready(drive, 60 * 5 * HZ); - rc = idetape_position_tape(drive, block, 0, 0); -#if ONSTREAM_DEBUG - printk(KERN_INFO "write_filler: positioning failed it returned %d\n", rc); -#endif - if (rc != 0) - /* don't write fillers if we cannot position the tape. */ - return; - - strcpy(stage->bh->b_data, "Filler"); - while (cnt--) { - if (!idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: write_filler: " - "couldn't write header frame\n", tape->name); - __idetape_kfree_stage(stage); - return; - } - } - __idetape_kfree_stage(stage); -} - -static void __idetape_write_header (ide_drive_t *drive, int block, int cnt) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - os_header_t header; - - stage = __idetape_kmalloc_stage(tape, 1, 1); - if (stage == NULL) - return; - idetape_init_stage(drive, stage, OS_FRAME_TYPE_HEADER, tape->logical_blk_num); - idetape_wait_ready(drive, 60 * 5 * HZ); - idetape_position_tape(drive, block, 0, 0); - memset(&header, 0, sizeof(header)); - strcpy(header.ident_str, "ADR_SEQ"); - header.major_rev = 1; - header.minor_rev = OS_ADR_MINREV; - header.par_num = 1; - header.partition.partition_num = OS_DATA_PARTITION; - header.partition.par_desc_ver = OS_PARTITION_VERSION; - header.partition.first_frame_addr = htonl(OS_DATA_STARTFRAME1); - header.partition.last_frame_addr = htonl(tape->capacity); - header.partition.wrt_pass_cntr = htons(tape->wrt_pass_cntr); - header.partition.eod_frame_addr = htonl(tape->eod_frame_addr); - memcpy(stage->bh->b_data, &header, sizeof(header)); - while (cnt--) { - if (!idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: couldn't write " - "header frame\n", tape->name); - __idetape_kfree_stage(stage); - return; - } - } - __idetape_kfree_stage(stage); - idetape_flush_tape_buffers(drive); -} - -static void idetape_write_header (ide_drive_t *drive, int locate_eod) -{ - idetape_tape_t *tape = drive->driver_data; - -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: writing tape header\n", - tape->name); -#endif - if (!tape->onstream || tape->raw) - return; - tape->update_frame_cntr++; - __idetape_write_header(drive, 5, 5); - __idetape_write_header(drive, 0xbae, 5); /* 2990 */ - if (locate_eod) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: locating back to eod " - "frame addr %d\n", tape->name, - tape->eod_frame_addr); -#endif - idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); - } -} - static ssize_t idetape_chrdev_write (struct file *file, const char *buf, size_t count, loff_t *ppos) { - struct inode *inode = file->f_dentry->d_inode; ide_drive_t *drive = file->private_data; idetape_tape_t *tape = drive->driver_data; - unsigned int minor = iminor(inode); ssize_t retval, actually_written = 0; - int position; if (ppos != &file->f_pos) { /* "A request was outside the capabilities of the device." */ @@ -4942,28 +3832,6 @@ "count %Zd\n", count); #endif /* IDETAPE_DEBUG_LOG */ - if (tape->onstream) { - if (count != tape->tape_block_size) { - printk(KERN_ERR "ide-tape: %s: chrdev_write: use %d " - "bytes as block size (%Zd used)\n", - tape->name, tape->tape_block_size, count); - return -EINVAL; - } - /* - * Check if we reach the end of the tape. Just assume the whole - * pipeline is filled with write requests! - */ - if (tape->first_frame_position + tape->nr_stages >= tape->capacity - OS_EW) { -#if ONSTREAM_DEBUG - printk(KERN_INFO, "chrdev_write: Write truncated at " - "EOM early warning"); -#endif - if (tape->chrdev_direction == idetape_direction_write) - idetape_write_release(drive, minor); - return -ENOSPC; - } - } - /* Initialize write operation */ if (tape->chrdev_direction != idetape_direction_write) { if (tape->chrdev_direction == idetape_direction_read) @@ -4980,39 +3848,6 @@ tape->chrdev_direction = idetape_direction_write; idetape_init_merge_stage(tape); - if (tape->onstream) { - position = idetape_read_position(drive); - if (position <= OS_DATA_STARTFRAME1) { - tape->logical_blk_num = 0; - tape->wrt_pass_cntr++; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: logical block num 0, setting eod to %d\n", tape->name, OS_DATA_STARTFRAME1); - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: allocating new write pass counter %d\n", tape->name, tape->wrt_pass_cntr); -#endif - tape->filemark_cnt = 0; - tape->eod_frame_addr = OS_DATA_STARTFRAME1; - tape->first_mark_addr = tape->last_mark_addr = -1; - idetape_write_header(drive, 1); - } -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: positioning " - "tape to eod at %d\n", - tape->name, tape->eod_frame_addr); -#endif - position = idetape_read_position(drive); - if (position != tape->eod_frame_addr) - idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: " - "first_frame_position %d\n", - tape->name, tape->first_frame_position); -#endif - } - /* * Issue a write 0 command to ensure that DSC handshake * is switched from completion mode to buffer available @@ -5029,11 +3864,6 @@ return retval; } } -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk("ide-tape: first_frame_position %d\n", - tape->first_frame_position); -#endif } if (count == 0) return (0); @@ -5078,88 +3908,14 @@ static int idetape_write_filemark (ide_drive_t *drive) { - idetape_tape_t *tape = drive->driver_data; - int last_mark_addr; idetape_pc_t pc; - if (!tape->onstream) { - /* Write a filemark */ - idetape_create_write_filemark_cmd(drive, &pc, 1); - if (idetape_queue_pc_tail(drive, &pc)) { - printk(KERN_ERR "ide-tape: Couldn't write a filemark\n"); - return -EIO; - } - } else if (!tape->raw) { - last_mark_addr = idetape_read_position(drive); - tape->merge_stage = __idetape_kmalloc_stage(tape, 1, 0); - if (tape->merge_stage != NULL) { - idetape_init_stage(drive, tape->merge_stage, OS_FRAME_TYPE_MARKER, tape->logical_blk_num); - idetape_pad_zeros(drive, tape->stage_size); - tape->logical_blk_num++; - __idetape_kfree_stage(tape->merge_stage); - tape->merge_stage = NULL; - } - if (tape->filemark_cnt) - idetape_update_last_marker(drive, tape->last_mark_addr, last_mark_addr); - tape->last_mark_addr = last_mark_addr; - if (tape->filemark_cnt++ == 0) - tape->first_mark_addr = last_mark_addr; - } - return 0; -} - -static void idetape_write_eod (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - if (!tape->onstream || tape->raw) - return; - tape->merge_stage = __idetape_kmalloc_stage(tape, 1, 0); - if (tape->merge_stage != NULL) { - tape->eod_frame_addr = idetape_read_position(drive); - idetape_init_stage(drive, tape->merge_stage, OS_FRAME_TYPE_EOD, tape->logical_blk_num); - idetape_pad_zeros(drive, tape->stage_size); - __idetape_kfree_stage(tape->merge_stage); - tape->merge_stage = NULL; - } - return; -} - -int idetape_seek_logical_blk (ide_drive_t *drive, int logical_blk_num) -{ - idetape_tape_t *tape = drive->driver_data; - int estimated_address = logical_blk_num + 20; - int retries = 0; - int speed_control; - - speed_control = tape->speed_control; - tape->speed_control = 0; - if (logical_blk_num < 0) - logical_blk_num = 0; - if (idetape_get_logical_blk(drive, logical_blk_num, 10, 1)) - goto ok; - while (++retries < 10) { - idetape_discard_read_pipeline(drive, 0); - idetape_position_tape(drive, estimated_address, 0, 0); - if (idetape_get_logical_blk(drive, logical_blk_num, 10, 1)) - goto ok; - if (!idetape_get_logical_blk(drive, -1, 10, 1)) - goto error; - if (tape->logical_blk_num < logical_blk_num) - estimated_address += logical_blk_num - tape->logical_blk_num; - else - break; + /* Write a filemark */ + idetape_create_write_filemark_cmd(drive, &pc, 1); + if (idetape_queue_pc_tail(drive, &pc)) { + printk(KERN_ERR "ide-tape: Couldn't write a filemark\n"); + return -EIO; } -error: - tape->speed_control = speed_control; - tape->restart_speed_control_req = 1; - printk(KERN_INFO "ide-tape: %s: couldn't seek to logical block %d " - "(at %d), %d retries\n", tape->name, logical_blk_num, - tape->logical_blk_num, retries); - return -EIO; -ok: - tape->speed_control = speed_control; - tape->restart_speed_control_req = 1; return 0; } @@ -5266,8 +4022,6 @@ idetape_discard_read_pipeline(drive, 0); if (idetape_rewind_tape(drive)) return -EIO; - if (tape->onstream && !tape->raw) - return idetape_position_tape(drive, OS_DATA_STARTFRAME1, 0, 0); return 0; case MTLOAD: idetape_discard_read_pipeline(drive, 0); @@ -5298,50 +4052,13 @@ idetape_create_load_unload_cmd(drive, &pc,IDETAPE_LU_RETENSION_MASK | IDETAPE_LU_LOAD_MASK); return (idetape_queue_pc_tail(drive, &pc)); case MTEOM: - if (tape->onstream) { -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: positioning tape to eod at %d\n", tape->name, tape->eod_frame_addr); -#endif - idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); - if (!idetape_get_logical_blk(drive, -1, 10, 0)) - return -EIO; - if (tape->first_stage->aux->frame_type != OS_FRAME_TYPE_EOD) - return -EIO; - return 0; - } idetape_create_space_cmd(&pc, 0, IDETAPE_SPACE_TO_EOD); return (idetape_queue_pc_tail(drive, &pc)); case MTERASE: - if (tape->onstream) { - tape->eod_frame_addr = OS_DATA_STARTFRAME1; - tape->logical_blk_num = 0; - tape->first_mark_addr = tape->last_mark_addr = -1; - idetape_position_tape(drive, tape->eod_frame_addr, 0, 0); - idetape_write_eod(drive); - idetape_flush_tape_buffers(drive); - idetape_write_header(drive, 0); - /* - * write filler frames to the unused frames... - * REMOVE WHEN going to LIN4 application type... - */ - idetape_write_filler(drive, OS_DATA_STARTFRAME1 - 10, 10); - idetape_write_filler(drive, OS_DATA_ENDFRAME1, 10); - idetape_flush_tape_buffers(drive); - (void) idetape_rewind_tape(drive); - return 0; - } (void) idetape_rewind_tape(drive); idetape_create_erase_cmd(&pc); return (idetape_queue_pc_tail(drive, &pc)); case MTSETBLK: - if (tape->onstream) { - if (mt_count != tape->tape_block_size) { - printk(KERN_INFO "ide-tape: %s: MTSETBLK %d -- only %d bytes block size supported\n", tape->name, mt_count, tape->tape_block_size); - return -EINVAL; - } - return 0; - } if (mt_count) { if (mt_count < tape->tape_block_size || mt_count % tape->tape_block_size) return -EIO; @@ -5351,28 +4068,13 @@ set_bit(IDETAPE_DETECT_BS, &tape->flags); return 0; case MTSEEK: - if (!tape->onstream || tape->raw) { - idetape_discard_read_pipeline(drive, 0); - return idetape_position_tape(drive, mt_count * tape->user_bs_factor, tape->partition, 0); - } - return idetape_seek_logical_blk(drive, mt_count); + idetape_discard_read_pipeline(drive, 0); + return idetape_position_tape(drive, mt_count * tape->user_bs_factor, tape->partition, 0); case MTSETPART: idetape_discard_read_pipeline(drive, 0); - if (tape->onstream) - return -EIO; return (idetape_position_tape(drive, 0, mt_count, 0)); case MTFSR: case MTBSR: - if (tape->onstream) { - if (!idetape_get_logical_blk(drive, -1, 10, 0)) - return -EIO; - if (mt_op == MTFSR) - return idetape_seek_logical_blk(drive, tape->logical_blk_num + mt_count); - else { - idetape_discard_read_pipeline(drive, 0); - return idetape_seek_logical_blk(drive, tape->logical_blk_num - mt_count); - } - } case MTLOCK: if (!idetape_create_prevent_cmd(drive, &pc, 1)) return 0; @@ -5450,34 +4152,16 @@ case MTIOCGET: memset(&mtget, 0, sizeof (struct mtget)); mtget.mt_type = MT_ISSCSI2; - if (!tape->onstream || tape->raw) - mtget.mt_blkno = position / tape->user_bs_factor - block_offset; - else { - if (!idetape_get_logical_blk(drive, -1, 10, 0)) - mtget.mt_blkno = -1; - else - mtget.mt_blkno = tape->logical_blk_num; - } + mtget.mt_blkno = position / tape->user_bs_factor - block_offset; mtget.mt_dsreg = ((tape->tape_block_size * tape->user_bs_factor) << MT_ST_BLKSIZE_SHIFT) & MT_ST_BLKSIZE_MASK; - if (tape->onstream) { - mtget.mt_gstat |= GMT_ONLINE(0xffffffff); - if (tape->first_stage && tape->first_stage->aux->frame_type == OS_FRAME_TYPE_EOD) - mtget.mt_gstat |= GMT_EOD(0xffffffff); - if (position <= OS_DATA_STARTFRAME1) - mtget.mt_gstat |= GMT_BOT(0xffffffff); - } else if (tape->drv_write_prot) { + if (tape->drv_write_prot) { mtget.mt_gstat |= GMT_WR_PROT(0xffffffff); } if (copy_to_user((char *) arg,(char *) &mtget, sizeof(struct mtget))) return -EFAULT; return 0; case MTIOCPOS: - if (tape->onstream && !tape->raw) { - if (!idetape_get_logical_blk(drive, -1, 10, 0)) - return -EIO; - mtpos.mt_blkno = tape->logical_blk_num; - } else - mtpos.mt_blkno = position / tape->user_bs_factor - block_offset; + mtpos.mt_blkno = position / tape->user_bs_factor - block_offset; if (copy_to_user((char *) arg,(char *) &mtpos, sizeof(struct mtpos))) return -EFAULT; return 0; @@ -5488,106 +4172,6 @@ } } -static int __idetape_analyze_headers (ide_drive_t *drive, int block) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_stage_t *stage; - os_header_t *header; - os_aux_t *aux; - - if (!tape->onstream || tape->raw) { - tape->header_ok = tape->linux_media = 1; - return 1; - } - tape->header_ok = tape->linux_media = 0; - tape->update_frame_cntr = 0; - tape->wrt_pass_cntr = 0; - tape->eod_frame_addr = OS_DATA_STARTFRAME1; - tape->first_mark_addr = tape->last_mark_addr = -1; - stage = __idetape_kmalloc_stage(tape, 0, 0); - if (stage == NULL) - return 0; -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: reading header\n", tape->name); -#endif - idetape_position_tape(drive, block, 0, 0); - if (!idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, 1, stage->bh)) { - printk(KERN_INFO "ide-tape: %s: couldn't read header frame\n", - tape->name); - __idetape_kfree_stage(stage); - return 0; - } - header = (os_header_t *) stage->bh->b_data; - aux = stage->aux; - if (strncmp(header->ident_str, "ADR_SEQ", 7) != 0) { - printk(KERN_INFO "ide-tape: %s: invalid header identification string\n", tape->name); - __idetape_kfree_stage(stage); - return 0; - } - if (header->major_rev != 1 || (header->minor_rev > OS_ADR_MINREV)) - printk(KERN_INFO "ide-tape: warning: revision %d.%d " - "detected (up to 1.%d supported)\n", - header->major_rev, header->minor_rev, OS_ADR_MINREV); - if (header->par_num != 1) - printk(KERN_INFO "ide-tape: warning: %d partitions defined, only one supported\n", header->par_num); - tape->wrt_pass_cntr = ntohs(header->partition.wrt_pass_cntr); - tape->eod_frame_addr = ntohl(header->partition.eod_frame_addr); - tape->filemark_cnt = ntohl(aux->filemark_cnt); - tape->first_mark_addr = ntohl(aux->next_mark_addr); - tape->last_mark_addr = ntohl(aux->last_mark_addr); - tape->update_frame_cntr = ntohl(aux->update_frame_cntr); - memcpy(tape->application_sig, aux->application_sig, 4); - tape->application_sig[4] = 0; - if (memcmp(tape->application_sig, "LIN", 3) == 0) { - tape->linux_media = 1; - tape->linux_media_version = tape->application_sig[3] - '0'; - if (tape->linux_media_version != 3) - printk(KERN_INFO "ide-tape: %s: Linux media version " - "%d detected (current 3)\n", - tape->name, tape->linux_media_version); - } else { - printk(KERN_INFO "ide-tape: %s: non Linux media detected " - "(%s)\n", tape->name, tape->application_sig); - tape->linux_media = 0; - } -#if ONSTREAM_DEBUG - if (tape->debug_level >= 2) - printk(KERN_INFO "ide-tape: %s: detected write pass counter " - "%d, eod frame addr %d\n", tape->name, - tape->wrt_pass_cntr, tape->eod_frame_addr); -#endif - __idetape_kfree_stage(stage); - return 1; -} - -static int idetape_analyze_headers (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - int position, block; - - if (!tape->onstream || tape->raw) { - tape->header_ok = tape->linux_media = 1; - return 1; - } - tape->header_ok = tape->linux_media = 0; - position = idetape_read_position(drive); - for (block = 5; block < 10; block++) - if (__idetape_analyze_headers(drive, block)) - goto ok; - for (block = 0xbae; block < 0xbb3; block++) /* 2990 - 2994 */ - if (__idetape_analyze_headers(drive, block)) - goto ok; - printk(KERN_ERR "ide-tape: %s: failed to find valid ADRL header\n", tape->name); - return 0; -ok: - if (position < OS_DATA_STARTFRAME1) - position = OS_DATA_STARTFRAME1; - idetape_position_tape(drive, position, 0, 0); - tape->header_ok = 1; - return 1; -} - static void idetape_get_blocksize_from_block_descriptor(ide_drive_t *drive); /* @@ -5613,16 +4197,6 @@ if (test_and_set_bit(IDETAPE_BUSY, &tape->flags)) return -EBUSY; - if (tape->onstream) { - if (minor & 64) { - tape->tape_block_size = tape->stage_size = 32768 + 512; - tape->raw = 1; - } else { - tape->tape_block_size = tape->stage_size = 32768; - tape->raw = 0; - } - idetape_onstream_mode_sense_tape_parameter_page(drive, tape->debug_level); - } retval = idetape_wait_ready(drive, 60 * HZ); if (retval) { clear_bit(IDETAPE_BUSY, &tape->flags); @@ -5657,7 +4231,6 @@ /* * Lock the tape drive door so user can't eject. - * Analyze headers for OnStream drives. */ if (tape->chrdev_direction == idetape_direction_none) { if (idetape_create_prevent_cmd(drive, &pc, 1)) { @@ -5666,9 +4239,7 @@ tape->door_locked = DOOR_LOCKED; } } - idetape_analyze_headers(drive); } - tape->max_frames = tape->cur_frames = tape->req_buffer_fill = 0; idetape_restart_speed_control(drive); tape->restart_speed_control_req = 0; return 0; @@ -5686,9 +4257,7 @@ tape->merge_stage = NULL; } idetape_write_filemark(drive); - idetape_write_eod(drive); idetape_flush_tape_buffers(drive); - idetape_write_header(drive, minor >= 128); idetape_flush_tape_buffers(drive); } @@ -5867,100 +4436,6 @@ } /* - * Notify vendor ID to the OnStream tape drive - */ -static void idetape_onstream_set_vendor (ide_drive_t *drive, char *vendor) -{ - idetape_pc_t pc; - idetape_mode_parameter_header_t *header; - - idetape_create_mode_select_cmd(&pc, sizeof(*header) + 8); - pc.buffer[0] = 3 + 8; /* Mode Data Length */ - pc.buffer[1] = 0; /* Medium Type - ignoring */ - pc.buffer[2] = 0; /* Reserved */ - pc.buffer[3] = 0; /* Block Descriptor Length */ - pc.buffer[4 + 0] = 0x36 | (1 << 7); - pc.buffer[4 + 1] = 6; - pc.buffer[4 + 2] = vendor[0]; - pc.buffer[4 + 3] = vendor[1]; - pc.buffer[4 + 4] = vendor[2]; - pc.buffer[4 + 5] = vendor[3]; - pc.buffer[4 + 6] = 0; - pc.buffer[4 + 7] = 0; - if (idetape_queue_pc_tail(drive, &pc)) - printk(KERN_ERR "ide-tape: Couldn't set vendor name to %s\n", vendor); - -} - -/* - * Various unused OnStream commands - */ -#if ONSTREAM_DEBUG -static void idetape_onstream_set_retries (ide_drive_t *drive, int retries) -{ - idetape_pc_t pc; - - idetape_create_mode_select_cmd(&pc, sizeof(idetape_mode_parameter_header_t) + 4); - pc.buffer[0] = 3 + 4; - pc.buffer[1] = 0; /* Medium Type - ignoring */ - pc.buffer[2] = 0; /* Reserved */ - pc.buffer[3] = 0; /* Block Descriptor Length */ - pc.buffer[4 + 0] = 0x2f | (1 << 7); - pc.buffer[4 + 1] = 2; - pc.buffer[4 + 2] = 4; - pc.buffer[4 + 3] = retries; - if (idetape_queue_pc_tail(drive, &pc)) - printk(KERN_ERR "ide-tape: Couldn't set retries to %d\n", retries); -} -#endif - -/* - * Configure 32.5KB block size. - */ -static void idetape_onstream_configure_block_size (ide_drive_t *drive) -{ - idetape_pc_t pc; - idetape_mode_parameter_header_t *header; - idetape_block_size_page_t *bs; - - /* - * Get the current block size from the block size mode page - */ - idetape_create_mode_sense_cmd(&pc, IDETAPE_BLOCK_SIZE_PAGE); - if (idetape_queue_pc_tail(drive, &pc)) - printk(KERN_ERR "ide-tape: can't get tape block size mode page\n"); - header = (idetape_mode_parameter_header_t *) pc.buffer; - bs = (idetape_block_size_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl); - -#if IDETAPE_DEBUG_INFO - printk(KERN_INFO "ide-tape: 32KB play back: %s\n", bs->play32 ? "Yes" : "No"); - printk(KERN_INFO "ide-tape: 32.5KB play back: %s\n", bs->play32_5 ? "Yes" : "No"); - printk(KERN_INFO "ide-tape: 32KB record: %s\n", bs->record32 ? "Yes" : "No"); - printk(KERN_INFO "ide-tape: 32.5KB record: %s\n", bs->record32_5 ? "Yes" : "No"); -#endif /* IDETAPE_DEBUG_INFO */ - - /* - * Configure default auto columns mode, 32.5KB block size - */ - bs->one = 1; - bs->play32 = 0; - bs->play32_5 = 1; - bs->record32 = 0; - bs->record32_5 = 1; - idetape_create_mode_select_cmd(&pc, sizeof(*header) + sizeof(*bs)); - if (idetape_queue_pc_tail(drive, &pc)) - printk(KERN_ERR "ide-tape: Couldn't set tape block size mode page\n"); - -#if ONSTREAM_DEBUG - /* - * In debug mode, we want to see as many errors as possible - * to test the error recovery mechanism. - */ - idetape_onstream_set_retries(drive, 0); -#endif -} - -/* * Use INQUIRY to get the firmware revision */ static void idetape_get_inquiry_results (ide_drive_t *drive) @@ -5985,63 +4460,10 @@ r = tape->firmware_revision; if (*(r + 1) == '.') tape->firmware_revision_num = (*r - '0') * 100 + (*(r + 2) - '0') * 10 + *(r + 3) - '0'; - else if (tape->onstream) - tape->firmware_revision_num = (*r - '0') * 100 + (*(r + 1) - '0') * 10 + *(r + 2) - '0'; printk(KERN_INFO "ide-tape: %s <-> %s: %s %s rev %s\n", drive->name, tape->name, tape->vendor_id, tape->product_id, tape->firmware_revision); } /* - * Configure the OnStream ATAPI tape drive for default operation - */ -static void idetape_configure_onstream (ide_drive_t *drive) -{ - idetape_tape_t *tape = drive->driver_data; - - if (tape->firmware_revision_num < 105) { - printk(KERN_INFO "ide-tape: %s: Old OnStream firmware revision detected (%s)\n", tape->name, tape->firmware_revision); - printk(KERN_INFO "ide-tape: %s: An upgrade to version 1.05 or above is recommended\n", tape->name); - } - - /* - * Configure 32.5KB (data+aux) block size. - */ - idetape_onstream_configure_block_size(drive); - - /* - * Set vendor name to 'LIN3' for "Linux support version 3". - */ - idetape_onstream_set_vendor(drive, "LIN3"); -} - -/* - * idetape_get_mode_sense_parameters asks the tape about its various - * parameters. This may work for other drives to??? - */ -static void idetape_onstream_mode_sense_tape_parameter_page(ide_drive_t *drive, int debug) -{ - idetape_tape_t *tape = drive->driver_data; - idetape_pc_t pc; - idetape_mode_parameter_header_t *header; - onstream_tape_paramtr_page_t *prm; - - idetape_create_mode_sense_cmd(&pc, IDETAPE_PARAMTR_PAGE); - if (idetape_queue_pc_tail(drive, &pc)) { - printk(KERN_ERR "ide-tape: Can't get tape parameters page - probably no tape inserted in onstream drive\n"); - return; - } - header = (idetape_mode_parameter_header_t *) pc.buffer; - prm = (onstream_tape_paramtr_page_t *) (pc.buffer + sizeof(idetape_mode_parameter_header_t) + header->bdl); - - tape->capacity = ntohs(prm->segtrk) * ntohs(prm->trks); - if (debug) { - printk(KERN_INFO "ide-tape: %s <-> %s: Tape length %dMB (%d frames/track, %d tracks = %d blocks, density: %dKbpi)\n", - drive->name, tape->name, tape->capacity/32, ntohs(prm->segtrk), ntohs(prm->trks), tape->capacity, prm->density); - } - - return; -} - -/* * idetape_get_mode_sense_results asks the tape about its various * parameters. In particular, we will adjust our data transfer buffer * size to the recommended value as returned by the tape. @@ -6084,8 +4506,6 @@ tape->tape_block_size = 512; else if (capabilities->blk1024) tape->tape_block_size = 1024; - else if (tape->onstream && capabilities->blk32768) - tape->tape_block_size = 32768; #if IDETAPE_DEBUG_INFO printk(KERN_INFO "ide-tape: Dumping the results of the MODE SENSE packet command\n"); @@ -6169,18 +4589,6 @@ ide_add_setting(drive, "pipeline_head_speed_u",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->uncontrolled_pipeline_head_speed, NULL); ide_add_setting(drive, "avg_speed", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->avg_speed, NULL); ide_add_setting(drive, "debug_level",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->debug_level, NULL); - if (tape->onstream) { - ide_add_setting(drive, "cur_frames", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->cur_frames, NULL); - ide_add_setting(drive, "max_frames", SETTING_READ, -1, -1, TYPE_SHORT, 0, 0xffff, 1, 1, &tape->max_frames, NULL); - ide_add_setting(drive, "insert_speed", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->insert_speed, NULL); - ide_add_setting(drive, "speed_control",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->speed_control, NULL); - ide_add_setting(drive, "tape_still_time",SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->tape_still_time, NULL); - ide_add_setting(drive, "max_insert_speed",SETTING_RW, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->max_insert_speed, NULL); - ide_add_setting(drive, "insert_size", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->insert_size, NULL); - ide_add_setting(drive, "capacity", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->capacity, NULL); - ide_add_setting(drive, "first_frame", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->first_frame_position, NULL); - ide_add_setting(drive, "logical_blk", SETTING_READ, -1, -1, TYPE_INT, 0, 0xffff, 1, 1, &tape->logical_blk_num, NULL); - } } /* @@ -6208,11 +4616,9 @@ drive->driver_data = tape; /* An ATAPI device ignores DRDY */ drive->ready_stat = 0; - if (strstr(drive->id->model, "OnStream DI-")) - tape->onstream = 1; drive->dsc_overlap = 1; #ifdef CONFIG_BLK_DEV_IDEPCI - if (!tape->onstream && HWIF(drive)->pci_dev != NULL) { + if (HWIF(drive)->pci_dev != NULL) { /* * These two ide-pci host adapters appear to need DSC overlap disabled. * This probably needs further analysis. @@ -6245,10 +4651,6 @@ idetape_get_inquiry_results(drive); idetape_get_mode_sense_results(drive); idetape_get_blocksize_from_block_descriptor(drive); - if (tape->onstream) { - idetape_onstream_mode_sense_tape_parameter_page(drive, 1); - idetape_configure_onstream(drive); - } tape->user_bs_factor = 1; tape->stage_size = tape->capabilities.ctl * tape->tape_block_size; while (tape->stage_size > 0xffff) { @@ -6257,8 +4659,6 @@ tape->stage_size = tape->capabilities.ctl * tape->tape_block_size; } stage_size = tape->stage_size; - if (tape->onstream) - stage_size = 32768 + 512; tape->pages_per_stage = stage_size / PAGE_SIZE; if (stage_size % PAGE_SIZE) { tape->pages_per_stage++; @@ -6454,7 +4854,7 @@ printk(KERN_ERR "ide-tape: %s: Can't allocate a tape structure\n", drive->name); goto failed; } - if (ide_register_subdriver (drive, &idetape_driver, IDE_SUBDRIVER_VERSION)) { + if (ide_register_subdriver(drive, &idetape_driver)) { printk(KERN_ERR "ide-tape: %s: Failed to register the driver with ide.c\n", drive->name); kfree(tape); goto failed; @@ -6502,3 +4902,4 @@ module_init(idetape_init); module_exit(idetape_exit); +MODULE_ALIAS_CHARDEV_MAJOR(IDETAPE_MAJOR); diff -Nru a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c --- a/drivers/ide/ide-taskfile.c Thu Feb 19 23:44:22 2004 +++ b/drivers/ide/ide-taskfile.c Thu Feb 19 23:44:22 2004 @@ -219,66 +219,6 @@ EXPORT_SYMBOL(do_rw_taskfile); /* - * Clean up after success/failure of an explicit taskfile operation. - */ -void ide_end_taskfile (ide_drive_t *drive, u8 stat, u8 err) -{ - ide_hwif_t *hwif = HWIF(drive); - unsigned long flags; - struct request *rq; - ide_task_t *args; - task_ioreg_t command; - - spin_lock_irqsave(&ide_lock, flags); - rq = HWGROUP(drive)->rq; - spin_unlock_irqrestore(&ide_lock, flags); - args = (ide_task_t *) rq->special; - - command = args->tfRegister[IDE_COMMAND_OFFSET]; - - if (rq->errors == 0) - rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT); - - if (args->tf_in_flags.b.data) { - u16 data = hwif->INW(IDE_DATA_REG); - args->tfRegister[IDE_DATA_OFFSET] = (data) & 0xFF; - args->hobRegister[IDE_DATA_OFFSET_HOB] = (data >> 8) & 0xFF; - } - args->tfRegister[IDE_ERROR_OFFSET] = err; - args->tfRegister[IDE_NSECTOR_OFFSET] = hwif->INB(IDE_NSECTOR_REG); - args->tfRegister[IDE_SECTOR_OFFSET] = hwif->INB(IDE_SECTOR_REG); - args->tfRegister[IDE_LCYL_OFFSET] = hwif->INB(IDE_LCYL_REG); - args->tfRegister[IDE_HCYL_OFFSET] = hwif->INB(IDE_HCYL_REG); - args->tfRegister[IDE_SELECT_OFFSET] = hwif->INB(IDE_SELECT_REG); - args->tfRegister[IDE_STATUS_OFFSET] = stat; - if ((drive->id->command_set_2 & 0x0400) && - (drive->id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - hwif->OUTB(drive->ctl|0x80, IDE_CONTROL_REG_HOB); - args->hobRegister[IDE_FEATURE_OFFSET_HOB] = hwif->INB(IDE_FEATURE_REG); - args->hobRegister[IDE_NSECTOR_OFFSET_HOB] = hwif->INB(IDE_NSECTOR_REG); - args->hobRegister[IDE_SECTOR_OFFSET_HOB] = hwif->INB(IDE_SECTOR_REG); - args->hobRegister[IDE_LCYL_OFFSET_HOB] = hwif->INB(IDE_LCYL_REG); - args->hobRegister[IDE_HCYL_OFFSET_HOB] = hwif->INB(IDE_HCYL_REG); - } - -#if 0 -/* taskfile_settings_update(drive, args, command); */ - - if (args->posthandler != NULL) - args->posthandler(drive, args); -#endif - - spin_lock_irqsave(&ide_lock, flags); - blkdev_dequeue_request(rq); - HWGROUP(drive)->rq = NULL; - end_that_request_last(rq); - spin_unlock_irqrestore(&ide_lock, flags); -} - -EXPORT_SYMBOL(ide_end_taskfile); - -/* * set_multmode_intr() is invoked on completion of a WIN_SETMULT cmd. */ ide_startstop_t set_multmode_intr (ide_drive_t *drive) @@ -1669,7 +1609,6 @@ */ int ide_cmd_ioctl (ide_drive_t *drive, unsigned int cmd, unsigned long arg) { -#if 1 int err = 0; u8 args[4], *argbuf = args; u8 xfer_rate = 0; @@ -1720,70 +1659,6 @@ if (argsize > 4) kfree(argbuf); return err; - -#else - - int err = -EIO; - u8 args[4], *argbuf = args; - u8 xfer_rate = 0; - int argsize = 0; - ide_task_t tfargs; - - if (NULL == (void *) arg) { - struct request rq; - ide_init_drive_cmd(&rq); - return ide_do_drive_cmd(drive, &rq, ide_wait); - } - - if (copy_from_user(args, (void *)arg, 4)) - return -EFAULT; - - memset(&tfargs, 0, sizeof(ide_task_t)); - tfargs.tfRegister[IDE_FEATURE_OFFSET] = args[2]; - tfargs.tfRegister[IDE_NSECTOR_OFFSET] = args[3]; - tfargs.tfRegister[IDE_SECTOR_OFFSET] = args[1]; - tfargs.tfRegister[IDE_LCYL_OFFSET] = 0x00; - tfargs.tfRegister[IDE_HCYL_OFFSET] = 0x00; - tfargs.tfRegister[IDE_SELECT_OFFSET] = 0x00; - tfargs.tfRegister[IDE_COMMAND_OFFSET] = args[0]; - - if (args[3]) { - argsize = (SECTOR_WORDS * 4 * args[3]); - argbuf = kmalloc(argsize, GFP_KERNEL); - if (argbuf == NULL) - return -ENOMEM; - } - - if (set_transfer(drive, &tfargs)) { - xfer_rate = args[1]; - if (ide_ata66_check(drive, &tfargs)) - goto abort; - } - - tfargs.command_type = ide_cmd_type_parser(&tfargs); - err = ide_raw_taskfile(drive, &tfargs, argbuf); - - if (!err && xfer_rate) { - /* active-retuning-calls future */ - ide_set_xfer_rate(driver, xfer_rate); - ide_driveid_update(drive); - } -abort: - args[0] = tfargs.tfRegister[IDE_COMMAND_OFFSET]; - args[1] = tfargs.tfRegister[IDE_FEATURE_OFFSET]; - args[2] = tfargs.tfRegister[IDE_NSECTOR_OFFSET]; - args[3] = 0; - - if (copy_to_user((void *)arg, argbuf, 4)) - err = -EFAULT; - if (argbuf != NULL) { - if (copy_to_user((void *)arg, argbuf + 4, argsize)) - err = -EFAULT; - kfree(argbuf); - } - return err; - -#endif } EXPORT_SYMBOL(ide_cmd_ioctl); diff -Nru a/drivers/ide/ide.c b/drivers/ide/ide.c --- a/drivers/ide/ide.c Thu Feb 19 23:44:24 2004 +++ b/drivers/ide/ide.c Thu Feb 19 23:44:24 2004 @@ -474,6 +474,8 @@ }; #ifdef CONFIG_PROC_FS +struct proc_dir_entry *proc_ide_root; + ide_proc_entry_t generic_subdriver_entries[] = { { "capacity", S_IFREG|S_IRUGO, proc_ide_read_capacity, NULL }, { NULL, 0, NULL, NULL } @@ -642,10 +644,9 @@ drive = &hwif->drives[unit]; if (!drive->present) continue; - if (drive->usage) - goto abort; - if (DRIVER(drive)->shutdown(drive)) + if (drive->usage || DRIVER(drive)->busy) goto abort; + drive->dead = 1; } hwif->present = 0; @@ -1392,7 +1393,6 @@ ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL); ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL); ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode); - ide_add_setting(drive, "slow", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->slow, NULL); ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL); ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma); ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL); @@ -1786,83 +1786,9 @@ /* * ide_setup() gets called VERY EARLY during initialization, - * to handle kernel "command line" strings beginning with "hdx=" - * or "ide". Here is the complete set currently supported: + * to handle kernel "command line" strings beginning with "hdx=" or "ide". * - * "hdx=" is recognized for all "x" from "a" to "h", such as "hdc". - * "idex=" is recognized for all "x" from "0" to "3", such as "ide1". - * - * "hdx=noprobe" : drive may be present, but do not probe for it - * "hdx=none" : drive is NOT present, ignore cmos and do not probe - * "hdx=nowerr" : ignore the WRERR_STAT bit on this drive - * "hdx=cdrom" : drive is present, and is a cdrom drive - * "hdx=cyl,head,sect" : disk drive is present, with specified geometry - * "hdx=remap63" : add 63 to all sector numbers (for OnTrack DM) - * "hdx=remap" : remap 0->1 (for EZDrive) - * "hdx=autotune" : driver will attempt to tune interface speed - * to the fastest PIO mode supported, - * if possible for this drive only. - * Not fully supported by all chipset types, - * and quite likely to cause trouble with - * older/odd IDE drives. - * "hdx=slow" : insert a huge pause after each access to the data - * port. Should be used only as a last resort. - * - * "hdx=swapdata" : when the drive is a disk, byte swap all data - * "hdx=bswap" : same as above.......... - * "hdxlun=xx" : set the drive last logical unit. - * "hdx=flash" : allows for more than one ata_flash disk to be - * registered. In most cases, only one device - * will be present. - * "hdx=scsi" : the return of the ide-scsi flag, this is useful for - * allowing ide-floppy, ide-tape, and ide-cdrom|writers - * to use ide-scsi emulation on a device specific option. - * "idebus=xx" : inform IDE driver of VESA/PCI bus speed in MHz, - * where "xx" is between 20 and 66 inclusive, - * used when tuning chipset PIO modes. - * For PCI bus, 25 is correct for a P75 system, - * 30 is correct for P90,P120,P180 systems, - * and 33 is used for P100,P133,P166 systems. - * If in doubt, use idebus=33 for PCI. - * As for VLB, it is safest to not specify it. - * - * "idex=noprobe" : do not attempt to access/use this interface - * "idex=base" : probe for an interface at the addr specified, - * where "base" is usually 0x1f0 or 0x170 - * and "ctl" is assumed to be "base"+0x206 - * "idex=base,ctl" : specify both base and ctl - * "idex=base,ctl,irq" : specify base, ctl, and irq number - * "idex=autotune" : driver will attempt to tune interface speed - * to the fastest PIO mode supported, - * for all drives on this interface. - * Not fully supported by all chipset types, - * and quite likely to cause trouble with - * older/odd IDE drives. - * "idex=noautotune" : driver will NOT attempt to tune interface speed - * This is the default for most chipsets, - * except the cmd640. - * "idex=serialize" : do not overlap operations on idex and ide(x^1) - * "idex=four" : four drives on idex and ide(x^1) share same ports - * "idex=reset" : reset interface before first use - * "idex=dma" : enable DMA by default on both drives if possible - * "idex=ata66" : informs the interface that it has an 80c cable - * for chipsets that are ATA-66 capable, but - * the ablity to bit test for detection is - * currently unknown. - * "ide=reverse" : Formerly called to pci sub-system, but now local. - * - * The following are valid ONLY on ide0, (except dc4030) - * and the defaults for the base,ctl ports must not be altered. - * - * "ide0=dtc2278" : probe/support DTC2278 interface - * "ide0=ht6560b" : probe/support HT6560B interface - * "ide0=cmd640_vlb" : *REQUIRED* for VLB cards with the CMD640 chip - * (not for PCI -- automatically detected) - * "ide0=qd65xx" : probe/support qd65xx interface - * "ide0=ali14xx" : probe/support ali14xx chipsets (ALI M1439, M1443, M1445) - * "ide0=umc8672" : probe/support umc8672 chipsets - * "idex=dc4030" : probe/support Promise DC4030VL interface - * "ide=doubler" : probe/support IDE doublers on Amiga + * Remember to update Documentation/ide.txt if you change something here. */ int __init ide_setup (char *s) { @@ -1915,8 +1841,8 @@ if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) { const char *hd_words[] = { "none", "noprobe", "nowerr", "cdrom", "serialize", - "autotune", "noautotune", "slow", "swapdata", "bswap", - "flash", "remap", "remap63", "scsi", NULL }; + "autotune", "noautotune", "minus8", "swapdata", "bswap", + "minus11", "remap", "remap63", "scsi", NULL }; unit = s[2] - 'a'; hw = unit / MAX_DRIVES; unit = unit % MAX_DRIVES; @@ -1941,7 +1867,6 @@ } switch (match_parm(&s[3], hd_words, vals, 3)) { case -1: /* "none" */ - drive->nobios = 1; /* drop into "noprobe" */ case -2: /* "noprobe" */ drive->noprobe = 1; goto done; @@ -1963,16 +1888,10 @@ case -7: /* "noautotune" */ drive->autotune = IDE_TUNE_NOAUTO; goto done; - case -8: /* "slow" */ - drive->slow = 1; - goto done; case -9: /* "swapdata" */ case -10: /* "bswap" */ drive->bswap = 1; goto done; - case -11: /* "flash" */ - drive->ata_flash = 1; - goto done; case -12: /* "remap" */ drive->remap_0_to_1 = 1; goto done; @@ -2251,34 +2170,6 @@ return ide_unregister_subdriver(drive); } -/* - * Check if we can unregister the subdriver. Called with the - * request lock held. - */ - -static int default_shutdown(ide_drive_t *drive) -{ - if (drive->usage || DRIVER(drive)->busy) { - return 1; - } - drive->dead = 1; - return 0; -} - -/* - * Default function to use for the cache flush operation. This - * must be replaced for disk devices (see ATA specification - * documents on cache flush and drive suspend rules) - * - * If we have no device attached or the device is not writable - * this handler is sufficient. - */ - -static int default_flushcache (ide_drive_t *drive) -{ - return 0; -} - static ide_startstop_t default_do_request (ide_drive_t *drive, struct request *rq, sector_t block) { ide_end_request(drive, 0, 0); @@ -2341,8 +2232,6 @@ static void setup_driver_defaults (ide_driver_t *d) { if (d->cleanup == NULL) d->cleanup = default_cleanup; - if (d->shutdown == NULL) d->shutdown = default_shutdown; - if (d->flushcache == NULL) d->flushcache = default_flushcache; if (d->do_request == NULL) d->do_request = default_do_request; if (d->end_request == NULL) d->end_request = default_end_request; if (d->sense == NULL) d->sense = default_sense; @@ -2356,15 +2245,15 @@ d->start_power_step = default_start_power_step; } -int ide_register_subdriver (ide_drive_t *drive, ide_driver_t *driver, int version) +int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver) { unsigned long flags; - - BUG_ON(drive->driver == NULL); - + + BUG_ON(!drive->driver); + spin_lock_irqsave(&ide_lock, flags); - if (version != IDE_SUBDRIVER_VERSION || !drive->present || - drive->driver != &idedefault_driver || drive->usage || drive->dead) { + if (!drive->present || drive->driver != &idedefault_driver || + drive->usage || drive->dead) { spin_unlock_irqrestore(&ide_lock, flags); return 1; } @@ -2477,12 +2366,6 @@ printk(KERN_ERR "%s: cleanup_module() called while still busy\n", drive->name); BUG(); } - /* We must remove proc entries defined in this module. - Otherwise we oops while accessing these entries */ -#ifdef CONFIG_PROC_FS - if (drive->proc) - ide_remove_proc_entries(drive->proc, driver->proc); -#endif ata_attach(drive); } } @@ -2520,6 +2403,10 @@ bus_register(&ide_bus_type); init_ide_data(); + +#ifdef CONFIG_PROC_FS + proc_ide_root = proc_mkdir("ide", 0); +#endif #ifdef CONFIG_BLK_DEV_ALI14XX if (probe_ali14xx) diff -Nru a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c --- a/drivers/ide/pci/aec62xx.c Thu Feb 19 23:44:27 2004 +++ b/drivers/ide/pci/aec62xx.c Thu Feb 19 23:44:27 2004 @@ -423,7 +423,7 @@ if (!aec62xx_proc) { aec62xx_proc = 1; - ide_pci_register_host_proc(&aec62xx_procs[0]); + ide_pci_create_host_proc("aec62xx", aec62xx_get_info); } #endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */ diff -Nru a/drivers/ide/pci/aec62xx.h b/drivers/ide/pci/aec62xx.h --- a/drivers/ide/pci/aec62xx.h Thu Feb 19 23:44:25 2004 +++ b/drivers/ide/pci/aec62xx.h Thu Feb 19 23:44:25 2004 @@ -70,24 +70,6 @@ #define BUSCLOCK(D) \ ((struct chipset_bus_clock_list_entry *) pci_get_drvdata((D))) -#if defined(DISPLAY_AEC62XX_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 aec62xx_proc; - -static int aec62xx_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t aec62xx_procs[] = { - { - .name = "aec62xx", - .set = 1, - .get_info = aec62xx_get_info, - .parent = NULL, - }, -}; -#endif /* DISPLAY_AEC62XX_TIMINGS && CONFIG_PROC_FS */ - static void init_setup_aec6x80(struct pci_dev *, ide_pci_device_t *); static void init_setup_aec62xx(struct pci_dev *, ide_pci_device_t *); static unsigned int init_chipset_aec62xx(struct pci_dev *, const char *); diff -Nru a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c --- a/drivers/ide/pci/alim15x3.c Thu Feb 19 23:44:24 2004 +++ b/drivers/ide/pci/alim15x3.c Thu Feb 19 23:44:24 2004 @@ -588,7 +588,7 @@ if (!ali_proc) { ali_proc = 1; bmide_dev = dev; - ide_pci_register_host_proc(&ali_procs[0]); + ide_pci_create_host_proc("ali", ali_get_info); } #endif /* defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) */ diff -Nru a/drivers/ide/pci/alim15x3.h b/drivers/ide/pci/alim15x3.h --- a/drivers/ide/pci/alim15x3.h Thu Feb 19 23:44:22 2004 +++ b/drivers/ide/pci/alim15x3.h Thu Feb 19 23:44:22 2004 @@ -7,24 +7,6 @@ #define DISPLAY_ALI_TIMINGS -#if defined(DISPLAY_ALI_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 ali_proc; - -static int ali_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t ali_procs[] = { - { - .name = "ali", - .set = 1, - .get_info = ali_get_info, - .parent = NULL, - }, -}; -#endif /* DISPLAY_ALI_TIMINGS && CONFIG_PROC_FS */ - static unsigned int init_chipset_ali15x3(struct pci_dev *, const char *); static void init_hwif_common_ali15x3(ide_hwif_t *); static void init_hwif_ali15x3(ide_hwif_t *); diff -Nru a/drivers/ide/pci/amd74xx.c b/drivers/ide/pci/amd74xx.c --- a/drivers/ide/pci/amd74xx.c Thu Feb 19 23:44:28 2004 +++ b/drivers/ide/pci/amd74xx.c Thu Feb 19 23:44:28 2004 @@ -88,6 +88,8 @@ #include #include +static u8 amd74xx_proc; + static unsigned char amd_udma2cyc[] = { 4, 6, 8, 10, 3, 2, 1, 15 }; static unsigned long amd_base; static struct pci_dev *bmide_dev; @@ -398,7 +400,7 @@ if (!amd74xx_proc) { amd_base = pci_resource_start(dev, 4); bmide_dev = dev; - ide_pci_register_host_proc(&amd74xx_procs[0]); + ide_pci_create_host_proc("amd74xx", amd74xx_get_info); amd74xx_proc = 1; } #endif /* DISPLAY_AMD_TIMINGS && CONFIG_PROC_FS */ diff -Nru a/drivers/ide/pci/amd74xx.h b/drivers/ide/pci/amd74xx.h --- a/drivers/ide/pci/amd74xx.h Thu Feb 19 23:44:22 2004 +++ b/drivers/ide/pci/amd74xx.h Thu Feb 19 23:44:22 2004 @@ -7,24 +7,6 @@ #define DISPLAY_AMD_TIMINGS -#if defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 amd74xx_proc; - -static int amd74xx_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t amd74xx_procs[] = { - { - .name = "amd74xx", - .set = 1, - .get_info = amd74xx_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_AMD_TIMINGS) && defined(CONFIG_PROC_FS) */ - static unsigned int init_chipset_amd74xx(struct pci_dev *, const char *); static void init_hwif_amd74xx(ide_hwif_t *); diff -Nru a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c --- a/drivers/ide/pci/cmd64x.c Thu Feb 19 23:44:27 2004 +++ b/drivers/ide/pci/cmd64x.c Thu Feb 19 23:44:27 2004 @@ -667,7 +667,7 @@ if (!cmd64x_proc) { cmd64x_proc = 1; - ide_pci_register_host_proc(&cmd64x_procs[0]); + ide_pci_create_host_proc("cmd64x", cmd64x_get_info); } #endif /* DISPLAY_CMD64X_TIMINGS && CONFIG_PROC_FS */ diff -Nru a/drivers/ide/pci/cmd64x.h b/drivers/ide/pci/cmd64x.h --- a/drivers/ide/pci/cmd64x.h Thu Feb 19 23:44:24 2004 +++ b/drivers/ide/pci/cmd64x.h Thu Feb 19 23:44:24 2004 @@ -60,25 +60,6 @@ #define UDIDETCR1 0x7B #define DTPR1 0x7C -#if defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 cmd64x_proc; - -static char * print_cmd64x_get_info(char *, struct pci_dev *, int); -static int cmd64x_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t cmd64x_procs[] = { - { - .name = "cmd64x", - .set = 1, - .get_info = cmd64x_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_CMD64X_TIMINGS) && defined(CONFIG_PROC_FS) */ - static unsigned int init_chipset_cmd64x(struct pci_dev *, const char *); static void init_hwif_cmd64x(ide_hwif_t *); diff -Nru a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c --- a/drivers/ide/pci/cs5520.c Thu Feb 19 23:44:23 2004 +++ b/drivers/ide/pci/cs5520.c Thu Feb 19 23:44:23 2004 @@ -196,7 +196,7 @@ if (!cs5520_proc) { cs5520_proc = 1; bmide_dev = dev; - ide_pci_register_host_proc(&cs5520_procs[0]); + ide_pci_create_host_proc("cs5520", cs5520_get_info); } #endif /* DISPLAY_CS5520_TIMINGS && CONFIG_PROC_FS */ return 0; diff -Nru a/drivers/ide/pci/cs5520.h b/drivers/ide/pci/cs5520.h --- a/drivers/ide/pci/cs5520.h Thu Feb 19 23:44:28 2004 +++ b/drivers/ide/pci/cs5520.h Thu Feb 19 23:44:28 2004 @@ -7,24 +7,6 @@ #define DISPLAY_CS5520_TIMINGS -#if defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 cs5520_proc; - -static int cs5520_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t cs5520_procs[] = { - { - .name = "cs5520", - .set = 1, - .get_info = cs5520_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_CS5520_TIMINGS) && defined(CONFIG_PROC_FS) */ - static unsigned int init_chipset_cs5520(struct pci_dev *, const char *); static void init_hwif_cs5520(ide_hwif_t *); static void cs5520_init_setup_dma(struct pci_dev *dev, struct ide_pci_device_s *d, ide_hwif_t *hwif); diff -Nru a/drivers/ide/pci/cs5530.c b/drivers/ide/pci/cs5530.c --- a/drivers/ide/pci/cs5530.c Thu Feb 19 23:44:24 2004 +++ b/drivers/ide/pci/cs5530.c Thu Feb 19 23:44:24 2004 @@ -276,7 +276,7 @@ if (!cs5530_proc) { cs5530_proc = 1; bmide_dev = dev; - ide_pci_register_host_proc(&cs5530_procs[0]); + ide_pci_create_host_proc("cs5530", cs5530_get_info); } #endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ diff -Nru a/drivers/ide/pci/cs5530.h b/drivers/ide/pci/cs5530.h --- a/drivers/ide/pci/cs5530.h Thu Feb 19 23:44:22 2004 +++ b/drivers/ide/pci/cs5530.h Thu Feb 19 23:44:22 2004 @@ -7,24 +7,6 @@ #define DISPLAY_CS5530_TIMINGS -#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 cs5530_proc; - -static int cs5530_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t cs5530_procs[] = { - { - .name = "cs5530", - .set = 1, - .get_info = cs5530_get_info, - .parent = NULL, - }, -}; -#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ - static unsigned int init_chipset_cs5530(struct pci_dev *, const char *); static void init_hwif_cs5530(ide_hwif_t *); diff -Nru a/drivers/ide/pci/hpt34x.c b/drivers/ide/pci/hpt34x.c --- a/drivers/ide/pci/hpt34x.c Thu Feb 19 23:44:24 2004 +++ b/drivers/ide/pci/hpt34x.c Thu Feb 19 23:44:24 2004 @@ -282,7 +282,7 @@ if (!hpt34x_proc) { hpt34x_proc = 1; - ide_pci_register_host_proc(&hpt34x_procs[0]); + ide_pci_create_host_proc("hpt34x", hpt34x_get_info); } #endif /* DISPLAY_HPT34X_TIMINGS && CONFIG_PROC_FS */ diff -Nru a/drivers/ide/pci/hpt34x.h b/drivers/ide/pci/hpt34x.h --- a/drivers/ide/pci/hpt34x.h Thu Feb 19 23:44:22 2004 +++ b/drivers/ide/pci/hpt34x.h Thu Feb 19 23:44:22 2004 @@ -13,24 +13,6 @@ #undef DISPLAY_HPT34X_TIMINGS -#if defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 hpt34x_proc; - -static int hpt34x_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t hpt34x_procs[] = { - { - .name = "hpt34x", - .set = 1, - .get_info = hpt34x_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_HPT34X_TIMINGS) && defined(CONFIG_PROC_FS) */ - static unsigned int init_chipset_hpt34x(struct pci_dev *, const char *); static void init_hwif_hpt34x(ide_hwif_t *); diff -Nru a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c --- a/drivers/ide/pci/hpt366.c Thu Feb 19 23:44:25 2004 +++ b/drivers/ide/pci/hpt366.c Thu Feb 19 23:44:25 2004 @@ -972,7 +972,7 @@ if (!hpt366_proc) { hpt366_proc = 1; - ide_pci_register_host_proc(&hpt366_procs[0]); + ide_pci_create_host_proc("hpt366", hpt366_get_info); } #endif /* DISPLAY_HPT366_TIMINGS && CONFIG_PROC_FS */ diff -Nru a/drivers/ide/pci/hpt366.h b/drivers/ide/pci/hpt366.h --- a/drivers/ide/pci/hpt366.h Thu Feb 19 23:44:26 2004 +++ b/drivers/ide/pci/hpt366.h Thu Feb 19 23:44:26 2004 @@ -416,24 +416,6 @@ #define F_LOW_PCI_50 0x2d #define F_LOW_PCI_66 0x42 -#if defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 hpt366_proc; - -static int hpt366_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t hpt366_procs[] = { - { - .name = "hpt366", - .set = 1, - .get_info = hpt366_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_HPT366_TIMINGS) && defined(CONFIG_PROC_FS) */ - static void init_setup_hpt366(struct pci_dev *, ide_pci_device_t *); static void init_setup_hpt37x(struct pci_dev *, ide_pci_device_t *); static void init_setup_hpt374(struct pci_dev *, ide_pci_device_t *); diff -Nru a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c --- a/drivers/ide/pci/pdc202xx_new.c Thu Feb 19 23:44:27 2004 +++ b/drivers/ide/pci/pdc202xx_new.c Thu Feb 19 23:44:27 2004 @@ -574,7 +574,7 @@ if (!pdcnew_proc) { pdcnew_proc = 1; - ide_pci_register_host_proc(&pdcnew_procs[0]); + ide_pci_create_host_proc("pdcnew", pdcnew_get_info); } #endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ diff -Nru a/drivers/ide/pci/pdc202xx_new.h b/drivers/ide/pci/pdc202xx_new.h --- a/drivers/ide/pci/pdc202xx_new.h Thu Feb 19 23:44:23 2004 +++ b/drivers/ide/pci/pdc202xx_new.h Thu Feb 19 23:44:23 2004 @@ -164,25 +164,6 @@ #define DISPLAY_PDC202XX_TIMINGS -#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 pdcnew_proc; - -static int pdcnew_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t pdcnew_procs[] = { - { - .name = "pdcnew", - .set = 1, - .get_info = pdcnew_get_info, - .parent = NULL, - }, -}; -#endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ - - static void init_setup_pdcnew(struct pci_dev *, ide_pci_device_t *); static void init_setup_pdc20270(struct pci_dev *, ide_pci_device_t *); static void init_setup_pdc20276(struct pci_dev *dev, ide_pci_device_t *d); diff -Nru a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c --- a/drivers/ide/pci/pdc202xx_old.c Thu Feb 19 23:44:28 2004 +++ b/drivers/ide/pci/pdc202xx_old.c Thu Feb 19 23:44:28 2004 @@ -707,7 +707,7 @@ if (!pdc202xx_proc) { pdc202xx_proc = 1; - ide_pci_register_host_proc(&pdc202xx_procs[0]); + ide_pci_create_host_proc("pdc202xx", pdc202xx_get_info); } #endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ diff -Nru a/drivers/ide/pci/pdc202xx_old.h b/drivers/ide/pci/pdc202xx_old.h --- a/drivers/ide/pci/pdc202xx_old.h Thu Feb 19 23:44:22 2004 +++ b/drivers/ide/pci/pdc202xx_old.h Thu Feb 19 23:44:22 2004 @@ -199,25 +199,6 @@ #define DISPLAY_PDC202XX_TIMINGS -#if defined(DISPLAY_PDC202XX_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 pdc202xx_proc; - -static int pdc202xx_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t pdc202xx_procs[] = { - { - .name = "pdc202xx", - .set = 1, - .get_info = pdc202xx_get_info, - .parent = NULL, - }, -}; -#endif /* DISPLAY_PDC202XX_TIMINGS && CONFIG_PROC_FS */ - - static void init_setup_pdc202ata4(struct pci_dev *dev, ide_pci_device_t *d); static void init_setup_pdc20265(struct pci_dev *, ide_pci_device_t *); static void init_setup_pdc202xx(struct pci_dev *, ide_pci_device_t *); diff -Nru a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c --- a/drivers/ide/pci/piix.c Thu Feb 19 23:44:23 2004 +++ b/drivers/ide/pci/piix.c Thu Feb 19 23:44:23 2004 @@ -636,7 +636,7 @@ if (!piix_proc) { piix_proc = 1; - ide_pci_register_host_proc(&piix_procs[0]); + ide_pci_create_host_proc("piix", piix_get_info); } #endif /* DISPLAY_PIIX_TIMINGS && CONFIG_PROC_FS */ return 0; diff -Nru a/drivers/ide/pci/piix.h b/drivers/ide/pci/piix.h --- a/drivers/ide/pci/piix.h Thu Feb 19 23:44:23 2004 +++ b/drivers/ide/pci/piix.h Thu Feb 19 23:44:23 2004 @@ -9,24 +9,6 @@ #define DISPLAY_PIIX_TIMINGS -#if defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 piix_proc; - -static int piix_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t piix_procs[] = { - { - .name = "piix", - .set = 1, - .get_info = piix_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_PIIX_TIMINGS) && defined(CONFIG_PROC_FS) */ - static void init_setup_piix(struct pci_dev *, ide_pci_device_t *); static unsigned int __devinit init_chipset_piix(struct pci_dev *, const char *); static void init_hwif_piix(ide_hwif_t *); diff -Nru a/drivers/ide/pci/sc1200.c b/drivers/ide/pci/sc1200.c --- a/drivers/ide/pci/sc1200.c Thu Feb 19 23:44:26 2004 +++ b/drivers/ide/pci/sc1200.c Thu Feb 19 23:44:26 2004 @@ -515,7 +515,7 @@ if (!bmide_dev) { sc1200_proc = 1; bmide_dev = dev; - ide_pci_register_host_proc(&sc1200_procs[0]); + ide_pci_create_host_proc("sc1200", sc1200_get_info); } #endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */ return 0; diff -Nru a/drivers/ide/pci/sc1200.h b/drivers/ide/pci/sc1200.h --- a/drivers/ide/pci/sc1200.h Thu Feb 19 23:44:24 2004 +++ b/drivers/ide/pci/sc1200.h Thu Feb 19 23:44:24 2004 @@ -7,24 +7,6 @@ #define DISPLAY_SC1200_TIMINGS -#if defined(DISPLAY_SC1200_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 sc1200_proc; - -static int sc1200_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t sc1200_procs[] = { - { - .name = "sc1200", - .set = 1, - .get_info = sc1200_get_info, - .parent = NULL, - }, -}; -#endif /* DISPLAY_SC1200_TIMINGS && CONFIG_PROC_FS */ - static unsigned int init_chipset_sc1200(struct pci_dev *, const char *); static void init_hwif_sc1200(ide_hwif_t *); diff -Nru a/drivers/ide/pci/serverworks.c b/drivers/ide/pci/serverworks.c --- a/drivers/ide/pci/serverworks.c Thu Feb 19 23:44:22 2004 +++ b/drivers/ide/pci/serverworks.c Thu Feb 19 23:44:22 2004 @@ -621,7 +621,7 @@ if (!svwks_proc) { svwks_proc = 1; - ide_pci_register_host_proc(&svwks_procs[0]); + ide_pci_create_host_proc("svwks", svwks_get_info); } #endif /* DISPLAY_SVWKS_TIMINGS && CONFIG_PROC_FS */ diff -Nru a/drivers/ide/pci/serverworks.h b/drivers/ide/pci/serverworks.h --- a/drivers/ide/pci/serverworks.h Thu Feb 19 23:44:24 2004 +++ b/drivers/ide/pci/serverworks.h Thu Feb 19 23:44:24 2004 @@ -23,24 +23,6 @@ #define DISPLAY_SVWKS_TIMINGS 1 -#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 svwks_proc; - -static int svwks_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t svwks_procs[] = { -{ - .name = "svwks", - .set = 1, - .get_info = svwks_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */ - static void init_setup_svwks(struct pci_dev *, ide_pci_device_t *); static void init_setup_csb6(struct pci_dev *, ide_pci_device_t *); static unsigned int init_chipset_svwks(struct pci_dev *, const char *); diff -Nru a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c --- a/drivers/ide/pci/siimage.c Thu Feb 19 23:44:24 2004 +++ b/drivers/ide/pci/siimage.c Thu Feb 19 23:44:24 2004 @@ -785,7 +785,7 @@ if (!siimage_proc) { siimage_proc = 1; - ide_pci_register_host_proc(&siimage_procs[0]); + ide_pci_create_host_proc("siimage", siimage_get_info); } #endif /* DISPLAY_SIIMAGE_TIMINGS && CONFIG_PROC_FS */ } diff -Nru a/drivers/ide/pci/siimage.h b/drivers/ide/pci/siimage.h --- a/drivers/ide/pci/siimage.h Thu Feb 19 23:44:25 2004 +++ b/drivers/ide/pci/siimage.h Thu Feb 19 23:44:25 2004 @@ -21,26 +21,6 @@ #define siiprintk(x...) #endif - -#if defined(DISPLAY_SIIMAGE_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static char * print_siimage_get_info(char *, struct pci_dev *, int); -static int siimage_get_info(char *, char **, off_t, int); - -static u8 siimage_proc; - -static ide_pci_host_proc_t siimage_procs[] = { - { - .name = "siimage", - .set = 1, - .get_info = siimage_get_info, - .parent = NULL, - }, -}; -#endif /* DISPLAY_SIIMAGE_TIMINGS && CONFIG_PROC_FS */ - static unsigned int init_chipset_siimage(struct pci_dev *, const char *); static void init_iops_siimage(ide_hwif_t *); static void init_hwif_siimage(ide_hwif_t *); diff -Nru a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c --- a/drivers/ide/pci/sis5513.c Thu Feb 19 23:44:25 2004 +++ b/drivers/ide/pci/sis5513.c Thu Feb 19 23:44:25 2004 @@ -881,7 +881,7 @@ if (!sis_proc) { sis_proc = 1; bmide_dev = dev; - ide_pci_register_host_proc(&sis_procs[0]); + ide_pci_create_host_proc("sis", sis_get_info); } #endif } diff -Nru a/drivers/ide/pci/sis5513.h b/drivers/ide/pci/sis5513.h --- a/drivers/ide/pci/sis5513.h Thu Feb 19 23:44:26 2004 +++ b/drivers/ide/pci/sis5513.h Thu Feb 19 23:44:26 2004 @@ -7,24 +7,6 @@ #define DISPLAY_SIS_TIMINGS -#if defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 sis_proc; - -static int sis_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t sis_procs[] = { -{ - .name = "sis", - .set = 1, - .get_info = sis_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_SIS_TIMINGS) && defined(CONFIG_PROC_FS) */ - static unsigned int init_chipset_sis5513(struct pci_dev *, const char *); static void init_hwif_sis5513(ide_hwif_t *); diff -Nru a/drivers/ide/pci/slc90e66.c b/drivers/ide/pci/slc90e66.c --- a/drivers/ide/pci/slc90e66.c Thu Feb 19 23:44:27 2004 +++ b/drivers/ide/pci/slc90e66.c Thu Feb 19 23:44:27 2004 @@ -319,7 +319,7 @@ if (!slc90e66_proc) { slc90e66_proc = 1; bmide_dev = dev; - ide_pci_register_host_proc(&slc90e66_procs[0]); + ide_pci_create_host_proc("slc90e66", slc90e66_get_info); } #endif /* DISPLAY_SLC90E66_TIMINGS && CONFIG_PROC_FS */ return 0; diff -Nru a/drivers/ide/pci/slc90e66.h b/drivers/ide/pci/slc90e66.h --- a/drivers/ide/pci/slc90e66.h Thu Feb 19 23:44:24 2004 +++ b/drivers/ide/pci/slc90e66.h Thu Feb 19 23:44:24 2004 @@ -9,24 +9,6 @@ #define SLC90E66_DEBUG_DRIVE_INFO 0 -#if defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 slc90e66_proc; - -static int slc90e66_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t slc90e66_procs[] = { - { - .name = "slc90e66", - .set = 1, - .get_info = slc90e66_get_info, - .parent = NULL, - }, -}; -#endif /* defined(DISPLAY_SLC90E66_TIMINGS) && defined(CONFIG_PROC_FS) */ - static unsigned int init_chipset_slc90e66(struct pci_dev *, const char *); static void init_hwif_slc90e66(ide_hwif_t *); diff -Nru a/drivers/ide/pci/triflex.c b/drivers/ide/pci/triflex.c --- a/drivers/ide/pci/triflex.c Thu Feb 19 23:44:24 2004 +++ b/drivers/ide/pci/triflex.c Thu Feb 19 23:44:24 2004 @@ -212,7 +212,7 @@ const char *name) { #ifdef CONFIG_PROC_FS - ide_pci_register_host_proc(&triflex_proc); + ide_pci_create_host_proc("triflex", triflex_get_info); #endif return 0; } diff -Nru a/drivers/ide/pci/triflex.h b/drivers/ide/pci/triflex.h --- a/drivers/ide/pci/triflex.h Thu Feb 19 23:44:27 2004 +++ b/drivers/ide/pci/triflex.h Thu Feb 19 23:44:27 2004 @@ -14,15 +14,6 @@ static unsigned int __devinit init_chipset_triflex(struct pci_dev *, const char *); static void init_hwif_triflex(ide_hwif_t *); -#ifdef CONFIG_PROC_FS -static int triflex_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t triflex_proc = { - .name = "triflex", - .set = 1, - .get_info = triflex_get_info, -}; -#endif static ide_pci_device_t triflex_devices[] __devinitdata = { { diff -Nru a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c --- a/drivers/ide/pci/via82cxxx.c Thu Feb 19 23:44:22 2004 +++ b/drivers/ide/pci/via82cxxx.c Thu Feb 19 23:44:22 2004 @@ -567,7 +567,7 @@ via_base = pci_resource_start(dev, 4); bmide_dev = dev; isa_dev = isa; - ide_pci_register_host_proc(&via_procs[0]); + ide_pci_create_host_proc("via", via_get_info); via_proc = 1; } #endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS */ diff -Nru a/drivers/ide/pci/via82cxxx.h b/drivers/ide/pci/via82cxxx.h --- a/drivers/ide/pci/via82cxxx.h Thu Feb 19 23:44:26 2004 +++ b/drivers/ide/pci/via82cxxx.h Thu Feb 19 23:44:26 2004 @@ -7,24 +7,6 @@ #define DISPLAY_VIA_TIMINGS -#if defined(DISPLAY_VIA_TIMINGS) && defined(CONFIG_PROC_FS) -#include -#include - -static u8 via_proc; - -static int via_get_info(char *, char **, off_t, int); - -static ide_pci_host_proc_t via_procs[] = { - { - .name = "via", - .set = 1, - .get_info = via_get_info, - .parent = NULL, - }, -}; -#endif /* DISPLAY_VIA_TIMINGS && CONFIG_PROC_FS */ - static unsigned int init_chipset_via82cxxx(struct pci_dev *, const char *); static void init_hwif_via82cxxx(ide_hwif_t *); diff -Nru a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c --- a/drivers/ide/ppc/pmac.c Thu Feb 19 23:44:23 2004 +++ b/drivers/ide/ppc/pmac.c Thu Feb 19 23:44:23 2004 @@ -55,7 +55,7 @@ #define IDE_PMAC_DEBUG -#define DMA_WAIT_TIMEOUT 100 +#define DMA_WAIT_TIMEOUT 50 typedef struct pmac_ide_hwif { unsigned long regbase; @@ -2026,8 +2026,11 @@ dstat = readl(&dma->status); writel(((RUN|WAKE|DEAD) << 16), &dma->control); pmac_ide_destroy_dmatable(drive); - /* verify good dma status */ - return (dstat & (RUN|DEAD|ACTIVE)) != RUN; + /* verify good dma status. we don't check for ACTIVE beeing 0. We should... + * in theory, but with ATAPI decices doing buffer underruns, that would + * cause us to disable DMA, which isn't what we want + */ + return (dstat & (RUN|DEAD)) != RUN; } /* @@ -2041,7 +2044,7 @@ { pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)HWIF(drive)->hwif_data; volatile struct dbdma_regs *dma; - unsigned long status; + unsigned long status, timeout; if (pmif == NULL) return 0; @@ -2057,17 +2060,8 @@ * - The dbdma fifo hasn't yet finished flushing to * to system memory when the disk interrupt occurs. * - * The trick here is to increment drive->waiting_for_dma, - * and return as if no interrupt occurred. If the counter - * reach a certain timeout value, we then return 1. If - * we really got the interrupt, it will happen right away - * again. - * Apple's solution here may be more elegant. They issue - * a DMA channel interrupt (a separate irq line) via a DBDMA - * NOP command just before the STOP, and wait for both the - * disk and DBDMA interrupts to have completed. */ - + /* If ACTIVE is cleared, the STOP command have passed and * transfer is complete. */ @@ -2079,15 +2073,26 @@ called while not waiting\n", HWIF(drive)->index); /* If dbdma didn't execute the STOP command yet, the - * active bit is still set */ - drive->waiting_for_dma++; - if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) { - printk(KERN_WARNING "ide%d, timeout waiting \ - for dbdma command stop\n", HWIF(drive)->index); - return 1; - } - udelay(5); - return 0; + * active bit is still set. We consider that we aren't + * sharing interrupts (which is hopefully the case with + * those controllers) and so we just try to flush the + * channel for pending data in the fifo + */ + udelay(1); + writel((FLUSH << 16) | FLUSH, &dma->control); + timeout = 0; + for (;;) { + udelay(1); + status = readl(&dma->status); + if ((status & FLUSH) == 0) + break; + if (++timeout > 100) { + printk(KERN_WARNING "ide%d, ide_dma_test_irq \ + timeout flushing channel\n", HWIF(drive)->index); + break; + } + } + return 1; } static int __pmac diff -Nru a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig --- a/drivers/isdn/Kconfig Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/Kconfig Thu Feb 19 23:44:28 2004 @@ -4,8 +4,8 @@ menu "ISDN subsystem" -config ISDN_BOOL - bool "ISDN support" +config ISDN + tristate "ISDN support" depends on NET ---help--- ISDN ("Integrated Services Digital Networks", called RNIS in France) @@ -22,9 +22,9 @@ menu "Old ISDN4Linux" - depends on NET && ISDN_BOOL && BROKEN_ON_SMP + depends on NET && ISDN -config ISDN +config ISDN_I4L tristate "Old ISDN4Linux (obsolete)" ---help--- This driver allows you to use an ISDN-card for networking @@ -41,18 +41,18 @@ Therefore the old ISDN4Linux layer is becoming obsolete. It is still usable, though, if you select this option. -if ISDN +if ISDN_I4L source "drivers/isdn/i4l/Kconfig" endif endmenu comment "CAPI subsystem" - depends on NET && ISDN_BOOL + depends on NET && ISDN config ISDN_CAPI tristate "CAPI2.0 support" - depends on ISDN_BOOL + depends on ISDN help This provides the CAPI (Common ISDN Application Programming Interface, a standard making it easy for programs to access ISDN diff -Nru a/drivers/isdn/Makefile b/drivers/isdn/Makefile --- a/drivers/isdn/Makefile Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/Makefile Thu Feb 19 23:44:28 2004 @@ -2,7 +2,7 @@ # Object files in subdirectories -obj-$(CONFIG_ISDN) += i4l/ +obj-$(CONFIG_ISDN_I4L) += i4l/ obj-$(CONFIG_ISDN_CAPI) += capi/ obj-$(CONFIG_ISDN_CAPI) += hardware/ obj-$(CONFIG_ISDN_DIVERSION) += divert/ diff -Nru a/drivers/isdn/act2000/Kconfig b/drivers/isdn/act2000/Kconfig --- a/drivers/isdn/act2000/Kconfig Thu Feb 19 23:44:26 2004 +++ b/drivers/isdn/act2000/Kconfig Thu Feb 19 23:44:26 2004 @@ -3,7 +3,7 @@ # config ISDN_DRV_ACT2000 tristate "IBM Active 2000 support" - depends on ISDN && ISA + depends on ISDN_I4L && ISA help Say Y here if you have an IBM Active 2000 ISDN card. In order to use this card, additional firmware is necessary, which has to be loaded diff -Nru a/drivers/isdn/act2000/act2000.h b/drivers/isdn/act2000/act2000.h --- a/drivers/isdn/act2000/act2000.h Thu Feb 19 23:44:25 2004 +++ b/drivers/isdn/act2000/act2000.h Thu Feb 19 23:44:25 2004 @@ -147,34 +147,36 @@ * Per card driver data */ typedef struct act2000_card { - unsigned short port; /* Base-port-address */ - unsigned short irq; /* Interrupt */ - u_char ptype; /* Protocol type (1TR6 or Euro) */ - u_char bus; /* Cardtype (ISA, MCA, PCMCIA) */ - struct act2000_card *next; /* Pointer to next device struct */ - int myid; /* Driver-Nr. assigned by linklevel */ - unsigned long flags; /* Statusflags */ - unsigned long ilock; /* Semaphores for IRQ-Routines */ - struct sk_buff_head rcvq; /* Receive-Message queue */ - struct sk_buff_head sndq; /* Send-Message queue */ - struct sk_buff_head ackq; /* Data-Ack-Message queue */ - u_char *ack_msg; /* Ptr to User Data in User skb */ - __u16 need_b3ack; /* Flag: Need ACK for current skb */ - struct sk_buff *sbuf; /* skb which is currently sent */ - struct timer_list ptimer; /* Poll timer */ - struct work_struct snd_tq; /* Task struct for xmit bh */ - struct work_struct rcv_tq; /* Task struct for rcv bh */ - struct work_struct poll_tq; /* Task struct for polled rcv bh */ + unsigned short port; /* Base-port-address */ + unsigned short irq; /* Interrupt */ + u_char ptype; /* Protocol type (1TR6 or Euro) */ + u_char bus; /* Cardtype (ISA, MCA, PCMCIA) */ + struct act2000_card *next; /* Pointer to next device struct */ + spinlock_t lock; /* protect critical operations */ + int myid; /* Driver-Nr. assigned by linklevel */ + unsigned long flags; /* Statusflags */ + unsigned long ilock; /* Semaphores for IRQ-Routines */ + struct sk_buff_head rcvq; /* Receive-Message queue */ + struct sk_buff_head sndq; /* Send-Message queue */ + struct sk_buff_head ackq; /* Data-Ack-Message queue */ + u_char *ack_msg; /* Ptr to User Data in User skb */ + __u16 need_b3ack; /* Flag: Need ACK for current skb */ + struct sk_buff *sbuf; /* skb which is currently sent */ + struct timer_list ptimer; /* Poll timer */ + struct work_struct snd_tq; /* Task struct for xmit bh */ + struct work_struct rcv_tq; /* Task struct for rcv bh */ + struct work_struct poll_tq; /* Task struct for polled rcv bh */ msn_entry *msn_list; - unsigned short msgnum; /* Message number fur sending */ - act2000_chan bch[ACT2000_BCH]; /* B-Channel status/control */ - char status_buf[256]; /* Buffer for status messages */ + unsigned short msgnum; /* Message number for sending */ + spinlock_t mnlock; /* lock for msgnum */ + act2000_chan bch[ACT2000_BCH]; /* B-Channel status/control */ + char status_buf[256]; /* Buffer for status messages */ char *status_buf_read; char *status_buf_write; char *status_buf_end; - irq_data idat; /* Data used for IRQ handler */ - isdn_if interface; /* Interface to upper layer */ - char regname[35]; /* Name used for request_region */ + irq_data idat; /* Data used for IRQ handler */ + isdn_if interface; /* Interface to upper layer */ + char regname[35]; /* Name used for request_region */ } act2000_card; extern __inline__ void act2000_schedule_tx(act2000_card *card) diff -Nru a/drivers/isdn/act2000/act2000_isa.c b/drivers/isdn/act2000/act2000_isa.c --- a/drivers/isdn/act2000/act2000_isa.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/act2000/act2000_isa.c Thu Feb 19 23:44:24 2004 @@ -21,10 +21,8 @@ static void act2000_isa_delay(long t) { - sti(); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(t); - sti(); } /* @@ -64,8 +62,10 @@ { int ret = 0; - if (!check_region(portbase, ISA_REGION)) + if (request_region(portbase, ACT2000_PORTLEN, "act2000isa")) { ret = act2000_isa_reset(portbase); + release_region(portbase, ISA_REGION); + } return ret; } @@ -177,14 +177,13 @@ release_region(card->port, ISA_REGION); card->flags &= ~ACT2000_FLAGS_PVALID; } - if (!check_region(portbase, ISA_REGION)) { - if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL) - return -EIO; + if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL) + return -EBUSY; + else { card->port = portbase; card->flags |= ACT2000_FLAGS_PVALID; return 0; } - return -EBUSY; } /* @@ -195,8 +194,7 @@ { unsigned long flags; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); if (card->flags & ACT2000_FLAGS_IVALID) { free_irq(card->irq, NULL); irq2card_map[card->irq] = NULL; @@ -205,7 +203,7 @@ if (card->flags & ACT2000_FLAGS_PVALID) release_region(card->port, ISA_REGION); card->flags &= ~ACT2000_FLAGS_PVALID; - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); } static int @@ -316,8 +314,7 @@ if (test_and_set_bit(ACT2000_LOCK_TX, (void *) &card->ilock) != 0) return; while (1) { - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); if (!(card->sbuf)) { if ((card->sbuf = skb_dequeue(&card->sndq))) { card->ack_msg = card->sbuf->data; @@ -330,7 +327,7 @@ } } } - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); if (!(card->sbuf)) { /* No more data to send */ test_and_clear_bit(ACT2000_LOCK_TX, (void *) &card->ilock); diff -Nru a/drivers/isdn/act2000/capi.c b/drivers/isdn/act2000/capi.c --- a/drivers/isdn/act2000/capi.c Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/act2000/capi.c Thu Feb 19 23:44:28 2004 @@ -591,10 +591,9 @@ struct actcapi_msg *m; int ret = 0; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); skb = skb_peek(&card->ackq); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); if (!skb) { printk(KERN_WARNING "act2000: handle_ack nothing found!\n"); return 0; @@ -614,10 +613,9 @@ chan->queued = 0; return ret; } - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); tmp = skb_peek((struct sk_buff_head *)tmp); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); if ((tmp == skb) || (tmp == NULL)) { /* reached end of queue */ printk(KERN_WARNING "act2000: handle_ack nothing found!\n"); diff -Nru a/drivers/isdn/act2000/capi.h b/drivers/isdn/act2000/capi.h --- a/drivers/isdn/act2000/capi.h Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/act2000/capi.h Thu Feb 19 23:44:28 2004 @@ -336,12 +336,11 @@ unsigned long flags; unsigned short n; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->mnlock, flags); n = card->msgnum; card->msgnum++; card->msgnum &= 0x7fff; - restore_flags(flags); + spin_unlock_irqrestore(&card->mnlock, flags); return n; } #define DEBUG_MSG diff -Nru a/drivers/isdn/act2000/module.c b/drivers/isdn/act2000/module.c --- a/drivers/isdn/act2000/module.c Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/act2000/module.c Thu Feb 19 23:44:27 2004 @@ -62,19 +62,18 @@ static void act2000_clear_msn(act2000_card *card) { - struct msn_entry *p = card->msn_list; - struct msn_entry *q; + struct msn_entry *p = card->msn_list; + struct msn_entry *q; unsigned long flags; - save_flags(flags); - cli(); - card->msn_list = NULL; - restore_flags(flags); - while (p) { - q = p->next; - kfree(p); - p = q; - } + spin_lock_irqsave(&card->lock, flags); + card->msn_list = NULL; + spin_unlock_irqrestore(&card->lock, flags); + while (p) { + q = p->next; + kfree(p); + p = q; + } } /* @@ -143,13 +142,12 @@ /* Delete a single MSN */ while (p) { if (p->eaz == eazmsn[0]) { - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); if (q) q->next = p->next; else card->msn_list = p->next; - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); kfree(p); printk(KERN_DEBUG "Mapping for EAZ %c deleted\n", @@ -165,10 +163,9 @@ while (p) { /* Found in list, replace MSN */ if (p->eaz == eazmsn[0]) { - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); strcpy(p->msn, &eazmsn[1]); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); printk(KERN_DEBUG "Mapping for EAZ %c changed to %s\n", eazmsn[0], @@ -184,10 +181,9 @@ p->eaz = eazmsn[0]; strcpy(p->msn, &eazmsn[1]); p->next = card->msn_list; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); card->msn_list = p; - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); printk(KERN_DEBUG "Mapping %c -> %s added\n", eazmsn[0], @@ -232,10 +228,9 @@ unsigned long flags; act2000_receive(card); - save_flags(flags); - cli(); - mod_timer(&card->ptimer, jiffies+3); - restore_flags(flags); + spin_lock_irqsave(&card->lock, flags); + mod_timer(&card->ptimer, jiffies+3); + spin_unlock_irqrestore(&card->lock, flags); } static int @@ -311,10 +306,9 @@ return -ENODEV; if (!(chan = find_channel(card, c->arg & 0x0f))) break; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); if (chan->fsm_state != ACT2000_STATE_NULL) { - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); printk(KERN_WARNING "Dial on channel with state %d\n", chan->fsm_state); return -EBUSY; @@ -325,7 +319,7 @@ tmp[0] = c->parm.setup.eazmsn[0]; chan->fsm_state = ACT2000_STATE_OCALL; chan->callref = 0xffff; - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); ret = actcapi_connect_req(card, chan, c->parm.setup.phone, tmp[0], c->parm.setup.si1, c->parm.setup.si2); @@ -580,6 +574,8 @@ return; } memset((char *) card, 0, sizeof(act2000_card)); + spin_lock_init(&card->lock); + spin_lock_init(&card->mnlock); skb_queue_head_init(&card->sndq); skb_queue_head_init(&card->rcvq); skb_queue_head_init(&card->ackq); diff -Nru a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig --- a/drivers/isdn/capi/Kconfig Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/capi/Kconfig Thu Feb 19 23:44:24 2004 @@ -44,7 +44,7 @@ config ISDN_CAPI_CAPIDRV tristate "CAPI2.0 capidrv interface support" - depends on ISDN_CAPI && ISDN + depends on ISDN_CAPI && ISDN_I4L help This option provides the glue code to hook up CAPI driven cards to the legacy isdn4linux link layer. If you have a card which is diff -Nru a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c --- a/drivers/isdn/capi/capi.c Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/capi/capi.c Thu Feb 19 23:44:28 2004 @@ -1,4 +1,4 @@ -/* $Id: capi.c,v 1.1.4.1.2.2 2001/12/21 15:00:17 kai Exp $ +/* $Id: capi.c,v 1.1.2.3 2004/01/16 21:09:26 keil Exp $ * * CAPI 2.0 Interface for Linux * @@ -44,7 +44,7 @@ #include "capifs.h" #endif -static char *revision = "$Revision: 1.1.4.1.2.2 $"; +static char *revision = "$Revision: 1.1.2.3 $"; MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface"); MODULE_AUTHOR("Carsten Paeth"); @@ -203,7 +203,7 @@ struct list_head *l; unsigned int minor = 0; unsigned long flags; - + mp = kmalloc(sizeof(*mp), GFP_ATOMIC); if (!mp) { printk(KERN_ERR "capi: can't alloc capiminor\n"); @@ -220,19 +220,24 @@ skb_queue_head_init(&mp->outqueue); write_lock_irqsave(&capiminor_list_lock, flags); - list_for_each(l, &capiminor_list) { - p = list_entry(l, struct capiminor, list); - if (p->minor > minor) { - mp->minor = minor; - list_add_tail(&mp->list, &p->list); - break; + if (list_empty(&capiminor_list)) { + list_add(&mp->list, &capiminor_list); + write_unlock_irqrestore(&capiminor_list_lock, flags); + } else { + list_for_each(l, &capiminor_list) { + p = list_entry(l, struct capiminor, list); + if (p->minor > minor) { + mp->minor = minor; + list_add_tail(&mp->list, &p->list); + break; + } + minor++; + } + write_unlock_irqrestore(&capiminor_list_lock, flags); + if (l == &capiminor_list) { + kfree(mp); + return NULL; } - minor++; - } - write_unlock_irqrestore(&capiminor_list_lock, flags); - if (l == &capiminor_list) { - kfree(mp); - return NULL; } return mp; } @@ -297,7 +302,7 @@ printk(KERN_DEBUG "set mp->nccip\n"); #endif #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) - capifs_new_ncci(0, mp->minor, MKDEV(capi_ttymajor, mp->minor)); + capifs_new_ncci(mp->minor, MKDEV(capi_ttymajor, mp->minor)); #endif } #endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */ @@ -322,8 +327,7 @@ #ifdef CONFIG_ISDN_CAPI_MIDDLEWARE if ((mp = np->minorp) != 0) { #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE) - capifs_free_ncci('r', mp->minor); - capifs_free_ncci(0, mp->minor); + capifs_free_ncci(mp->minor); #endif if (mp->tty) { mp->nccip = 0; diff -Nru a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c --- a/drivers/isdn/capi/capidrv.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/capi/capidrv.c Thu Feb 19 23:44:24 2004 @@ -1,4 +1,4 @@ -/* $Id: capidrv.c,v 1.39.6.7 2001/09/23 22:24:33 kai Exp $ +/* $Id: capidrv.c,v 1.1.2.2 2004/01/12 23:17:24 keil Exp $ * * ISDN4Linux Driver, using capi20 interface (kernelcapi) * @@ -34,7 +34,7 @@ #include #include "capidrv.h" -static char *revision = "$Revision: 1.39.6.7 $"; +static char *revision = "$Revision: 1.1.2.2 $"; static int debugmode = 0; MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux"); @@ -1263,6 +1263,10 @@ goto ignored; case CAPI_DATA_B3_CONF: /* ncci */ + if (cmsg->Info) { + printk(KERN_WARNING "CAPI_DATA_B3_CONF: Info %x - %s\n", + cmsg->Info, capi_info2str(cmsg->Info)); + } if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) goto notfound; @@ -1368,7 +1372,7 @@ static void capidrv_recv_message(struct capi20_appl *ap, struct sk_buff *skb) { capi_message2cmsg(&s_cmsg, skb->data); - if (debugmode > 2) + if (debugmode > 3) printk(KERN_DEBUG "capidrv_signal: applid=%d %s\n", ap->applid, capi_cmsg2str(&s_cmsg)); @@ -1825,7 +1829,7 @@ id); return 0; } - if (debugmode > 1) + if (debugmode > 4) printk(KERN_DEBUG "capidrv-%d: sendbuf len=%d skb=%p doack=%d\n", card->contrnr, len, skb, doack); bchan = &card->bchans[channel % card->nbchan]; @@ -1866,6 +1870,9 @@ nccip->datahandle++; return len; } + if (debugmode > 3) + printk(KERN_DEBUG "capidrv-%d: sendbuf putmsg ret(%x) - %s\n", + card->contrnr, errcode, capi_info2str(errcode)); (void)capidrv_del_ack(nccip, datahandle); dev_kfree_skb(nskb); return errcode == CAPI_SENDQUEUEFULL ? 0 : -1; @@ -1876,6 +1883,9 @@ nccip->datahandle++; return len; } + if (debugmode > 3) + printk(KERN_DEBUG "capidrv-%d: sendbuf putmsg ret(%x) - %s\n", + card->contrnr, errcode, capi_info2str(errcode)); skb_pull(skb, msglen); (void)capidrv_del_ack(nccip, datahandle); return errcode == CAPI_SENDQUEUEFULL ? 0 : -1; diff -Nru a/drivers/isdn/capi/capifs.c b/drivers/isdn/capi/capifs.c --- a/drivers/isdn/capi/capifs.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/capi/capifs.c Thu Feb 19 23:44:24 2004 @@ -1,4 +1,4 @@ -/* $Id: capifs.c,v 1.14.6.8 2001/09/23 22:24:33 kai Exp $ +/* $Id: capifs.c,v 1.1.2.3 2004/01/16 21:09:26 keil Exp $ * * Copyright 2000 by Carsten Paeth * @@ -20,99 +20,75 @@ MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); -static char *revision = "$Revision: 1.14.6.8 $"; +/* ------------------------------------------------------------------ */ + +static char *revision = "$Revision: 1.1.2.3 $"; + +/* ------------------------------------------------------------------ */ -struct options { +#define CAPIFS_SUPER_MAGIC (('C'<<8)|'N') + +static struct vfsmount *capifs_mnt; +static struct dentry *capifs_root; + +static struct { int setuid; int setgid; uid_t uid; gid_t gid; umode_t mode; -}; -static struct options options = {.mode = 0600}; - -#define CAPIFS_SUPER_MAGIC (('C'<<8)|'N') +} config = {.mode = 0600}; /* ------------------------------------------------------------------ */ - -static int capifs_parse_options(char *s, struct options *p) +static int capifs_remount(struct super_block *s, int *flags, char *data) { int setuid = 0; int setgid = 0; uid_t uid = 0; gid_t gid = 0; umode_t mode = 0600; - char *this_char, *value; + char *this_char; - if (!s) - return 0; - - while ((this_char = strsep(&s, ",")) != NULL) { + this_char = NULL; + while ((this_char = strsep(&data, ",")) != NULL) { + int n; + char dummy; if (!*this_char) continue; - if ((value = strchr(this_char,'=')) != NULL) - *value++ = 0; - if (!strcmp(this_char,"uid")) { - if (!value || !*value) - return 1; - uid = simple_strtoul(value,&value,0); - if (*value) - return 1; + if (sscanf(this_char, "uid=%i%c", &n, &dummy) == 1) { setuid = 1; - } - else if (!strcmp(this_char,"gid")) { - if (!value || !*value) - return 1; - gid = simple_strtoul(value,&value,0); - if (*value) - return 1; + uid = n; + } else if (sscanf(this_char, "gid=%i%c", &n, &dummy) == 1) { setgid = 1; + gid = n; + } else if (sscanf(this_char, "mode=%o%c", &n, &dummy) == 1) + mode = n & ~S_IFMT; + else { + printk("capifs: called with bogus options\n"); + return -EINVAL; } - else if (!strcmp(this_char,"mode")) { - if (!value || !*value) - return 1; - mode = simple_strtoul(value,&value,8); - if (*value) - return 1; - } - } - p->setuid = setuid; - p->setgid = setgid; - p->uid = uid; - p->gid = gid; - p->mode = mode & ~S_IFMT; - - return 0; -} - -static int capifs_remount(struct super_block *s, int *flags, char *data) -{ - struct options new; - if (capifs_parse_options(data, &new)) { - printk("capifs: called with bogus options\n"); - return -EINVAL; } - options = new; + config.setuid = setuid; + config.setgid = setgid; + config.uid = uid; + config.gid = gid; + config.mode = mode; return 0; } - static struct super_operations capifs_sops = { .statfs = simple_statfs, .remount_fs = capifs_remount, }; -static int capifs_fill_super(struct super_block *s, void *data, int silent) + +static int +capifs_fill_super(struct super_block *s, void *data, int silent) { struct inode * inode; - if (capifs_parse_options(data, &options)) { - printk("capifs: called with bogus options\n"); - return -EINVAL; - } - s->s_blocksize = 1024; s->s_blocksize_bits = 10; s->s_magic = CAPIFS_SUPER_MAGIC; @@ -120,24 +96,25 @@ inode = new_inode(s); if (!inode) - return -ENOMEM; + goto fail; + inode->i_ino = 1; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; inode->i_blocks = 0; inode->i_blksize = 1024; inode->i_uid = inode->i_gid = 0; - inode->i_ino = 1; inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR; inode->i_op = &simple_dir_inode_operations; inode->i_fop = &simple_dir_operations; inode->i_nlink = 2; - s->s_root = d_alloc_root(inode); - if (!s->s_root) { - printk("capifs: get root dentry failed\n"); - iput(inode); - return -ENOMEM; - } - return 0; + capifs_root = s->s_root = d_alloc_root(inode); + if (s->s_root) + return 0; + + printk("capifs: get root dentry failed\n"); + iput(inode); +fail: + return -ENOMEM; } static struct super_block *capifs_get_sb(struct file_system_type *fs_type, @@ -153,78 +130,48 @@ .kill_sb = kill_anon_super, }; -static struct vfsmount *capifs_mnt; -static int entry_count; - -static int grab_instance(void) -{ - return simple_pin_fs("capifs", &capifs_mnt, &entry_count); -} - -static void drop_instance(void) -{ - return simple_release_fs(&capifs_mnt, &entry_count); -} - -static struct dentry *get_node(int type, int num) +static struct dentry *get_node(int num) { char s[10]; - int len; - struct dentry *root = capifs_mnt->mnt_root; - if (type) - len = sprintf(s, "%d", num); - else - len = sprintf(s, "%c%d", type, num); + struct dentry *root = capifs_root; down(&root->d_inode->i_sem); - return lookup_one_len(s, root, len); + return lookup_one_len(s, root, sprintf(s, "%d", num)); } -void capifs_new_ncci(char type, unsigned int num, dev_t device) +void capifs_new_ncci(unsigned int number, dev_t device) { - struct super_block *sb; struct dentry *dentry; - struct inode *inode; - - if (grab_instance() < 0) + struct inode *inode = new_inode(capifs_mnt->mnt_sb); + if (!inode) return; - sb = capifs_mnt->mnt_sb; - inode = new_inode(sb); - if (inode) { - inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; - inode->i_blocks = 0; - inode->i_blksize = 1024; - inode->i_uid = options.setuid ? options.uid : current->fsuid; - inode->i_gid = options.setgid ? options.gid : current->fsgid; - inode->i_nlink = 1; - init_special_inode(inode, S_IFCHR | options.mode, device); - dentry = get_node(type, num); - if (!IS_ERR(dentry) && !dentry->d_inode) { - grab_instance(); - d_instantiate(dentry, inode); - } else - iput(inode); - up(&sb->s_root->d_inode->i_sem); - } - drop_instance(); + inode->i_ino = number+2; + inode->i_blksize = 1024; + inode->i_uid = config.setuid ? config.uid : current->fsuid; + inode->i_gid = config.setgid ? config.gid : current->fsgid; + inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; + init_special_inode(inode, S_IFCHR|config.mode, device); + //inode->i_op = &capifs_file_inode_operations; + + dentry = get_node(number); + if (!IS_ERR(dentry) && !dentry->d_inode) + d_instantiate(dentry, inode); + up(&capifs_root->d_inode->i_sem); } -void capifs_free_ncci(char type, unsigned int num) +void capifs_free_ncci(unsigned int number) { - if (grab_instance() == 0) { - struct dentry *dentry = get_node(type, num); - if (!IS_ERR(dentry)) { - struct inode *inode = dentry->d_inode; - if (inode) { - inode->i_nlink--; - d_delete(dentry); - dput(dentry); - drop_instance(); - } + struct dentry *dentry = get_node(number); + + if (!IS_ERR(dentry)) { + struct inode *inode = dentry->d_inode; + if (inode) { + inode->i_nlink--; + d_delete(dentry); dput(dentry); } - up(&capifs_mnt->mnt_root->d_inode->i_sem); - drop_instance(); + dput(dentry); } + up(&capifs_root->d_inode->i_sem); } static int __init capifs_init(void) @@ -241,14 +188,20 @@ strcpy(rev, "1.0"); err = register_filesystem(&capifs_fs_type); + if (!err) { + capifs_mnt = kern_mount(&capifs_fs_type); + if (IS_ERR(capifs_mnt)) + err = PTR_ERR(capifs_mnt); + } if (!err) printk(KERN_NOTICE "capifs: Rev %s\n", rev); - return 0; + return err; } static void __exit capifs_exit(void) { unregister_filesystem(&capifs_fs_type); + mntput(capifs_mnt); } EXPORT_SYMBOL(capifs_new_ncci); diff -Nru a/drivers/isdn/capi/capifs.h b/drivers/isdn/capi/capifs.h --- a/drivers/isdn/capi/capifs.h Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/capi/capifs.h Thu Feb 19 23:44:23 2004 @@ -1,4 +1,4 @@ -/* $Id: capifs.h,v 1.2.6.2 2001/09/23 22:24:33 kai Exp $ +/* $Id: capifs.h,v 1.1.2.2 2004/01/16 21:09:26 keil Exp $ * * Copyright 2000 by Carsten Paeth * @@ -7,5 +7,5 @@ * */ -void capifs_new_ncci(char type, unsigned int num, dev_t device); -void capifs_free_ncci(char type, unsigned int num); +void capifs_new_ncci(unsigned int num, dev_t device); +void capifs_free_ncci(unsigned int num); diff -Nru a/drivers/isdn/capi/kcapi.c b/drivers/isdn/capi/kcapi.c --- a/drivers/isdn/capi/kcapi.c Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/capi/kcapi.c Thu Feb 19 23:44:27 2004 @@ -1,4 +1,4 @@ -/* $Id: kcapi.c,v 1.21.6.8 2001/09/23 22:24:33 kai Exp $ +/* $Id: kcapi.c,v 1.1.2.4 2004/02/10 01:07:11 keil Exp $ * * Kernel CAPI 2.0 Module * @@ -31,7 +31,7 @@ #include #endif -static char *revision = "$Revision: 1.21.6.8 $"; +static char *revision = "$Revision: 1.1.2.4 $"; /* ------------------------------------------------------------- */ @@ -61,7 +61,7 @@ #define NCCI2CTRL(ncci) (((ncci) >> 24) & 0x7f) LIST_HEAD(capi_drivers); -spinlock_t capi_drivers_lock = SPIN_LOCK_UNLOCKED; +rwlock_t capi_drivers_list_lock = RW_LOCK_UNLOCKED; struct capi20_appl *capi_applications[CAPI_MAXAPPL]; struct capi_ctr *capi_cards[CAPI_MAXCONTR]; @@ -309,12 +309,10 @@ continue; } - if ( CAPIMSG_COMMAND(skb->data) == CAPI_DATA_B3 - && CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) { + if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_IND) ap->nrecvdatapkt++; - } else { + else ap->nrecvctlpkt++; - } ap->recv_message(ap, skb); } } @@ -498,6 +496,28 @@ EXPORT_SYMBOL(detach_capi_ctr); +void register_capi_driver(struct capi_driver *driver) +{ + unsigned long flags; + + write_lock_irqsave(&capi_drivers_list_lock, flags); + list_add_tail(&driver->list, &capi_drivers); + write_unlock_irqrestore(&capi_drivers_list_lock, flags); +} + +EXPORT_SYMBOL(register_capi_driver); + +void unregister_capi_driver(struct capi_driver *driver) +{ + unsigned long flags; + + write_lock_irqsave(&capi_drivers_list_lock, flags); + list_del(&driver->list); + write_unlock_irqrestore(&capi_drivers_list_lock, flags); +} + +EXPORT_SYMBOL(unregister_capi_driver); + /* ------------------------------------------------------------- */ /* -------- CAPI2.0 Interface ---------------------------------- */ /* ------------------------------------------------------------- */ @@ -704,12 +724,68 @@ static int old_capi_manufacturer(unsigned int cmd, void *data) { avmb1_loadandconfigdef ldef; + avmb1_extcarddef cdef; avmb1_resetdef rdef; + capicardparams cparams; struct capi_ctr *card; + struct capi_driver *driver = 0; capiloaddata ldata; + struct list_head *l; + unsigned long flags; int retval; switch (cmd) { + case AVMB1_ADDCARD: + case AVMB1_ADDCARD_WITH_TYPE: + if (cmd == AVMB1_ADDCARD) { + if ((retval = copy_from_user((void *) &cdef, data, + sizeof(avmb1_carddef)))) + return retval; + cdef.cardtype = AVM_CARDTYPE_B1; + } else { + if ((retval = copy_from_user((void *) &cdef, data, + sizeof(avmb1_extcarddef)))) + return retval; + } + cparams.port = cdef.port; + cparams.irq = cdef.irq; + cparams.cardnr = cdef.cardnr; + + read_lock_irqsave(&capi_drivers_list_lock, flags); + switch (cdef.cardtype) { + case AVM_CARDTYPE_B1: + list_for_each(l, &capi_drivers) { + driver = list_entry(l, struct capi_driver, list); + if (strcmp(driver->name, "b1isa") == 0) + break; + } + break; + case AVM_CARDTYPE_T1: + list_for_each(l, &capi_drivers) { + driver = list_entry(l, struct capi_driver, list); + if (strcmp(driver->name, "t1isa") == 0) + break; + } + break; + default: + driver = 0; + break; + } + if (!driver) { + read_unlock_irqrestore(&capi_drivers_list_lock, flags); + printk(KERN_ERR "kcapi: driver not loaded.\n"); + return -EIO; + } + if (!driver->add_card) { + read_unlock_irqrestore(&capi_drivers_list_lock, flags); + printk(KERN_ERR "kcapi: driver has no add card function.\n"); + return -EIO; + } + + retval = driver->add_card(driver, &cparams); + read_unlock_irqrestore(&capi_drivers_list_lock, flags); + return retval; + case AVMB1_LOAD: case AVMB1_LOAD_AND_CONFIG: @@ -831,6 +907,43 @@ printk(KERN_INFO "kcapi: contr %d set trace=%d\n", card->cnr, card->traceflag); return 0; + } + case KCAPI_CMD_ADDCARD: + { + struct list_head *l; + struct capi_driver *driver = 0; + capicardparams cparams; + kcapi_carddef cdef; + int retval; + + if ((retval = copy_from_user((void *) &cdef, data, + sizeof(cdef)))) + return retval; + + cparams.port = cdef.port; + cparams.irq = cdef.irq; + cparams.membase = cdef.membase; + cparams.cardnr = cdef.cardnr; + cparams.cardtype = 0; + cdef.driver[sizeof(cdef.driver)-1] = 0; + + list_for_each(l, &capi_drivers) { + driver = list_entry(l, struct capi_driver, list); + if (strcmp(driver->name, cdef.driver) == 0) + break; + } + if (driver == 0) { + printk(KERN_ERR "kcapi: driver \"%s\" not loaded.\n", + cdef.driver); + return -ESRCH; + } + + if (!driver->add_card) { + printk(KERN_ERR "kcapi: driver \"%s\" has no add card function.\n", cdef.driver); + return -EIO; + } + + return driver->add_card(driver, &cparams); } default: diff -Nru a/drivers/isdn/capi/kcapi.h b/drivers/isdn/capi/kcapi.h --- a/drivers/isdn/capi/kcapi.h Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/capi/kcapi.h Thu Feb 19 23:44:27 2004 @@ -15,10 +15,13 @@ #include #include +#ifdef KCAPI_DEBUG #define DBG(format, arg...) do { \ printk(KERN_DEBUG "%s: " format "\n" , __FUNCTION__ , ## arg); \ } while (0) - +#else +#define DBG(format, arg...) /* */ +#endif enum { CARD_DETECTED = 1, @@ -27,7 +30,7 @@ }; extern struct list_head capi_drivers; -extern spinlock_t capi_drivers_lock; +extern rwlock_t capi_drivers_list_lock; extern struct capi20_appl *capi_applications[CAPI_MAXAPPL]; extern struct capi_ctr *capi_cards[CAPI_MAXCONTR]; diff -Nru a/drivers/isdn/capi/kcapi_proc.c b/drivers/isdn/capi/kcapi_proc.c --- a/drivers/isdn/capi/kcapi_proc.c Thu Feb 19 23:44:25 2004 +++ b/drivers/isdn/capi/kcapi_proc.c Thu Feb 19 23:44:25 2004 @@ -243,16 +243,84 @@ // --------------------------------------------------------------------------- + +static __inline__ struct capi_driver *capi_driver_get_idx(loff_t pos) +{ + struct capi_driver *drv = 0; + struct list_head *l; + loff_t i; + + i = 0; + list_for_each(l, &capi_drivers) { + drv = list_entry(l, struct capi_driver, list); + if (i++ == pos) + return drv; + } + return 0; +} + +static void *capi_driver_start(struct seq_file *seq, loff_t *pos) +{ + struct capi_driver *drv; + read_lock(&capi_drivers_list_lock); + drv = capi_driver_get_idx(*pos); + return drv; +} + +static void *capi_driver_next(struct seq_file *seq, void *v, loff_t *pos) +{ + struct capi_driver *drv = (struct capi_driver *)v; + ++*pos; + if (drv->list.next == &capi_drivers) return 0; + return list_entry(drv->list.next, struct capi_driver, list); +} + +static void capi_driver_stop(struct seq_file *seq, void *v) +{ + read_unlock(&capi_drivers_list_lock); +} + +static int capi_driver_show(struct seq_file *seq, void *v) +{ + struct capi_driver *drv = (struct capi_driver *)v; + seq_printf(seq, "%-32s %s\n", drv->name, drv->revision); + return 0; +} + +struct seq_operations seq_capi_driver_ops = { + .start = capi_driver_start, + .next = capi_driver_next, + .stop = capi_driver_stop, + .show = capi_driver_show, +}; + +static int +seq_capi_driver_open(struct inode *inode, struct file *file) +{ + int err; + err = seq_open(file, &seq_capi_driver_ops); + return err; +} + +static struct file_operations proc_driver_ops = { + .open = seq_capi_driver_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +// --------------------------------------------------------------------------- + void __init kcapi_proc_init(void) { proc_mkdir("capi", NULL); proc_mkdir("capi/controllers", NULL); - proc_mkdir("capi/drivers", NULL); create_seq_entry("capi/controller", 0, &proc_controller_ops); create_seq_entry("capi/contrstats", 0, &proc_contrstats_ops); create_seq_entry("capi/applications", 0, &proc_applications_ops); create_seq_entry("capi/applstats", 0, &proc_applstats_ops); + create_seq_entry("capi/driver", 0, &proc_driver_ops); } void __exit @@ -263,7 +331,6 @@ remove_proc_entry("capi/contrstats", NULL); remove_proc_entry("capi/applications", NULL); remove_proc_entry("capi/applstats", NULL); - remove_proc_entry("capi/drivers", NULL); remove_proc_entry("capi/controllers", NULL); remove_proc_entry("capi", NULL); } diff -Nru a/drivers/isdn/hardware/Kconfig b/drivers/isdn/hardware/Kconfig --- a/drivers/isdn/hardware/Kconfig Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/hardware/Kconfig Thu Feb 19 23:44:28 2004 @@ -2,32 +2,9 @@ # ISDN hardware drivers # comment "CAPI hardware drivers" - depends on NET && ISDN_BOOL && ISDN_CAPI + depends on NET && ISDN && ISDN_CAPI source "drivers/isdn/hardware/avm/Kconfig" source "drivers/isdn/hardware/eicon/Kconfig" - -comment "ISDN4Linux hardware drivers" - depends on NET && ISDN_BOOL && ISDN - -source "drivers/isdn/hisax/Kconfig" - - -menu "Active cards" - depends on NET && ISDN_BOOL && ISDN!=n - -source "drivers/isdn/icn/Kconfig" - -source "drivers/isdn/pcbit/Kconfig" - -source "drivers/isdn/sc/Kconfig" - -source "drivers/isdn/act2000/Kconfig" - -source "drivers/isdn/tpam/Kconfig" - -source "drivers/isdn/hysdn/Kconfig" - -endmenu diff -Nru a/drivers/isdn/hardware/avm/Kconfig b/drivers/isdn/hardware/avm/Kconfig --- a/drivers/isdn/hardware/avm/Kconfig Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hardware/avm/Kconfig Thu Feb 19 23:44:24 2004 @@ -3,7 +3,7 @@ # menu "Active AVM cards" - depends on NET && ISDN_BOOL && ISDN_CAPI!=n + depends on NET && ISDN && ISDN_CAPI!=n config CAPI_AVM bool "Support AVM cards" diff -Nru a/drivers/isdn/hardware/avm/b1.c b/drivers/isdn/hardware/avm/b1.c --- a/drivers/isdn/hardware/avm/b1.c Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/hardware/avm/b1.c Thu Feb 19 23:44:27 2004 @@ -1,4 +1,4 @@ -/* $Id: b1.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $ +/* $Id: b1.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ * * Common module for AVM B1 cards. * @@ -28,7 +28,7 @@ #include #include -static char *revision = "$Revision: 1.1.4.1.2.1 $"; +static char *revision = "$Revision: 1.1.2.2 $"; /* ------------------------------------------------------------- */ @@ -76,7 +76,7 @@ kfree(card); return 0; } - memset(cinfo, 0, sizeof(*cinfo)); + memset(cinfo, 0, sizeof(*cinfo) * nr_controllers); card->ctrlinfo = cinfo; for (i = 0; i < nr_controllers; i++) { @@ -308,14 +308,13 @@ return -EIO; } - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); b1_setinterrupt(port, card->irq, card->cardtype); b1_put_byte(port, SEND_INIT); b1_put_word(port, CAPI_MAXAPPL); b1_put_word(port, AVM_NCCI_PER_CHANNEL*2); b1_put_word(port, ctrl->cnr - 1); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); return 0; } @@ -348,15 +347,14 @@ else nconn = ctrl->profile.nbchannel * -want; if (nconn == 0) nconn = ctrl->profile.nbchannel; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); b1_put_byte(port, SEND_REGISTER); b1_put_word(port, appl); b1_put_word(port, 1024 * (nconn+1)); b1_put_word(port, nconn); b1_put_word(port, rp->datablkcnt); b1_put_word(port, rp->datablklen); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); } void b1_release_appl(struct capi_ctr *ctrl, u16 appl) @@ -368,11 +366,10 @@ capilib_release_appl(&cinfo->ncci_head, appl); - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); b1_put_byte(port, SEND_RELEASE); b1_put_word(port, appl); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); } u16 b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) @@ -396,20 +393,18 @@ dlen = CAPIMSG_DATALEN(skb->data); - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); b1_put_byte(port, SEND_DATA_B3_REQ); b1_put_slice(port, skb->data, len); b1_put_slice(port, skb->data + len, dlen); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); } else { retval = CAPI_NOERROR; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); b1_put_byte(port, SEND_MESSAGE); b1_put_slice(port, skb->data, len); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); } out: dev_kfree_skb_any(skb); @@ -505,9 +500,14 @@ unsigned DataB3Len; unsigned NCCI; unsigned WindowSize; + unsigned long flags; + + spin_lock_irqsave(&card->lock, flags); - if (!b1_rx_full(card->port)) - return IRQ_NONE; + if (!b1_rx_full(card->port)) { + spin_unlock_irqrestore(&card->lock, flags); + return IRQ_NONE; + } b1cmd = b1_get_byte(card->port); @@ -518,6 +518,7 @@ ApplId = (unsigned) b1_get_word(card->port); MsgLen = b1_get_slice(card->port, card->msgbuf); DataB3Len = b1_get_slice(card->port, card->databuf); + spin_unlock_irqrestore(&card->lock, flags); if (MsgLen < 30) { /* not CAPI 64Bit */ memset(card->msgbuf+MsgLen, 0, 30-MsgLen); @@ -538,6 +539,7 @@ ApplId = (unsigned) b1_get_word(card->port); MsgLen = b1_get_slice(card->port, card->msgbuf); + spin_unlock_irqrestore(&card->lock, flags); if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { printk(KERN_ERR "%s: incoming packet dropped\n", card->name); @@ -557,6 +559,7 @@ ApplId = b1_get_word(card->port); NCCI = b1_get_word(card->port); WindowSize = b1_get_word(card->port); + spin_unlock_irqrestore(&card->lock, flags); capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize); @@ -566,6 +569,7 @@ ApplId = b1_get_word(card->port); NCCI = b1_get_word(card->port); + spin_unlock_irqrestore(&card->lock, flags); if (NCCI != 0xffffffff) capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI); @@ -574,16 +578,19 @@ case RECEIVE_START: /* b1_put_byte(card->port, SEND_POLLACK); */ + spin_unlock_irqrestore(&card->lock, flags); capi_ctr_resume_output(ctrl); break; case RECEIVE_STOP: + spin_unlock_irqrestore(&card->lock, flags); capi_ctr_suspend_output(ctrl); break; case RECEIVE_INIT: cinfo->versionlen = b1_get_slice(card->port, cinfo->versionbuf); + spin_unlock_irqrestore(&card->lock, flags); b1_parse_version(cinfo); printk(KERN_INFO "%s: %s-card (%s) now active\n", card->name, @@ -595,6 +602,7 @@ case RECEIVE_TASK_READY: ApplId = (unsigned) b1_get_word(card->port); MsgLen = b1_get_slice(card->port, card->msgbuf); + spin_unlock_irqrestore(&card->lock, flags); card->msgbuf[MsgLen] = 0; while ( MsgLen > 0 && ( card->msgbuf[MsgLen-1] == '\n' @@ -608,6 +616,7 @@ case RECEIVE_DEBUGMSG: MsgLen = b1_get_slice(card->port, card->msgbuf); + spin_unlock_irqrestore(&card->lock, flags); card->msgbuf[MsgLen] = 0; while ( MsgLen > 0 && ( card->msgbuf[MsgLen-1] == '\n' @@ -619,9 +628,11 @@ break; case 0xff: + spin_unlock_irqrestore(&card->lock, flags); printk(KERN_ERR "%s: card removed ?\n", card->name); return IRQ_NONE; default: + spin_unlock_irqrestore(&card->lock, flags); printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n", card->name, b1cmd); return IRQ_HANDLED; diff -Nru a/drivers/isdn/hardware/avm/b1dma.c b/drivers/isdn/hardware/avm/b1dma.c --- a/drivers/isdn/hardware/avm/b1dma.c Thu Feb 19 23:44:26 2004 +++ b/drivers/isdn/hardware/avm/b1dma.c Thu Feb 19 23:44:26 2004 @@ -1,4 +1,4 @@ -/* $Id: b1dma.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $ +/* $Id: b1dma.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $ * * Common module for AVM B1 cards that support dma with AMCC * @@ -28,11 +28,9 @@ #include #include -#if BITS_PER_LONG != 32 -#error FIXME: driver requires 32-bit platform -#endif +static char *revision = "$Revision: 1.1.2.3 $"; -static char *revision = "$Revision: 1.1.4.1.2.1 $"; +#undef CONFIG_B1DMA_DEBUG /* ------------------------------------------------------------- */ @@ -239,7 +237,7 @@ /* ------------------------------------------------------------- */ -int b1dma_detect(avmcard *card) +static int b1dma_detect(avmcard *card) { b1dma_writel(card, 0, AMCC_MCSR); mdelay(10); @@ -578,11 +576,16 @@ static void b1dma_handle_interrupt(avmcard *card) { - u32 status = b1dma_readl(card, AMCC_INTCSR); + u32 status; u32 newcsr; - if ((status & ANY_S5933_INT) == 0) + spin_lock(&card->lock); + + status = b1dma_readl(card, AMCC_INTCSR); + if ((status & ANY_S5933_INT) == 0) { + spin_unlock(&card->lock); return; + } newcsr = card->csr | (status & ALL_INT); if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT; @@ -593,20 +596,28 @@ struct avmcard_dmainfo *dma = card->dma; u32 rxlen; if (card->dma->recvlen == 0) { - dma->recvlen = *((u32 *)dma->recvbuf.dmabuf); - rxlen = (dma->recvlen + 3) & ~3; - b1dma_writel(card, dma->recvbuf.dmaaddr+4, AMCC_RXPTR); - b1dma_writel(card, rxlen, AMCC_RXLEN); + rxlen = b1dma_readl(card, AMCC_RXLEN); + if (rxlen == 0) { + dma->recvlen = *((u32 *)dma->recvbuf.dmabuf); + rxlen = (dma->recvlen + 3) & ~3; + b1dma_writel(card, dma->recvbuf.dmaaddr+4, AMCC_RXPTR); + b1dma_writel(card, rxlen, AMCC_RXLEN); +#ifdef CONFIG_B1DMA_DEBUG + } else { + printk(KERN_ERR "%s: rx not complete (%d).\n", + card->name, rxlen); +#endif + } } else { + spin_unlock(&card->lock); b1dma_handle_rx(card); dma->recvlen = 0; + spin_lock(&card->lock); b1dma_writel(card, dma->recvbuf.dmaaddr, AMCC_RXPTR); b1dma_writel(card, 4, AMCC_RXLEN); } } - spin_lock(&card->lock); - if ((status & TX_TC_INT) != 0) { if (skb_queue_empty(&card->dma->send_queue)) card->csr &= ~EN_TX_TC_INT; @@ -736,18 +747,19 @@ { avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = cinfo->card; + unsigned long flags; + spin_lock_irqsave(&card->lock, flags); b1dma_reset(card); + spin_unlock_irqrestore(&card->lock, flags); memset(cinfo->version, 0, sizeof(cinfo->version)); capilib_release(&cinfo->ncci_head); capi_ctr_reseted(ctrl); } - /* ------------------------------------------------------------- */ - void b1dma_register_appl(struct capi_ctr *ctrl, u16 appl, capi_register_params *rp) @@ -844,6 +856,7 @@ int len = 0; char *s; u32 txoff, txlen, rxoff, rxlen, csr; + unsigned long flags; len += sprintf(page+len, "%-16s %s\n", "name", card->name); len += sprintf(page+len, "%-16s 0x%x\n", "io", card->port); @@ -896,6 +909,9 @@ } len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); + + spin_lock_irqsave(&card->lock, flags); + txoff = (dma_addr_t)b1dma_readl(card, AMCC_TXPTR)-card->dma->sendbuf.dmaaddr; txlen = b1dma_readl(card, AMCC_TXLEN); @@ -903,6 +919,8 @@ rxlen = b1dma_readl(card, AMCC_RXLEN); csr = b1dma_readl(card, AMCC_INTCSR); + + spin_unlock_irqrestore(&card->lock, flags); len += sprintf(page+len, "%-16s 0x%lx\n", "csr (cached)", (unsigned long)card->csr); diff -Nru a/drivers/isdn/hardware/avm/b1isa.c b/drivers/isdn/hardware/avm/b1isa.c --- a/drivers/isdn/hardware/avm/b1isa.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hardware/avm/b1isa.c Thu Feb 19 23:44:24 2004 @@ -1,4 +1,4 @@ -/* $Id: b1isa.c,v 1.10.6.6 2001/09/23 22:24:33 kai Exp $ +/* $Id: b1isa.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $ * * Module for AVM B1 ISA-card. * @@ -27,6 +27,10 @@ /* ------------------------------------------------------------- */ +static char *revision = "$Revision: 1.1.2.3 $"; + +/* ------------------------------------------------------------- */ + MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM B1 ISA card"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); @@ -56,7 +60,7 @@ static char *b1isa_procinfo(struct capi_ctr *ctrl); -static int __init b1isa_probe(struct pci_dev *pdev) +static int b1isa_probe(struct pci_dev *pdev) { avmctrl_info *cinfo; avmcard *card; @@ -108,6 +112,7 @@ b1_reset(card->port); b1_getrevision(card); + cinfo->capi_ctrl.owner = THIS_MODULE; cinfo->capi_ctrl.driver_name = "b1isa"; cinfo->capi_ctrl.driverdata = cinfo; cinfo->capi_ctrl.register_appl = b1_register_appl; @@ -118,7 +123,6 @@ cinfo->capi_ctrl.procinfo = b1isa_procinfo; cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; strcpy(cinfo->capi_ctrl.name, card->name); - cinfo->capi_ctrl.owner = THIS_MODULE; retval = attach_capi_ctr(&cinfo->capi_ctrl); if (retval) { @@ -170,23 +174,56 @@ MODULE_PARM_DESC(io, "I/O base address(es)"); MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); +static int b1isa_add_card(struct capi_driver *driver, capicardparams *data) +{ + int i; + + for (i = 0; i < MAX_CARDS; i++) { + if (isa_dev[i].resource[0].start) + continue; + + isa_dev[i].resource[0].start = data->port; + isa_dev[i].irq = data->irq; + + if (b1isa_probe(&isa_dev[i]) == 0) + return 0; + } + return -ENODEV; +} + +static struct capi_driver capi_driver_b1isa = { + .name = "b1isa", + .revision = "1.0", + .add_card = b1isa_add_card, +}; + static int __init b1isa_init(void) { + char *p; + char rev[32]; int i; - int found = 0; + + if ((p = strchr(revision, ':')) != 0 && p[1]) { + strlcpy(rev, p + 2, 32); + if ((p = strchr(rev, '$')) != 0 && p > rev) + *(p-1) = 0; + } else + strcpy(rev, "1.0"); for (i = 0; i < MAX_CARDS; i++) { if (!io[i]) break; isa_dev[i].resource[0].start = io[i]; - isa_dev[i].irq_resource[0].start = irq[i]; + isa_dev[i].irq = irq[i]; - if (b1isa_probe(&isa_dev[i]) == 0) - found++; + if (b1isa_probe(&isa_dev[i]) != 0) + return -ENODEV; } - if (found == 0) - return -ENODEV; + + strlcpy(capi_driver_b1isa.revision, rev, 32); + register_capi_driver(&capi_driver_b1isa); + printk(KERN_INFO "b1isa: revision %s\n", rev); return 0; } @@ -201,6 +238,7 @@ b1isa_remove(&isa_dev[i]); } + unregister_capi_driver(&capi_driver_b1isa); } module_init(b1isa_init); diff -Nru a/drivers/isdn/hardware/avm/b1pci.c b/drivers/isdn/hardware/avm/b1pci.c --- a/drivers/isdn/hardware/avm/b1pci.c Thu Feb 19 23:44:22 2004 +++ b/drivers/isdn/hardware/avm/b1pci.c Thu Feb 19 23:44:22 2004 @@ -1,4 +1,4 @@ -/* $Id: b1pci.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $ +/* $Id: b1pci.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ * * Module for AVM B1 PCI-card. * @@ -28,6 +28,10 @@ /* ------------------------------------------------------------- */ +static char *revision = "$Revision: 1.1.2.2 $"; + +/* ------------------------------------------------------------- */ + static struct pci_device_id b1pci_pci_tbl[] = { { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_B1, PCI_ANY_ID, PCI_ANY_ID }, { } /* Terminating entry */ @@ -362,13 +366,50 @@ .remove = __devexit_p(b1pci_pci_remove), }; +static struct capi_driver capi_driver_b1pci = { + .name = "b1pci", + .revision = "1.0", +}; +#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 +static struct capi_driver capi_driver_b1pciv4 = { + .name = "b1pciv4", + .revision = "1.0", +}; +#endif + static int __init b1pci_init(void) { - return pci_module_init(&b1pci_pci_driver); + char *p; + char rev[32]; + int err; + + if ((p = strchr(revision, ':')) != 0 && p[1]) { + strlcpy(rev, p + 2, 32); + if ((p = strchr(rev, '$')) != 0 && p > rev) + *(p-1) = 0; + } else + strcpy(rev, "1.0"); + + + err = pci_module_init(&b1pci_pci_driver); + if (!err) { + strlcpy(capi_driver_b1pci.revision, rev, 32); + register_capi_driver(&capi_driver_b1pci); +#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 + strlcpy(capi_driver_b1pciv4.revision, rev, 32); + register_capi_driver(&capi_driver_b1pciv4); +#endif + printk(KERN_INFO "b1pci: revision %s\n", rev); + } + return err; } static void __exit b1pci_exit(void) { + unregister_capi_driver(&capi_driver_b1pci); +#ifdef CONFIG_ISDN_DRV_AVMB1_B1PCIV4 + unregister_capi_driver(&capi_driver_b1pciv4); +#endif pci_unregister_driver(&b1pci_pci_driver); } diff -Nru a/drivers/isdn/hardware/avm/b1pcmcia.c b/drivers/isdn/hardware/avm/b1pcmcia.c --- a/drivers/isdn/hardware/avm/b1pcmcia.c Thu Feb 19 23:44:22 2004 +++ b/drivers/isdn/hardware/avm/b1pcmcia.c Thu Feb 19 23:44:22 2004 @@ -1,4 +1,4 @@ -/* $Id: b1pcmcia.c,v 1.12.6.5 2001/09/23 22:24:33 kai Exp $ +/* $Id: b1pcmcia.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ * * Module for AVM B1/M1/M2 PCMCIA-card. * @@ -27,6 +27,10 @@ /* ------------------------------------------------------------- */ +static char *revision = "$Revision: 1.1.2.2 $"; + +/* ------------------------------------------------------------- */ + MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM PCMCIA cards"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); @@ -186,3 +190,36 @@ EXPORT_SYMBOL(b1pcmcia_addcard_m1); EXPORT_SYMBOL(b1pcmcia_addcard_m2); EXPORT_SYMBOL(b1pcmcia_delcard); + +static struct capi_driver capi_driver_b1pcmcia = { + .name = "b1pcmcia", + .revision = "1.0", +}; + +static int __init b1pcmcia_init(void) +{ + char *p; + char rev[32]; + int err; + + if ((p = strchr(revision, ':')) != 0 && p[1]) { + strlcpy(rev, p + 2, 32); + if ((p = strchr(rev, '$')) != 0 && p > rev) + *(p-1) = 0; + } else + strcpy(rev, "1.0"); + + strlcpy(capi_driver_b1pcmcia.revision, rev, 32); + register_capi_driver(&capi_driver_b1pcmcia); + printk(KERN_INFO "b1pci: revision %s\n", rev); + + return 0; +} + +static void __exit b1pcmcia_exit(void) +{ + unregister_capi_driver(&capi_driver_b1pcmcia); +} + +module_init(b1pcmcia_init); +module_exit(b1pcmcia_exit); diff -Nru a/drivers/isdn/hardware/avm/c4.c b/drivers/isdn/hardware/avm/c4.c --- a/drivers/isdn/hardware/avm/c4.c Thu Feb 19 23:44:25 2004 +++ b/drivers/isdn/hardware/avm/c4.c Thu Feb 19 23:44:25 2004 @@ -1,4 +1,4 @@ -/* $Id: c4.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $ +/* $Id: c4.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ * * Module for AVM C4 & C2 card. * @@ -34,6 +34,10 @@ /* ------------------------------------------------------------- */ +static char *revision = "$Revision: 1.1.2.2 $"; + +/* ------------------------------------------------------------- */ + static int suppress_pollack; static struct pci_device_id c4_pci_tbl[] = { @@ -404,18 +408,14 @@ static void c4_dispatch_tx(avmcard *card) { avmcard_dmainfo *dma = card->dma; - unsigned long flags; struct sk_buff *skb; u8 cmd, subcmd; u16 len; u32 txlen; void *p; - - save_flags(flags); - cli(); + if (card->csr & DBELL_DOWN_ARM) { /* tx busy */ - restore_flags(flags); return; } @@ -424,7 +424,6 @@ #ifdef CONFIG_C4_DEBUG printk(KERN_DEBUG "%s: tx underrun\n", card->name); #endif - restore_flags(flags); return; } @@ -470,7 +469,6 @@ c4outmeml(card->mbase+DOORBELL, DBELL_DOWN_ARM); - restore_flags(flags); dev_kfree_skb_any(skb); } @@ -664,11 +662,15 @@ static irqreturn_t c4_handle_interrupt(avmcard *card) { - u32 status = c4inmeml(card->mbase+DOORBELL); + u32 status; + + spin_lock(&card->lock); + status = c4inmeml(card->mbase+DOORBELL); if (status & DBELL_RESET_HOST) { u_int i; c4outmeml(card->mbase+PCI_OUT_INT_MASK, 0x0c); + spin_unlock(&card->lock); if (card->nlogcontr == 0) return IRQ_HANDLED; printk(KERN_ERR "%s: unexpected reset\n", card->name); @@ -683,8 +685,10 @@ } status &= (DBELL_UP_HOST | DBELL_DOWN_HOST); - if (!status) + if (!status) { + spin_unlock(&card->lock); return IRQ_HANDLED; + } c4outmeml(card->mbase+DOORBELL, status); if ((status & DBELL_UP_HOST) != 0) { @@ -705,6 +709,7 @@ c4_dispatch_tx(card); } } + spin_unlock(&card->lock); return IRQ_HANDLED; } @@ -767,6 +772,7 @@ static int queue_sendconfig(avmcard *card, char cval[4]) { struct sk_buff *skb; + unsigned long flags; void *p; skb = alloc_skb(3+4, GFP_ATOMIC); @@ -786,7 +792,10 @@ skb_put(skb, (u8 *)p - (u8 *)skb->data); skb_queue_tail(&card->dma->send_queue, skb); + + spin_lock_irqsave(&card->lock, flags); c4_dispatch_tx(card); + spin_unlock_irqrestore(&card->lock, flags); return 0; } @@ -835,7 +844,6 @@ { avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = cinfo->card; - unsigned long flags; int retval; if ((retval = c4_load_t4file(card, &data->firmware))) { @@ -845,9 +853,6 @@ return retval; } - save_flags(flags); - cli(); - card->csr = 0; c4outmeml(card->mbase+MBOX_UP_LEN, 0); c4outmeml(card->mbase+MBOX_DOWN_LEN, 0); @@ -862,7 +867,6 @@ c4outmeml(card->mbase+MBOX_UP_ADDR, card->dma->recvbuf.dmaaddr); c4outmeml(card->mbase+MBOX_UP_LEN, card->dma->recvbuf.size); c4outmeml(card->mbase+DOORBELL, DBELL_UP_ARM); - restore_flags(flags); if (data->configuration.len > 0 && data->configuration.data) { retval = c4_send_config(card, &data->configuration); @@ -885,9 +889,14 @@ avmcard *card = ((avmctrl_info *)(ctrl->driverdata))->card; avmctrl_info *cinfo; u_int i; + unsigned long flags; + + spin_lock_irqsave(&card->lock, flags); c4_reset(card); + spin_unlock_irqrestore(&card->lock, flags); + for (i=0; i < card->nr_controllers; i++) { cinfo = &card->ctrlinfo[i]; memset(cinfo->version, 0, sizeof(cinfo->version)); @@ -931,6 +940,7 @@ avmcard *card = cinfo->card; struct sk_buff *skb; int want = rp->level3cnt; + unsigned long flags; int nconn; void *p; @@ -958,7 +968,10 @@ skb_put(skb, (u8 *)p - (u8 *)skb->data); skb_queue_tail(&card->dma->send_queue, skb); + + spin_lock_irqsave(&card->lock, flags); c4_dispatch_tx(card); + spin_unlock_irqrestore(&card->lock, flags); } } @@ -968,6 +981,7 @@ { avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = cinfo->card; + unsigned long flags; struct sk_buff *skb; void *p; @@ -988,7 +1002,9 @@ skb_put(skb, (u8 *)p - (u8 *)skb->data); skb_queue_tail(&card->dma->send_queue, skb); + spin_lock_irqsave(&card->lock, flags); c4_dispatch_tx(card); + spin_unlock_irqrestore(&card->lock, flags); } } @@ -1000,6 +1016,7 @@ avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = cinfo->card; u16 retval = CAPI_NOERROR; + unsigned long flags; if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) { retval = capilib_data_b3_req(&cinfo->ncci_head, @@ -1009,7 +1026,9 @@ } if (retval == CAPI_NOERROR) { skb_queue_tail(&card->dma->send_queue, skb); + spin_lock_irqsave(&card->lock, flags); c4_dispatch_tx(card); + spin_unlock_irqrestore(&card->lock, flags); } else { dev_kfree_skb_any(skb); } @@ -1164,6 +1183,7 @@ for (i=0; i < nr_controllers ; i++) { cinfo = &card->ctrlinfo[i]; + cinfo->capi_ctrl.owner = THIS_MODULE; cinfo->capi_ctrl.driver_name = "c4"; cinfo->capi_ctrl.driverdata = cinfo; cinfo->capi_ctrl.register_appl = c4_register_appl; @@ -1174,7 +1194,6 @@ cinfo->capi_ctrl.procinfo = c4_procinfo; cinfo->capi_ctrl.ctr_read_proc = c4_read_proc; strcpy(cinfo->capi_ctrl.name, card->name); - cinfo->capi_ctrl.owner = THIS_MODULE; retval = attach_capi_ctr(&cinfo->capi_ctrl); if (retval) { @@ -1247,13 +1266,44 @@ .remove = c4_remove, }; +static struct capi_driver capi_driver_c2 = { + .name = "c2", + .revision = "1.0", +}; + +static struct capi_driver capi_driver_c4 = { + .name = "c4", + .revision = "1.0", +}; + static int __init c4_init(void) { - return pci_module_init(&c4_pci_driver); + char *p; + char rev[32]; + int err; + + if ((p = strchr(revision, ':')) != 0 && p[1]) { + strlcpy(rev, p + 2, 32); + if ((p = strchr(rev, '$')) != 0 && p > rev) + *(p-1) = 0; + } else + strcpy(rev, "1.0"); + + err = pci_module_init(&c4_pci_driver); + if (!err) { + strlcpy(capi_driver_c2.revision, rev, 32); + register_capi_driver(&capi_driver_c2); + strlcpy(capi_driver_c4.revision, rev, 32); + register_capi_driver(&capi_driver_c4); + printk(KERN_INFO "c4: revision %s\n", rev); + } + return err; } static void __exit c4_exit(void) { + unregister_capi_driver(&capi_driver_c2); + unregister_capi_driver(&capi_driver_c4); pci_unregister_driver(&c4_pci_driver); } diff -Nru a/drivers/isdn/hardware/avm/t1isa.c b/drivers/isdn/hardware/avm/t1isa.c --- a/drivers/isdn/hardware/avm/t1isa.c Thu Feb 19 23:44:26 2004 +++ b/drivers/isdn/hardware/avm/t1isa.c Thu Feb 19 23:44:26 2004 @@ -1,4 +1,4 @@ -/* $Id: t1isa.c,v 1.16.6.7 2001/09/23 22:24:34 kai Exp $ +/* $Id: t1isa.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $ * * Module for AVM T1 HEMA-card. * @@ -29,6 +29,10 @@ /* ------------------------------------------------------------- */ +static char *revision = "$Revision: 1.1.2.3 $"; + +/* ------------------------------------------------------------- */ + MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 HEMA ISA card"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); @@ -58,7 +62,6 @@ { unsigned char cregs[8]; unsigned char reverse_cardnr; - unsigned long flags; unsigned char dummy; int i; @@ -73,8 +76,12 @@ cregs[6] = 0; cregs[7] = 0; - save_flags(flags); - cli(); + /* + * no one else should use the ISA bus in this moment, + * but no function there to prevent this :-( + * save_flags(flags); cli(); + */ + /* board reset */ t1outp(base, T1_RESETBOARD, 0xf); mdelay(100); @@ -87,7 +94,7 @@ t1outp(base, HEMA_PAL_ID >> 4, cregs[0]); for(i=1;i<7;i++) t1outp(base, 0, cregs[i]); t1outp(base, ((base >> 4)) & 0x3, cregs[7]); - restore_flags(flags); + /* restore_flags(flags); */ mdelay(100); t1outp(base, T1_FASTLINK+T1_RESETLINK, 0); @@ -137,6 +144,9 @@ unsigned DataB3Len; unsigned NCCI; unsigned WindowSize; + unsigned long flags; + + spin_lock_irqsave(&card->lock, flags); while (b1_rx_full(card->port)) { @@ -149,6 +159,7 @@ ApplId = (unsigned) b1_get_word(card->port); MsgLen = t1_get_slice(card->port, card->msgbuf); DataB3Len = t1_get_slice(card->port, card->databuf); + spin_unlock_irqrestore(&card->lock, flags); if (MsgLen < 30) { /* not CAPI 64Bit */ memset(card->msgbuf+MsgLen, 0, 30-MsgLen); @@ -169,6 +180,7 @@ ApplId = (unsigned) b1_get_word(card->port); MsgLen = t1_get_slice(card->port, card->msgbuf); + spin_unlock_irqrestore(&card->lock, flags); if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { printk(KERN_ERR "%s: incoming packet dropped\n", card->name); @@ -188,6 +200,7 @@ ApplId = b1_get_word(card->port); NCCI = b1_get_word(card->port); WindowSize = b1_get_word(card->port); + spin_unlock_irqrestore(&card->lock, flags); capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize); @@ -197,6 +210,7 @@ ApplId = b1_get_word(card->port); NCCI = b1_get_word(card->port); + spin_unlock_irqrestore(&card->lock, flags); if (NCCI != 0xffffffff) capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI); @@ -205,16 +219,19 @@ case RECEIVE_START: b1_put_byte(card->port, SEND_POLLACK); + spin_unlock_irqrestore(&card->lock, flags); capi_ctr_resume_output(ctrl); break; case RECEIVE_STOP: + spin_unlock_irqrestore(&card->lock, flags); capi_ctr_suspend_output(ctrl); break; case RECEIVE_INIT: cinfo->versionlen = t1_get_slice(card->port, cinfo->versionbuf); + spin_unlock_irqrestore(&card->lock, flags); b1_parse_version(cinfo); printk(KERN_INFO "%s: %s-card (%s) now active\n", card->name, @@ -226,6 +243,7 @@ case RECEIVE_TASK_READY: ApplId = (unsigned) b1_get_word(card->port); MsgLen = t1_get_slice(card->port, card->msgbuf); + spin_unlock_irqrestore(&card->lock, flags); card->msgbuf[MsgLen] = 0; while ( MsgLen > 0 && ( card->msgbuf[MsgLen-1] == '\n' @@ -239,6 +257,7 @@ case RECEIVE_DEBUGMSG: MsgLen = t1_get_slice(card->port, card->msgbuf); + spin_unlock_irqrestore(&card->lock, flags); card->msgbuf[MsgLen] = 0; while ( MsgLen > 0 && ( card->msgbuf[MsgLen-1] == '\n' @@ -251,9 +270,11 @@ case 0xff: + spin_unlock_irqrestore(&card->lock, flags); printk(KERN_ERR "%s: card reseted ?\n", card->name); return IRQ_HANDLED; default: + spin_unlock_irqrestore(&card->lock, flags); printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n", card->name, b1cmd); return IRQ_NONE; @@ -296,14 +317,13 @@ return -EIO; } - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); b1_setinterrupt(port, card->irq, card->cardtype); b1_put_byte(port, SEND_INIT); b1_put_word(port, CAPI_MAXAPPL); b1_put_word(port, AVM_NCCI_PER_CHANNEL*30); b1_put_word(port, ctrl->cnr - 1); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); return 0; } @@ -349,7 +369,7 @@ static u16 t1isa_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); static char *t1isa_procinfo(struct capi_ctr *ctrl); -static int __init t1isa_probe(struct pci_dev *pdev, int cardnr) +static int t1isa_probe(struct pci_dev *pdev, int cardnr) { avmctrl_info *cinfo; avmcard *card; @@ -401,6 +421,7 @@ t1_disable_irq(card->port); b1_reset(card->port); + cinfo->capi_ctrl.owner = THIS_MODULE; cinfo->capi_ctrl.driver_name = "t1isa"; cinfo->capi_ctrl.driverdata = cinfo; cinfo->capi_ctrl.register_appl = b1_register_appl; @@ -411,7 +432,6 @@ cinfo->capi_ctrl.procinfo = t1isa_procinfo; cinfo->capi_ctrl.ctr_read_proc = b1ctl_read_proc; strcpy(cinfo->capi_ctrl.name, card->name); - cinfo->capi_ctrl.owner = THIS_MODULE; retval = attach_capi_ctr(&cinfo->capi_ctrl); if (retval) { @@ -456,20 +476,18 @@ dlen = CAPIMSG_DATALEN(skb->data); - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); b1_put_byte(port, SEND_DATA_B3_REQ); t1_put_slice(port, skb->data, len); t1_put_slice(port, skb->data + len, dlen); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); } else { retval = CAPI_NOERROR; - save_flags(flags); - cli(); + spin_lock_irqsave(&card->lock, flags); b1_put_byte(port, SEND_MESSAGE); t1_put_slice(port, skb->data, len); - restore_flags(flags); + spin_unlock_irqrestore(&card->lock, flags); } out: dev_kfree_skb_any(skb); @@ -509,23 +527,56 @@ MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)"); MODULE_PARM_DESC(cardnr, "Card number(s) (as jumpered)"); +static int t1isa_add_card(struct capi_driver *driver, capicardparams *data) +{ + int i; + + for (i = 0; i < MAX_CARDS; i++) { + if (isa_dev[i].resource[0].start) + continue; + + isa_dev[i].resource[0].start = data->port; + isa_dev[i].irq = data->irq; + + if (t1isa_probe(&isa_dev[i], data->cardnr) == 0) + return 0; + } + return -ENODEV; +} + +static struct capi_driver capi_driver_t1isa = { + .name = "t1isa", + .revision = "1.0", + .add_card = t1isa_add_card, +}; + static int __init t1isa_init(void) { + char rev[32]; + char *p; int i; - int found = 0; + + if ((p = strchr(revision, ':')) != 0 && p[1]) { + strlcpy(rev, p + 2, 32); + if ((p = strchr(rev, '$')) != 0 && p > rev) + *(p-1) = 0; + } else + strcpy(rev, "1.0"); for (i = 0; i < MAX_CARDS; i++) { if (!io[i]) break; isa_dev[i].resource[0].start = io[i]; - isa_dev[i].irq_resource[0].start = irq[i]; + isa_dev[i].irq = irq[i]; - if (t1isa_probe(&isa_dev[i], cardnr[i]) == 0) - found++; + if (t1isa_probe(&isa_dev[i], cardnr[i]) != 0) + return -ENODEV; } - if (found == 0) - return -ENODEV; + + strlcpy(capi_driver_t1isa.revision, rev, 32); + register_capi_driver(&capi_driver_t1isa); + printk(KERN_INFO "t1isa: revision %s\n", rev); return 0; } diff -Nru a/drivers/isdn/hardware/avm/t1pci.c b/drivers/isdn/hardware/avm/t1pci.c --- a/drivers/isdn/hardware/avm/t1pci.c Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hardware/avm/t1pci.c Thu Feb 19 23:44:23 2004 @@ -1,4 +1,4 @@ -/* $Id: t1pci.c,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $ +/* $Id: t1pci.c,v 1.1.2.2 2004/01/16 21:09:27 keil Exp $ * * Module for AVM T1 PCI-card. * @@ -30,6 +30,8 @@ #undef CONFIG_T1PCI_POLLDEBUG /* ------------------------------------------------------------- */ +static char *revision = "$Revision: 1.1.2.2 $"; +/* ------------------------------------------------------------- */ static struct pci_device_id t1pci_pci_tbl[] = { { PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_T1, PCI_ANY_ID, PCI_ANY_ID }, @@ -221,13 +223,36 @@ .remove = t1pci_remove, }; +static struct capi_driver capi_driver_t1pci = { + .name = "t1pci", + .revision = "1.0", +}; + static int __init t1pci_init(void) { - return pci_module_init(&t1pci_pci_driver); + char *p; + char rev[32]; + int err; + + if ((p = strchr(revision, ':')) != 0 && p[1]) { + strlcpy(rev, p + 2, 32); + if ((p = strchr(rev, '$')) != 0 && p > rev) + *(p-1) = 0; + } else + strcpy(rev, "1.0"); + + err = pci_module_init(&t1pci_pci_driver); + if (!err) { + strlcpy(capi_driver_t1pci.revision, rev, 32); + register_capi_driver(&capi_driver_t1pci); + printk(KERN_INFO "t1pci: revision %s\n", rev); + } + return err; } static void __exit t1pci_exit(void) { + unregister_capi_driver(&capi_driver_t1pci); pci_unregister_driver(&t1pci_pci_driver); } diff -Nru a/drivers/isdn/hardware/eicon/Kconfig b/drivers/isdn/hardware/eicon/Kconfig --- a/drivers/isdn/hardware/eicon/Kconfig Thu Feb 19 23:44:25 2004 +++ b/drivers/isdn/hardware/eicon/Kconfig Thu Feb 19 23:44:25 2004 @@ -3,7 +3,7 @@ # menu "Active Eicon DIVA Server cards" - depends on NET && ISDN_BOOL && ISDN_CAPI!=n + depends on NET && ISDN && ISDN_CAPI!=n config CAPI_EICON bool "Support Eicon cards" diff -Nru a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig --- a/drivers/isdn/hisax/Kconfig Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/hisax/Kconfig Thu Feb 19 23:44:27 2004 @@ -1,6 +1,6 @@ menu "Passive cards" - depends on ISDN + depends on ISDN_I4L config ISDN_DRV_HISAX tristate "HiSax SiemensChipSet driver support" @@ -341,8 +341,8 @@ # bool ' TESTEMULATOR (EXPERIMENTAL)' CONFIG_HISAX_TESTEMU config HISAX_ENTERNOW_PCI - bool "Formula-n enter:now PCI card (EXPERIMENTAL)" - depends on PCI && EXPERIMENTAL + bool "Formula-n enter:now PCI card" + depends on PCI help This enables HiSax support for the Formula-n enter:now PCI ISDN card. @@ -365,6 +365,8 @@ the ST5481 USB driver currently. If in doubt, say yes. +comment "HiSax PCMCIA card service modules" + config HISAX_SEDLBAUER_CS tristate "Sedlbauer PCMCIA cards" depends on PCMCIA && HISAX_SEDLBAUER @@ -374,18 +376,26 @@ config HISAX_ELSA_CS tristate "ELSA PCMCIA MicroLink cards" - depends on PCMCIA + depends on PCMCIA && HISAX_ELSA help This enables the PCMCIA client driver for the Elsa PCMCIA MicroLink card. config HISAX_AVM_A1_CS tristate "AVM A1 PCMCIA cards" - depends on PCMCIA + depends on PCMCIA && ISDN_DRV_HISAX help This enables the PCMCIA client driver for the AVM A1 / Fritz!Card PCMCIA cards. +config HISAX_TELES_CS + tristate "TELES PCMCIA cards" + depends on PCMCIA && HISAX_16_3 + help + This enables the PCMCIA client driver for the Teles PCMCIA cards. + +comment "HiSax sub driver modules" + config HISAX_ST5481 tristate "ST5481 USB ISDN modem (EXPERIMENTAL)" depends on USB && EXPERIMENTAL @@ -393,6 +403,12 @@ This enables the driver for ST5481 based USB ISDN adapters, e.g. the BeWan Gazel 128 USB +config HISAX_HFCUSB + tristate "HFC USB based ISDN modems (EXPERIMENTAL)" + depends on USB && EXPERIMENTAL + help + This enables the driver for HFC USB based ISDN modems. + config HISAX_FRITZ_PCIPNP tristate "AVM Fritz!Card PCI/PCIv2/PnP support (EXPERIMENTAL)" depends on EXPERIMENTAL @@ -402,18 +418,15 @@ (the latter also needs you to select "ISA Plug and Play support" from the menu "Plug and Play configuration") -config HISAX_FRITZ_CLASSIC - tristate "AVM Fritz!Card classic support (EXPERIMENTAL)" - depends on ISA && EXPERIMENTAL - help - This enables the driver for the AVM Fritz!Card classic, formerly - known as AVM A1. - -config HISAX_HFCPCI - tristate "HFC PCI support (EXPERIMENTAL)" - depends on PCI && EXPERIMENTAL - help - This enables the driver for CCD HFC PCI based cards. +config HISAX_HDLC + bool + depends on HISAX_ST5481 + default y + +config HISAX_AVM_A1_PCMCIA + bool + depends on HISAX_AVM_A1_CS + default y endif diff -Nru a/drivers/isdn/hisax/Makefile b/drivers/isdn/hisax/Makefile --- a/drivers/isdn/hisax/Makefile Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hisax/Makefile Thu Feb 19 23:44:24 2004 @@ -1,19 +1,23 @@ # Makefile for the hisax ISDN device driver +# The target object and module list name. + # Define maximum number of cards EXTRA_CFLAGS += -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS) -# Each configuration option enables a list of files. - obj-$(CONFIG_ISDN_DRV_HISAX) += hisax.o obj-$(CONFIG_HISAX_SEDLBAUER_CS) += sedlbauer_cs.o obj-$(CONFIG_HISAX_ELSA_CS) += elsa_cs.o obj-$(CONFIG_HISAX_AVM_A1_CS) += avma1_cs.o +obj-$(CONFIG_HISAX_TELES_CS) += teles_cs.o obj-$(CONFIG_HISAX_ST5481) += hisax_st5481.o +obj-$(CONFIG_HISAX_HFCUSB) += hfc_usb.o obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_isac.o hisax_fcpcipnp.o -obj-$(CONFIG_HISAX_FRITZ_CLASSIC) += hisax_isac.o hisax_hscx.o hisax_fcclassic.o -obj-$(CONFIG_HISAX_FRITZ_PCIPNP) += hisax_hfcpci.o + +ifdef CONFIG_HISAX_HDLC +obj-$(CONFIG_ISDN_DRV_HISAX) += isdnhdlc.o +endif # Multipart objects. @@ -21,7 +25,7 @@ st5481_b.o st5481_hdlc.o hisax-y := config.o isdnl1.o tei.o isdnl2.o isdnl3.o \ - lmgr.o q931.o callc.o fsm.o cert.o + lmgr.o q931.o callc.o fsm.o hisax-$(CONFIG_HISAX_EURO) += l3dss1.o hisax-$(CONFIG_HISAX_NI1) += l3ni1.o hisax-$(CONFIG_HISAX_1TR6) += l3_1tr6.o @@ -33,12 +37,12 @@ hisax-$(CONFIG_HISAX_AVM_A1) += avm_a1.o isac.o arcofi.o hscx.o hisax-$(CONFIG_HISAX_AVM_A1_PCMCIA) += avm_a1p.o isac.o arcofi.o hscx.o hisax-$(CONFIG_HISAX_FRITZPCI) += avm_pci.o isac.o arcofi.o -hisax-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o ipac.o +hisax-$(CONFIG_HISAX_ELSA) += elsa.o isac.o arcofi.o hscx.o hisax-$(CONFIG_HISAX_IX1MICROR2) += ix1_micro.o isac.o arcofi.o hscx.o -hisax-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o ipac.o ipacx.o -hisax-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o ipac.o +hisax-$(CONFIG_HISAX_DIEHLDIVA) += diva.o isac.o arcofi.o hscx.o ipacx.o +hisax-$(CONFIG_HISAX_ASUSCOM) += asuscom.o isac.o arcofi.o hscx.o hisax-$(CONFIG_HISAX_TELEINT) += teleint.o isac.o arcofi.o hfc_2bs0.o -hisax-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o ipac.o \ +hisax-$(CONFIG_HISAX_SEDLBAUER) += sedlbauer.o isac.o arcofi.o hscx.o \ isar.o hisax-$(CONFIG_HISAX_SPORTSTER) += sportster.o isac.o arcofi.o hscx.o hisax-$(CONFIG_HISAX_MIC) += mic.o isac.o arcofi.o hscx.o @@ -51,11 +55,9 @@ hisax-$(CONFIG_HISAX_ISURF) += isurf.o isac.o arcofi.o isar.o hisax-$(CONFIG_HISAX_HSTSAPHIR) += saphir.o isac.o arcofi.o hscx.o hisax-$(CONFIG_HISAX_BKM_A4T) += bkm_a4t.o isac.o arcofi.o jade.o -hisax-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o ipac.o -hisax-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o ipac.o +hisax-$(CONFIG_HISAX_SCT_QUADRO) += bkm_a8.o isac.o arcofi.o hscx.o +hisax-$(CONFIG_HISAX_GAZEL) += gazel.o isac.o arcofi.o hscx.o hisax-$(CONFIG_HISAX_W6692) += w6692.o hisax-$(CONFIG_HISAX_ENTERNOW_PCI) += enternow_pci.o amd7930_fn.o #hisax-$(CONFIG_HISAX_TESTEMU) += testemu.o -CERT = $(shell cd $(src); md5sum -c md5sums.asc > /dev/null 2> /dev/null ;echo $$?) -CFLAGS_cert.o = -DCERTIFICATION=$(CERT) diff -Nru a/drivers/isdn/hisax/amd7930_fn.c b/drivers/isdn/hisax/amd7930_fn.c --- a/drivers/isdn/hisax/amd7930_fn.c Thu Feb 19 23:44:26 2004 +++ b/drivers/isdn/hisax/amd7930_fn.c Thu Feb 19 23:44:26 2004 @@ -62,42 +62,53 @@ static void Amd7930_new_ph(struct IsdnCardState *cs); -static inline u8 -HIBYTE(u16 w) -{ - return (w >> 8) & 0xff; -} +static WORD initAMD[] = { + 0x0100, -static inline u8 -LOBYTE(u16 w) -{ - return w & 0xff; -} + 0x00A5, 3, 0x01, 0x40, 0x58, // LPR, LMR1, LMR2 + 0x0086, 1, 0x0B, // DMR1 (D-Buffer TH-Interrupts on) + 0x0087, 1, 0xFF, // DMR2 + 0x0092, 1, 0x03, // EFCR (extended mode d-channel-fifo on) + 0x0090, 4, 0xFE, 0xFF, 0x02, 0x0F, // FRAR4, SRAR4, DMR3, DMR4 (address recognition ) + 0x0084, 2, 0x80, 0x00, // DRLR + 0x00C0, 1, 0x47, // PPCR1 + 0x00C8, 1, 0x01, // PPCR2 -static inline u8 -rByteAMD(struct IsdnCardState *cs, u8 reg) -{ - return cs->dc_hw_ops->read_reg(cs, reg); -} + 0x0102, + 0x0107, + 0x01A1, 1, + 0x0121, 1, + 0x0189, 2, -static inline void -wByteAMD(struct IsdnCardState *cs, u8 reg, u8 val) -{ - cs->dc_hw_ops->write_reg(cs, reg, val); -} + 0x0045, 4, 0x61, 0x72, 0x00, 0x00, // MCR1, MCR2, MCR3, MCR4 + 0x0063, 2, 0x08, 0x08, // GX + 0x0064, 2, 0x08, 0x08, // GR + 0x0065, 2, 0x99, 0x00, // GER + 0x0066, 2, 0x7C, 0x8B, // STG + 0x0067, 2, 0x00, 0x00, // FTGR1, FTGR2 + 0x0068, 2, 0x20, 0x20, // ATGR1, ATGR2 + 0x0069, 1, 0x4F, // MMR1 + 0x006A, 1, 0x00, // MMR2 + 0x006C, 1, 0x40, // MMR3 + 0x0021, 1, 0x02, // INIT + 0x00A3, 1, 0x40, // LMR1 -static void -wWordAMD(struct IsdnCardState *cs, u8 reg, u16 val) + 0xFFFF +}; + + +void /* macro wWordAMD */ +WriteWordAmd7930(struct IsdnCardState *cs, BYTE reg, WORD val) { wByteAMD(cs, 0x00, reg); wByteAMD(cs, 0x01, LOBYTE(val)); wByteAMD(cs, 0x01, HIBYTE(val)); } -static u16 -rWordAMD(struct IsdnCardState *cs, u8 reg) +WORD /* macro rWordAMD */ +ReadWordAmd7930(struct IsdnCardState *cs, BYTE reg) { - u16 res; + WORD res; /* direct access register */ if(reg < 8) { res = rByteAMD(cs, reg); @@ -112,20 +123,9 @@ return (res); } -static inline void -AmdIrqOff(struct IsdnCardState *cs) -{ - cs->dc.amd7930.setIrqMask(cs, 0); -} - -static inline void -AmdIrqOn(struct IsdnCardState *cs) -{ - cs->dc.amd7930.setIrqMask(cs, 1); -} static void -Amd7930_ph_command(struct IsdnCardState *cs, u8 command, char *s) +Amd7930_ph_command(struct IsdnCardState *cs, u_char command, char *s) { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "AMD7930: %s: ph_command 0x%02X", s, command); @@ -136,7 +136,7 @@ -static u8 i430States[] = { +static BYTE i430States[] = { // to reset F3 F4 F5 F6 F7 F8 AR from 0x01, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x00, // init 0x01, 0x02, 0x00, 0x00, 0x00, 0x07, 0x05, 0x00, // reset @@ -150,14 +150,14 @@ /* Row init - reset F3 F4 F5 F6 F7 F8 AR */ -static u8 stateHelper[] = { 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; +static BYTE stateHelper[] = { 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; static void Amd7930_get_state(struct IsdnCardState *cs) { - u8 lsr = rByteAMD(cs, 0xA1); + BYTE lsr = rByteAMD(cs, 0xA1); cs->dc.amd7930.ph_state = (lsr & 0x7) + 2; Amd7930_new_ph(cs); } @@ -167,8 +167,8 @@ static void Amd7930_new_ph(struct IsdnCardState *cs) { - u8 index = stateHelper[cs->dc.amd7930.old_state]*8 + stateHelper[cs->dc.amd7930.ph_state]-1; - u8 message = i430States[index]; + u_char index = stateHelper[cs->dc.amd7930.old_state]*8 + stateHelper[cs->dc.amd7930.ph_state]-1; + u_char message = i430States[index]; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "AMD7930: new_ph %d, old_ph %d, message %d, index %d", @@ -176,7 +176,7 @@ cs->dc.amd7930.old_state = cs->dc.amd7930.ph_state; - /* abort transmit if necessary */ + /* abort transmit if nessesary */ if ((message & 0xf0) && (cs->tx_skb)) { wByteAMD(cs, 0x21, 0xC2); wByteAMD(cs, 0x21, 0x02); @@ -232,9 +232,9 @@ static void -Amd7930_bh(void *data) +Amd7930_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; + struct PStack *stptr; if (!cs) @@ -244,7 +244,7 @@ debugl1(cs, "Amd7930: bh, D-Channel Busy cleared"); stptr = cs->stlist; while (stptr != NULL) { - stptr->l2.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); stptr = stptr->next; } } @@ -267,13 +267,12 @@ } } - static void Amd7930_empty_Dfifo(struct IsdnCardState *cs, int flag) { - u8 stat, der; - u8 *ptr; + BYTE stat, der; + BYTE *ptr; struct sk_buff *skb; @@ -317,7 +316,7 @@ QuickHex(t, cs->rcvbuf, cs->rcvidx); debugl1(cs, cs->dlog); } - /* moves received data in sk-buffer */ + /* moves recieved data in sk-buffer */ memcpy(skb_put(skb, cs->rcvidx), cs->rcvbuf, cs->rcvidx); skb_queue_tail(&cs->rq, skb); } @@ -327,10 +326,10 @@ /* throw damaged packets away, reset recieve-buffer, indicate RX */ ptr = cs->rcvbuf; cs->rcvidx = 0; - sched_d_event(cs, D_RCVBUFREADY); + schedule_event(cs, D_RCVBUFREADY); } } - /* Packet too long, overflow */ + /* Packet to long, overflow */ if(cs->rcvidx >= MAX_DFRAME_LEN_L1) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "AMD7930: empty_Dfifo L2-Framelength overrun"); @@ -346,9 +345,9 @@ Amd7930_fill_Dfifo(struct IsdnCardState *cs) { - u16 dtcrr, dtcrw, len, count; - u8 txstat, dmr3; - u8 *ptr, *deb_ptr; + WORD dtcrr, dtcrw, len, count; + BYTE txstat, dmr3; + BYTE *ptr, *deb_ptr; if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) debugl1(cs, "Amd7930: fill_Dfifo"); @@ -414,10 +413,10 @@ } -void Amd7930_interrupt(struct IsdnCardState *cs, u8 irflags) +void Amd7930_interrupt(struct IsdnCardState *cs, BYTE irflags) { - u8 dsr1, dsr2, lsr; - u16 der; + BYTE dsr1, dsr2, lsr; + WORD der; while (irflags) { @@ -443,7 +442,7 @@ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); + schedule_event(cs, D_CLEARBUSY); /* restart frame */ if (cs->tx_skb) { skb_push(cs->tx_skb, cs->tx_cnt); @@ -461,7 +460,7 @@ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); + schedule_event(cs, D_CLEARBUSY); /* restart TX-Frame */ if (cs->tx_skb) { skb_push(cs->tx_skb, cs->tx_cnt); @@ -482,7 +481,7 @@ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); + schedule_event(cs, D_CLEARBUSY); if (cs->tx_skb) { if (cs->tx_skb->len) Amd7930_fill_Dfifo(cs); @@ -511,7 +510,7 @@ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); + schedule_event(cs, D_CLEARBUSY); if (cs->tx_skb) { if (cs->debug & L1_DEB_ISAC) @@ -529,7 +528,7 @@ Amd7930_fill_Dfifo(cs); } else - sched_d_event(cs, D_XMTBUFREADY); + schedule_event(cs, D_XMTBUFREADY); /* AMD interrupts on */ AmdIrqOn(cs); } @@ -544,7 +543,7 @@ cs->dc.amd7930.ph_state = (lsr & 0x7) + 2; - sched_d_event(cs, D_L1STATECHANGE); + schedule_event(cs, D_L1STATECHANGE); /* AMD interrupts on */ AmdIrqOn(cs); } @@ -560,6 +559,7 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; + u_long flags; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "Amd7930: l1hw called, pr: 0x%04X", pr); @@ -570,6 +570,7 @@ LogFrame(cs, skb->data, skb->len); if (cs->debug & DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0); + spin_lock_irqsave(&cs->lock, flags); if (cs->tx_skb) { skb_queue_tail(&cs->sq, skb); #ifdef L2FRAME_DEBUG /* psa */ @@ -586,8 +587,10 @@ #endif Amd7930_fill_Dfifo(cs); } + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | INDICATION): + spin_lock_irqsave(&cs->lock, flags); if (cs->tx_skb) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "Amd7930: l1hw: l2l1 tx_skb exist this shouldn't happen"); @@ -606,6 +609,7 @@ Logl2Frame(cs, skb, "Amd7930: l1hw: PH_DATA_PULLED", 0); #endif Amd7930_fill_Dfifo(cs); + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | REQUEST): #ifdef L2FRAME_DEBUG /* psa */ @@ -614,21 +618,23 @@ #endif if (!cs->tx_skb) { test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - st->l2.l1l2(st, PH_PULL | CONFIRM, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); } else test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (HW_RESET | REQUEST): - - if ((cs->dc.amd7930.ph_state == 8)) - /* b-channels off, PH-AR cleared - * change to F3 */ - Amd7930_ph_command(cs, 0x20, "HW_RESET REQEST"); //LMR1 bit 5 - else { - Amd7930_ph_command(cs, 0x40, "HW_RESET REQUEST"); - cs->dc.amd7930.ph_state = 2; - Amd7930_new_ph(cs); - } + spin_lock_irqsave(&cs->lock, flags); + if ((cs->dc.amd7930.ph_state == 8)) { + /* b-channels off, PH-AR cleared + * change to F3 */ + Amd7930_ph_command(cs, 0x20, "HW_RESET REQEST"); //LMR1 bit 5 + spin_unlock_irqrestore(&cs->lock, flags); + } else { + Amd7930_ph_command(cs, 0x40, "HW_RESET REQUEST"); + cs->dc.amd7930.ph_state = 2; + spin_unlock_irqrestore(&cs->lock, flags); + Amd7930_new_ph(cs); + } break; case (HW_ENABLE | REQUEST): cs->dc.amd7930.ph_state = 9; @@ -650,7 +656,7 @@ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); + schedule_event(cs, D_CLEARBUSY); break; default: if (cs->debug & L1_DEB_WARN) @@ -659,7 +665,7 @@ } } -static int +void setstack_Amd7930(struct PStack *st, struct IsdnCardState *cs) { @@ -667,21 +673,30 @@ debugl1(cs, "Amd7930: setstack called"); st->l1.l1hw = Amd7930_l1hw; - return 0; } + +void +DC_Close_Amd7930(struct IsdnCardState *cs) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "Amd7930: DC_Close called"); +} + + static void dbusy_timer_handler(struct IsdnCardState *cs) { + u_long flags; struct PStack *stptr; - u16 dtcr, der; - u8 dsr1, dsr2; + WORD dtcr, der; + BYTE dsr1, dsr2; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "Amd7930: dbusy_timer expired!"); if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { + spin_lock_irqsave(&cs->lock, flags); /* D Transmit Byte Count Register: * Counts down packet's number of Bytes, 0 if packet ready */ dtcr = rWordAMD(cs, 0x85); @@ -689,14 +704,15 @@ dsr2 = rByteAMD(cs, 0x07); der = rWordAMD(cs, 0x03); - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "Amd7930: dbusy_timer_handler: DSR1=0x%02X, DSR2=0x%02X, DER=0x%04X, cs->tx_skb->len=%u, tx_stat=%u, dtcr=%u, cs->tx_cnt=%u", dsr1, dsr2, der, cs->tx_skb->len, cs->dc.amd7930.tx_xmtlen, dtcr, cs->tx_cnt); + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "Amd7930: dbusy_timer_handler: DSR1=0x%02X, DSR2=0x%02X, DER=0x%04X, cs->tx_skb->len=%u, tx_stat=%u, dtcr=%u, cs->tx_cnt=%u", dsr1, dsr2, der, cs->tx_skb->len, cs->dc.amd7930.tx_xmtlen, dtcr, cs->tx_cnt); - if ((int)(cs->dc.amd7930.tx_xmtlen - dtcr) < cs->tx_cnt) { /* D-Channel Busy */ + if ((cs->dc.amd7930.tx_xmtlen - dtcr) < cs->tx_cnt) { /* D-Channel Busy */ test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); stptr = cs->stlist; + spin_unlock_irqrestore(&cs->lock, flags); while (stptr != NULL) { - stptr->l2.l1l2(stptr, PH_PAUSE | INDICATION, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); stptr = stptr->next; } @@ -716,7 +732,8 @@ /* Transmitter reset, abort transmit */ wByteAMD(cs, 0x21, 0x82); wByteAMD(cs, 0x21, 0x02); - cs->card_ops->irq_func(cs->irq, cs, NULL); /* FIXME? */ + spin_unlock_irqrestore(&cs->lock, flags); + cs->irq_func(cs->irq, cs, NULL); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "Amd7930: dbusy_timer_handler: Transmitter reset"); @@ -724,59 +741,23 @@ } } -static u16 initAMD[] = { - 0x0100, - 0x00A5, 3, 0x01, 0x40, 0x58, // LPR, LMR1, LMR2 - 0x0086, 1, 0x0B, // DMR1 (D-Buffer TH-Interrupts on) - 0x0087, 1, 0xFF, // DMR2 - 0x0092, 1, 0x03, // EFCR (extended mode d-channel-fifo on) - 0x0090, 4, 0xFE, 0xFF, 0x02, 0x0F, // FRAR4, SRAR4, DMR3, DMR4 (address recognition ) - 0x0084, 2, 0x80, 0x00, // DRLR - 0x00C0, 1, 0x47, // PPCR1 - 0x00C8, 1, 0x01, // PPCR2 - - 0x0102, - 0x0107, - 0x01A1, 1, - 0x0121, 1, - 0x0189, 2, - - 0x0045, 4, 0x61, 0x72, 0x00, 0x00, // MCR1, MCR2, MCR3, MCR4 - 0x0063, 2, 0x08, 0x08, // GX - 0x0064, 2, 0x08, 0x08, // GR - 0x0065, 2, 0x99, 0x00, // GER - 0x0066, 2, 0x7C, 0x8B, // STG - 0x0067, 2, 0x00, 0x00, // FTGR1, FTGR2 - 0x0068, 2, 0x20, 0x20, // ATGR1, ATGR2 - 0x0069, 1, 0x4F, // MMR1 - 0x006A, 1, 0x00, // MMR2 - 0x006C, 1, 0x40, // MMR3 - 0x0021, 1, 0x02, // INIT - 0x00A3, 1, 0x40, // LMR1 - - 0xFFFF}; - -static struct dc_l1_ops amd7930_l1_ops = { - .open = setstack_Amd7930, - .bh_func = Amd7930_bh, - .dbusy_func = dbusy_timer_handler, -}; void __devinit Amd7930_init(struct IsdnCardState *cs) { - u16 *ptr; - u8 cmd, cnt; + WORD *ptr; + BYTE cmd, cnt; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "Amd7930: initamd called"); - dc_l1_init(cs, &amd7930_l1_ops); cs->dc.amd7930.tx_xmtlen = 0; cs->dc.amd7930.old_state = 0; cs->dc.amd7930.lmr1 = 0x40; cs->dc.amd7930.ph_command = Amd7930_ph_command; + cs->setstack_d = setstack_Amd7930; + cs->DC_Close = DC_Close_Amd7930; /* AMD Initialisation */ for (ptr = initAMD; *ptr != 0xFFFF; ) { @@ -805,11 +786,11 @@ } } -int -amd7930_setup(struct IsdnCardState *cs, struct dc_hw_ops *amd7930_ops, - void (*set_irq_mask)(struct IsdnCardState *, u8 val)) -{ - cs->dc_hw_ops = amd7930_ops; - cs->dc.amd7930.setIrqMask = set_irq_mask; - return 0; +void __devinit +setup_Amd7930(struct IsdnCardState *cs) +{ + INIT_WORK(&cs->tqueue, (void *)(void *) Amd7930_bh, cs); + cs->dbusytimer.function = (void *) dbusy_timer_handler; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); } diff -Nru a/drivers/isdn/hisax/amd7930_fn.h b/drivers/isdn/hisax/amd7930_fn.h --- a/drivers/isdn/hisax/amd7930_fn.h Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/hisax/amd7930_fn.h Thu Feb 19 23:44:28 2004 @@ -12,13 +12,26 @@ */ + + +#define BYTE unsigned char +#define WORD unsigned int +#define rByteAMD(cs, reg) cs->readisac(cs, reg) +#define wByteAMD(cs, reg, val) cs->writeisac(cs, reg, val) +#define rWordAMD(cs, reg) ReadWordAmd7930(cs, reg) +#define wWordAMD(cs, reg, val) WriteWordAmd7930(cs, reg, val) +#define HIBYTE(w) ((unsigned char)((w & 0xff00) / 256)) +#define LOBYTE(w) ((unsigned char)(w & 0x00ff)) + +#define AmdIrqOff(cs) cs->dc.amd7930.setIrqMask(cs, 0) +#define AmdIrqOn(cs) cs->dc.amd7930.setIrqMask(cs, 1) + #define AMD_CR 0x00 #define AMD_DR 0x01 #define DBUSY_TIMER_VALUE 80 -void Amd7930_interrupt(struct IsdnCardState *cs, unsigned char irflags); -void Amd7930_init(struct IsdnCardState *cs); -int amd7930_setup(struct IsdnCardState *cs, struct dc_hw_ops *amd7930_ops, - void (*set_irq_mask)(struct IsdnCardState *, u8 val)); +extern void Amd7930_interrupt(struct IsdnCardState *, unsigned char); +extern void Amd7930_init(struct IsdnCardState *); +extern void setup_Amd7930(struct IsdnCardState *); diff -Nru a/drivers/isdn/hisax/arcofi.c b/drivers/isdn/hisax/arcofi.c --- a/drivers/isdn/hisax/arcofi.c Thu Feb 19 23:44:26 2004 +++ b/drivers/isdn/hisax/arcofi.c Thu Feb 19 23:44:26 2004 @@ -1,4 +1,4 @@ -/* $Id: arcofi.c,v 1.12.6.2 2001/09/23 22:24:46 kai Exp $ +/* $Id: arcofi.c,v 1.14.2.3 2004/01/13 14:31:24 keil Exp $ * * Ansteuerung ARCOFI 2165 * @@ -17,19 +17,6 @@ #define ARCOFI_TIMER_VALUE 20 - -static inline u8 -isac_read(struct IsdnCardState *cs, u8 addr) -{ - return cs->dc_hw_ops->read_reg(cs, addr); -} - -static inline void -isac_write(struct IsdnCardState *cs, u8 addr, u8 val) -{ - cs->dc_hw_ops->write_reg(cs, addr, val); -} - static void add_arcofi_timer(struct IsdnCardState *cs) { if (test_and_set_bit(FLG_ARCOFI_TIMER, &cs->HW_Flags)) { @@ -42,7 +29,7 @@ static void send_arcofi(struct IsdnCardState *cs) { - u8 val; + u_char val; add_arcofi_timer(cs); cs->dc.isac.mon_txp = 0; @@ -56,11 +43,11 @@ } cs->dc.isac.mocr &= 0x0f; cs->dc.isac.mocr |= 0xa0; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); - val = isac_read(cs, ISAC_MOSR); - isac_write(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); + val = cs->readisac(cs, ISAC_MOSR); + cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]); cs->dc.isac.mocr |= 0x10; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); } int diff -Nru a/drivers/isdn/hisax/asuscom.c b/drivers/isdn/hisax/asuscom.c --- a/drivers/isdn/hisax/asuscom.c Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/hisax/asuscom.c Thu Feb 19 23:44:28 2004 @@ -1,4 +1,4 @@ -/* $Id: asuscom.c,v 1.11.6.3 2001/09/23 22:24:46 kai Exp $ +/* $Id: asuscom.c,v 1.14.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for ASUSCOM NETWORK INC. ISDNLink cards * @@ -22,9 +22,8 @@ extern const char *CardType[]; -const char *Asuscom_revision = "$Revision: 1.11.6.3 $"; +const char *Asuscom_revision = "$Revision: 1.14.2.4 $"; -static spinlock_t asuscom_lock = SPIN_LOCK_UNLOCKED; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -43,237 +42,258 @@ /* CARD_ADR (Write) */ #define ASUS_RESET 0x80 /* Bit 7 Reset-Leitung */ -static inline u8 -readreg(struct IsdnCardState *cs, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&asuscom_lock, flags); - byteout(cs->hw.asus.adr, off); + byteout(ale, off); ret = bytein(adr); - spin_unlock_irqrestore(&asuscom_lock, flags); - return ret; + return (ret); } static inline void -writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; - - spin_lock_irqsave(&asuscom_lock, flags); - byteout(cs->hw.asus.adr, off); - byteout(adr, data); - spin_unlock_irqrestore(&asuscom_lock, flags); + byteout(ale, off); + insb(adr, data, size); } + static inline void -readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { - byteout(cs->hw.asus.adr, off); - insb(adr, data, size); + byteout(ale, off); + byteout(adr, data); } - static inline void -writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - byteout(cs->hw.asus.adr, off); + byteout(ale, off); outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.asus.isac, offset); + return (readreg(cs->hw.asus.adr, cs->hw.asus.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.asus.isac, offset, value); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - readfifo(cs, cs->hw.asus.isac, 0, data, size); + readfifo(cs->hw.asus.adr, cs->hw.asus.isac, 0, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs, cs->hw.asus.isac, 0, data, size); + writefifo(cs->hw.asus.adr, cs->hw.asus.isac, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0)); + return (readreg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0), value); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, offset|0x80, value); } static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - readfifo(cs, cs->hw.asus.hscx, hscx ? 0x40 : 0, data, size); + readfifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size); } static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs, cs->hw.asus.hscx, hscx ? 0x40 : 0, data, size); + writefifo(cs->hw.asus.adr, cs->hw.asus.isac, 0x80, data, size); } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static inline u8 -ipac_read(struct IsdnCardState *cs, u8 off) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - u8 ret; - unsigned long flags; - - spin_lock_irqsave(&asuscom_lock, flags); - byteout(cs->hw.asus.adr, off); - ret = bytein(cs->hw.asus.isac); - spin_unlock_irqrestore(&asuscom_lock, flags); - return ret; + return (readreg(cs->hw.asus.adr, + cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0))); } -static inline void -ipac_write(struct IsdnCardState *cs, u8 off, u8 data) -{ - unsigned long flags; - - spin_lock_irqsave(&asuscom_lock, flags); - byteout(cs->hw.asus.adr, off); - byteout(cs->hw.asus.isac, data); - spin_unlock_irqrestore(&asuscom_lock, flags); -} - -static inline void -ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 * data, int size) +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - byteout(cs->hw.asus.adr, off); - insb(cs->hw.asus.isac, data, size); + writereg(cs->hw.asus.adr, + cs->hw.asus.hscx, offset + (hscx ? 0x40 : 0), value); } +/* + * fast interrupt HSCX stuff goes here + */ -static inline void -ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 * data, int size) -{ - byteout(cs->hw.asus.adr, off); - outsb(cs->hw.asus.isac, data, size); +#define READHSCX(cs, nr, reg) readreg(cs->hw.asus.adr, \ + cs->hw.asus.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.asus.adr, \ + cs->hw.asus.hscx, reg + (nr ? 0x40 : 0), data) + +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.asus.adr, \ + cs->hw.asus.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.asus.adr, \ + cs->hw.asus.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" + +static irqreturn_t +asuscom_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40); + if (val) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA); + if (val) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_MASK, 0x0); + writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK, 0x0); + writereg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_MASK + 0x40, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} + +static irqreturn_t +asuscom_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char ista, val, icnt = 5; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA); +Start_IPAC: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = readreg(cs->hw.asus.adr, cs->hw.asus.hscx, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) + hscx_int_main(cs, val); + } + if (ista & 0x20) { + val = 0xfe & readreg(cs->hw.asus.adr, cs->hw.asus.isac, ISAC_ISTA | 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = readreg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPAC; + } + if (!icnt) + printk(KERN_WARNING "ASUS IRQ LOOP\n"); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xFF); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xC0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; } -/* This will generate ipac_dc_ops and ipac_bc_ops using the functions - * above */ +void +release_io_asuscom(struct IsdnCardState *cs) +{ + int bytecnt = 8; -BUILD_IPAC_OPS(ipac); + if (cs->hw.asus.cfg_reg) + release_region(cs->hw.asus.cfg_reg, bytecnt); +} -static int -asuscom_reset(struct IsdnCardState *cs) +static void +reset_asuscom(struct IsdnCardState *cs) { - byteout(cs->hw.asus.adr, ASUS_RESET); /* Reset On */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - byteout(cs->hw.asus.adr, 0); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - return 0; + if (cs->subtyp == ASUS_IPAC) + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x20); + else + byteout(cs->hw.asus.adr, ASUS_RESET); /* Reset On */ + mdelay(10); + if (cs->subtyp == ASUS_IPAC) + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_POTA2, 0x0); + else + byteout(cs->hw.asus.adr, 0); /* Reset Off */ + mdelay(10); + if (cs->subtyp == ASUS_IPAC) { + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_CONF, 0x0); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_ACFG, 0xff); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_AOE, 0x0); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_MASK, 0xc0); + writereg(cs->hw.asus.adr, cs->hw.asus.isac, IPAC_PCFG, 0x12); + } } static int -asuscom_ipac_reset(struct IsdnCardState *cs) +Asus_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - writereg(cs, cs->hw.asus.isac, IPAC_POTA2, 0x20); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writereg(cs, cs->hw.asus.isac, IPAC_POTA2, 0x0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writereg(cs, cs->hw.asus.isac, IPAC_CONF, 0x0); - writereg(cs, cs->hw.asus.isac, IPAC_ACFG, 0xff); - writereg(cs, cs->hw.asus.isac, IPAC_AOE, 0x0); - writereg(cs, cs->hw.asus.isac, IPAC_MASK, 0xc0); - writereg(cs, cs->hw.asus.isac, IPAC_PCFG, 0x12); - return 0; -} - -static struct card_ops asuscom_ops = { - .init = inithscxisac, - .reset = asuscom_reset, - .release = hisax_release_resources, - .irq_func = hscxisac_irq, -}; - -static struct card_ops asuscom_ipac_ops = { - .init = ipac_init, - .reset = asuscom_ipac_reset, - .release = hisax_release_resources, - .irq_func = ipac_irq, -}; + u_long flags; -static int __init -asuscom_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - int rc; - u8 val; - - printk(KERN_INFO "ISDNLink: defined at %#lx IRQ %lu\n", - card->para[1], card->para[0]); - - cs->hw.asus.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - - rc = -EBUSY; - if (!request_io(&cs->rs, cs->hw.asus.cfg_reg, 8, "asuscom isdn")) - goto err; - - rc = -ENODEV; - cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE; - val = readreg(cs, cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID); - if ((val == 1) || (val == 2)) { - cs->subtyp = ASUS_IPAC; - cs->card_ops = &asuscom_ipac_ops; - cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - } else { - cs->subtyp = ASUS_ISACHSCX; - cs->card_ops = &asuscom_ops; - cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR; - cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC; - cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX; - cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7; - cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_asuscom(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_asuscom(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + cs->debug |= L1_DEB_IPAC; + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); } - printk(KERN_INFO "ISDNLink: resetting card\n"); - cs->card_ops->reset(cs); - return 0; - - err: - hisax_release_resources(cs); - return rc; + return(0); } #ifdef __ISAPNP__ @@ -293,66 +313,115 @@ { 0, } }; -static struct isapnp_device_id *adev = &asus_ids[0]; +static struct isapnp_device_id *ipid __initdata = &asus_ids[0]; static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __init setup_asuscom(struct IsdnCard *card) { + int bytecnt; + struct IsdnCardState *cs = card->cs; + u_char val; char tmp[64]; strcpy(tmp, Asuscom_revision); printk(KERN_INFO "HiSax: Asuscom ISDNLink driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_ASUSCOM) + return (0); #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; + struct pnp_dev *pnp_d; + while(ipid->card_vendor) { + if ((pnp_c = pnp_find_card(ipid->card_vendor, + ipid->card_device, pnp_c))) { + pnp_d = NULL; + if ((pnp_d = pnp_find_dev(pnp_c, + ipid->vendor, ipid->function, pnp_d))) { + int err; - while(adev->card_vendor) { - if ((pb = pnp_find_card(adev->card_vendor, - adev->card_device, - pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - adev->vendor, - adev->function, - pd))) { printk(KERN_INFO "HiSax: %s detected\n", - (char *)adev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "AsusPnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "AsusPnP: activate failed\n"); - pnp_device_detach(pd); - return 0; + (char *)ipid->driver_data); + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[0] = pnp_irq(pnp_d, 0); + if (!card->para[0] || !card->para[1]) { printk(KERN_ERR "AsusPnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); + card->para[0], card->para[1]); + pnp_disable_dev(pnp_d); return(0); } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); break; } else { printk(KERN_ERR "AsusPnP: PnP error card found, no device\n"); } } - adev++; - pnp_c=NULL; + ipid++; + pnp_c = NULL; } - if (!adev->card_vendor) { + if (!ipid->card_vendor) { printk(KERN_INFO "AsusPnP: no ISAPnP card found\n"); return(0); } } #endif - if (asuscom_probe(card->cs, card) < 0) - return 0; - return 1; + bytecnt = 8; + cs->hw.asus.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + if (!request_region(cs->hw.asus.cfg_reg, bytecnt, "asuscom isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.asus.cfg_reg, + cs->hw.asus.cfg_reg + bytecnt); + return (0); + } + printk(KERN_INFO "ISDNLink: defined at 0x%x IRQ %d\n", + cs->hw.asus.cfg_reg, cs->irq); + setup_isac(cs); + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &Asus_card_msg; + val = readreg(cs->hw.asus.cfg_reg + ASUS_IPAC_ALE, + cs->hw.asus.cfg_reg + ASUS_IPAC_DATA, IPAC_ID); + if ((val == 1) || (val == 2)) { + cs->subtyp = ASUS_IPAC; + cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_IPAC_ALE; + cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA; + cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_IPAC_DATA; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + cs->readisac = &ReadISAC_IPAC; + cs->writeisac = &WriteISAC_IPAC; + cs->readisacfifo = &ReadISACfifo_IPAC; + cs->writeisacfifo = &WriteISACfifo_IPAC; + cs->irq_func = &asuscom_interrupt_ipac; + printk(KERN_INFO "Asus: IPAC version %x\n", val); + } else { + cs->subtyp = ASUS_ISACHSCX; + cs->hw.asus.adr = cs->hw.asus.cfg_reg + ASUS_ADR; + cs->hw.asus.isac = cs->hw.asus.cfg_reg + ASUS_ISAC; + cs->hw.asus.hscx = cs->hw.asus.cfg_reg + ASUS_HSCX; + cs->hw.asus.u7 = cs->hw.asus.cfg_reg + ASUS_CTRL_U7; + cs->hw.asus.pots = cs->hw.asus.cfg_reg + ASUS_CTRL_POTS; + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->irq_func = &asuscom_interrupt; + ISACVersion(cs, "ISDNLink:"); + if (HscxVersion(cs, "ISDNLink:")) { + printk(KERN_WARNING + "ISDNLink: wrong HSCX versions check IO address\n"); + release_io_asuscom(cs); + return (0); + } + } + return (1); } diff -Nru a/drivers/isdn/hisax/avm_a1.c b/drivers/isdn/hisax/avm_a1.c --- a/drivers/isdn/hisax/avm_a1.c Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/avm_a1.c Thu Feb 19 23:44:23 2004 @@ -1,4 +1,4 @@ -/* $Id: avm_a1.c,v 2.13.6.2 2001/09/23 22:24:46 kai Exp $ +/* $Id: avm_a1.c,v 2.15.2.4 2004/01/13 21:46:03 keil Exp $ * * low level stuff for AVM A1 (Fritz) isdn cards * @@ -17,7 +17,7 @@ #include "isdnl1.h" extern const char *CardType[]; -static const char *avm_revision = "$Revision: 2.13.6.2 $"; +static const char *avm_revision = "$Revision: 2.15.2.4 $"; #define AVM_A1_STAT_ISAC 0x01 #define AVM_A1_STAT_HSCX 0x02 @@ -26,172 +26,237 @@ #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static inline u8 -readreg(unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int adr, u_char off) { return (bytein(adr + off)); } static inline void -writereg(unsigned int adr, u8 off, u8 data) +writereg(unsigned int adr, u_char off, u_char data) { byteout(adr + off, data); } static inline void -read_fifo(unsigned int adr, u8 * data, int size) +read_fifo(unsigned int adr, u_char * data, int size) { insb(adr, data, size); } static void -write_fifo(unsigned int adr, u8 * data, int size) +write_fifo(unsigned int adr, u_char * data, int size) { outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs->hw.avm.isac, offset); + return (readreg(cs->hw.avm.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { writereg(cs->hw.avm.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { read_fifo(cs->hw.avm.isacfifo, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { write_fifo(cs->hw.avm.isacfifo, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { return (readreg(cs->hw.avm.hscx[hscx], offset)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { writereg(cs->hw.avm.hscx[hscx], offset, value); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - read_fifo(cs->hw.avm.hscxfifo[hscx], data, size); -} +/* + * fast interrupt HSCX stuff goes here + */ -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - write_fifo(cs->hw.avm.hscxfifo[hscx], data, size); -} +#define READHSCX(cs, nr, reg) readreg(cs->hw.avm.hscx[nr], reg) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.avm.hscx[nr], reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.avm.hscxfifo[nr], ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.avm.hscxfifo[nr], ptr, cnt) -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; +#include "hscx_irq.c" static irqreturn_t avm_a1_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val, sval; - int handled = 0; + u_char val, sval; + u_long flags; - spin_lock(&cs->lock); + spin_lock_irqsave(&cs->lock, flags); while (((sval = bytein(cs->hw.avm.cfg_reg)) & 0xf) != 0x7) { - handled = 1; if (!(sval & AVM_A1_STAT_TIMER)) { byteout(cs->hw.avm.cfg_reg, 0x1E); sval = bytein(cs->hw.avm.cfg_reg); } else if (cs->debug & L1_DEB_INTSTAT) debugl1(cs, "avm IntStatus %x", sval); if (!(sval & AVM_A1_STAT_HSCX)) { - val = hscx_read(cs, 1, HSCX_ISTA); + val = readreg(cs->hw.avm.hscx[1], HSCX_ISTA); if (val) hscx_int_main(cs, val); } if (!(sval & AVM_A1_STAT_ISAC)) { - val = isac_read(cs, ISAC_ISTA); + val = readreg(cs->hw.avm.isac, ISAC_ISTA); if (val) isac_interrupt(cs, val); } } - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(cs, 0, HSCX_MASK, 0x0); - hscx_write(cs, 1, HSCX_MASK, 0x0); - spin_unlock(&cs->lock); - return IRQ_RETVAL(handled); + writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0xFF); + writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0xFF); + writereg(cs->hw.avm.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.avm.isac, ISAC_MASK, 0x0); + writereg(cs->hw.avm.hscx[0], HSCX_MASK, 0x0); + writereg(cs->hw.avm.hscx[1], HSCX_MASK, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} + +inline static void +release_ioregs(struct IsdnCardState *cs, int mask) +{ + release_region(cs->hw.avm.cfg_reg, 8); + if (mask & 1) + release_region(cs->hw.avm.isac + 32, 32); + if (mask & 2) + release_region(cs->hw.avm.isacfifo, 1); + if (mask & 4) + release_region(cs->hw.avm.hscx[0] + 32, 32); + if (mask & 8) + release_region(cs->hw.avm.hscxfifo[0], 1); + if (mask & 0x10) + release_region(cs->hw.avm.hscx[1] + 32, 32); + if (mask & 0x20) + release_region(cs->hw.avm.hscxfifo[1], 1); +} + +static int +AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + u_long flags; + + switch (mt) { + case CARD_RESET: + return(0); + case CARD_RELEASE: + release_ioregs(cs, 0x3f); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithscxisac(cs, 1); + byteout(cs->hw.avm.cfg_reg, 0x16); + byteout(cs->hw.avm.cfg_reg, 0x1E); + inithscxisac(cs, 2); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); } -static void -avm_a1_init(struct IsdnCardState *cs) +int __init +setup_avm_a1(struct IsdnCard *card) { - byteout(cs->hw.avm.cfg_reg, 0x16); - byteout(cs->hw.avm.cfg_reg, 0x1E); - inithscxisac(cs); -} - -static struct card_ops avm_a1_ops = { - .init = avm_a1_init, - .release = hisax_release_resources, - .irq_func = avm_a1_interrupt, -}; - -static int __init -avm_a1_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - int rc; - u8 val; - - printk(KERN_INFO "AVM A1: defined at %#lx IRQ %lu\n", - card->para[1], card->para[0]); - - rc = -EBUSY; - cs->hw.avm.cfg_reg = request_io(&cs->rs, card->para[1] + 0x1800, 8, "avm cfg"); - if (!cs->hw.avm.cfg_reg) goto err; - cs->hw.avm.isac = request_io(&cs->rs, card->para[1] + 0x1400, 32, "HiSax isac"); - if (!cs->hw.avm.isac) goto err; - cs->hw.avm.isacfifo = request_io(&cs->rs, card->para[1] + 0x1000, 1, "HiSax isac fifo"); - if (!cs->hw.avm.isacfifo) goto err; - cs->hw.avm.hscx[0] = request_io(&cs->rs, card->para[1] + 0x400, 32, "HiSax hscx A"); - if (!cs->hw.avm.hscx[0]) goto err; - cs->hw.avm.hscxfifo[0] = request_io(&cs->rs, card->para[1], 1, "HiSax hscx A fifo"); - if (!cs->hw.avm.hscxfifo[0]) goto err; - cs->hw.avm.hscx[1] = request_io(&cs->rs, card->para[1] + 0xc00, 32, "HiSax hscx B"); - if (!cs->hw.avm.hscx[1]) goto err; - cs->hw.avm.hscxfifo[1] = request_io(&cs->rs, card->para[1] + 0x800, 1, "HiSax hscx B fifo"); - if (!cs->hw.avm.hscxfifo[1]) goto err; - cs->hw.avm.isac -= 0x20; - cs->hw.avm.hscx[0] -= 0x20; - cs->hw.avm.hscx[1] -= 0x20; - cs->irq = card->para[0]; + u_char val; + struct IsdnCardState *cs = card->cs; + char tmp[64]; + + strcpy(tmp, avm_revision); + printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_A1) + return (0); + cs->hw.avm.cfg_reg = card->para[1] + 0x1800; + cs->hw.avm.isac = card->para[1] + 0x1400 - 0x20; + cs->hw.avm.hscx[0] = card->para[1] + 0x400 - 0x20; + cs->hw.avm.hscx[1] = card->para[1] + 0xc00 - 0x20; + cs->hw.avm.isacfifo = card->para[1] + 0x1000; + cs->hw.avm.hscxfifo[0] = card->para[1]; + cs->hw.avm.hscxfifo[1] = card->para[1] + 0x800; + cs->irq = card->para[0]; + if (!request_region(cs->hw.avm.cfg_reg, 8, "avm cfg")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.avm.cfg_reg, + cs->hw.avm.cfg_reg + 8); + return (0); + } + if (!request_region(cs->hw.avm.isac + 32, 32, "HiSax isac")) { + printk(KERN_WARNING + "HiSax: %s isac ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.avm.isac + 32, + cs->hw.avm.isac + 64); + release_ioregs(cs, 0); + return (0); + } + if (!request_region(cs->hw.avm.isacfifo, 1, "HiSax isac fifo")) { + printk(KERN_WARNING + "HiSax: %s isac fifo port %x already in use\n", + CardType[cs->typ], + cs->hw.avm.isacfifo); + release_ioregs(cs, 1); + return (0); + } + if (!request_region(cs->hw.avm.hscx[0] + 32, 32, "HiSax hscx A")) { + printk(KERN_WARNING + "HiSax: %s hscx A ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.avm.hscx[0] + 32, + cs->hw.avm.hscx[0] + 64); + release_ioregs(cs, 3); + return (0); + } + if (!request_region(cs->hw.avm.hscxfifo[0], 1, "HiSax hscx A fifo")) { + printk(KERN_WARNING + "HiSax: %s hscx A fifo port %x already in use\n", + CardType[cs->typ], + cs->hw.avm.hscxfifo[0]); + release_ioregs(cs, 7); + return (0); + } + if (!request_region(cs->hw.avm.hscx[1] + 32, 32, "HiSax hscx B")) { + printk(KERN_WARNING + "HiSax: %s hscx B ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.avm.hscx[1] + 32, + cs->hw.avm.hscx[1] + 64); + release_ioregs(cs, 0xf); + return (0); + } + if (!request_region(cs->hw.avm.hscxfifo[1], 1, "HiSax hscx B fifo")) { + printk(KERN_WARNING + "HiSax: %s hscx B fifo port %x already in use\n", + CardType[cs->typ], + cs->hw.avm.hscxfifo[1]); + release_ioregs(cs, 0x1f); + return (0); + } byteout(cs->hw.avm.cfg_reg, 0x0); HZDELAY(HZ / 5 + 1); byteout(cs->hw.avm.cfg_reg, 0x1); @@ -219,24 +284,34 @@ printk(KERN_INFO "AVM A1: Byte at %x is %x\n", cs->hw.avm.cfg_reg, val); - cs->card_ops = &avm_a1_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return rc; -} - -int __init -setup_avm_a1(struct IsdnCard *card) -{ - char tmp[64]; - - strcpy(tmp, avm_revision); - printk(KERN_INFO "HiSax: AVM driver Rev. %s\n", HiSax_getrev(tmp)); - - if (avm_a1_probe(card->cs, card) < 0) - return 0; - return 1; + printk(KERN_INFO + "HiSax: %s config irq:%d cfg:0x%X\n", + CardType[cs->typ], cs->irq, + cs->hw.avm.cfg_reg); + printk(KERN_INFO + "HiSax: isac:0x%X/0x%X\n", + cs->hw.avm.isac + 32, cs->hw.avm.isacfifo); + printk(KERN_INFO + "HiSax: hscx A:0x%X/0x%X hscx B:0x%X/0x%X\n", + cs->hw.avm.hscx[0] + 32, cs->hw.avm.hscxfifo[0], + cs->hw.avm.hscx[1] + 32, cs->hw.avm.hscxfifo[1]); + + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + setup_isac(cs); + cs->cardmsg = &AVM_card_msg; + cs->irq_func = &avm_a1_interrupt; + ISACVersion(cs, "AVM A1:"); + if (HscxVersion(cs, "AVM A1:")) { + printk(KERN_WARNING + "AVM A1: wrong HSCX versions check IO address\n"); + release_ioregs(cs, 0x3f); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/avm_a1p.c b/drivers/isdn/hisax/avm_a1p.c --- a/drivers/isdn/hisax/avm_a1p.c Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/hisax/avm_a1p.c Thu Feb 19 23:44:28 2004 @@ -1,4 +1,4 @@ -/* $Id: avm_a1p.c,v 2.7.6.2 2001/09/23 22:24:46 kai Exp $ +/* $Id: avm_a1p.c,v 2.9.2.5 2004/01/24 20:47:19 keil Exp $ * * low level stuff for the following AVM cards: * A1 PCMCIA @@ -56,176 +56,182 @@ #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static const char *avm_revision = "$Revision: 2.7.6.2 $"; -static spinlock_t avm_a1p_lock = SPIN_LOCK_UNLOCKED; +static const char *avm_revision = "$Revision: 2.9.2.5 $"; -static inline u8 -readreg(struct IsdnCardState *cs, int offset, u8 adr) +static inline u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - unsigned long flags; - u8 ret; + u_char ret; - spin_lock_irqsave(&avm_a1p_lock, flags); - byteout(cs->hw.avm.cfg_reg + ADDRREG_OFFSET, offset + adr - 0x20); - ret = bytein(cs->hw.avm.cfg_reg + DATAREG_OFFSET); - spin_unlock_irqrestore(&avm_a1p_lock, flags); + offset -= 0x20; + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset); + ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET); return ret; } static inline void -writereg(struct IsdnCardState *cs, int offset, u8 adr, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - unsigned long flags; - - spin_lock_irqsave(&avm_a1p_lock, flags); - byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, offset + adr - 0x20); + offset -= 0x20; + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_REG_OFFSET+offset); byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value); - spin_unlock_irqrestore(&avm_a1p_lock, flags); } static inline void -readfifo(struct IsdnCardState *cs, int offset, u8 *data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - byteout(cs->hw.avm.cfg_reg + ADDRREG_OFFSET, offset); - insb(cs->hw.avm.cfg_reg + DATAREG_OFFSET, data, size); + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET); + insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size); } static inline void -writefifo(struct IsdnCardState *cs, int offset, u8 *data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, offset); + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET,ISAC_FIFO_OFFSET); outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 adr) -{ - return readreg(cs, ISAC_REG_OFFSET, adr); -} - -static void -isac_write(struct IsdnCardState *cs, u8 adr, u8 value) +static inline u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - writereg(cs, ISAC_REG_OFFSET, adr, value); -} + u_char ret; -static void -isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size) -{ - readfifo(cs, ISAC_FIFO_OFFSET, data, size); + offset -= 0x20; + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, + HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset); + ret = bytein(cs->hw.avm.cfg_reg+DATAREG_OFFSET); + return ret; } -static void -isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size) +static inline void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - writefifo(cs, ISAC_FIFO_OFFSET, data, size); + offset -= 0x20; + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, + HSCX_REG_OFFSET+hscx*HSCX_CH_DIFF+offset); + byteout(cs->hw.avm.cfg_reg+DATAREG_OFFSET, value); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 adr) +static inline void +ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size) { - return readreg(cs, HSCX_REG_OFFSET + hscx*HSCX_CH_DIFF, adr); + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, + HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF); + insb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size); } -static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 adr, u8 value) +static inline void +WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size) { - writereg(cs, HSCX_REG_OFFSET + hscx*HSCX_CH_DIFF, adr, value); + byteout(cs->hw.avm.cfg_reg+ADDRREG_OFFSET, + HSCX_FIFO_OFFSET+hscx*HSCX_CH_DIFF); + outsb(cs->hw.avm.cfg_reg+DATAREG_OFFSET, data, size); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - return readfifo(cs, HSCX_FIFO_OFFSET + hscx*HSCX_CH_DIFF, data, size); -} +/* + * fast interrupt HSCX stuff goes here + */ -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - writefifo(cs, HSCX_FIFO_OFFSET + hscx*HSCX_CH_DIFF, data, size); -} +#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg) +#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt) -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; +#include "hscx_irq.c" static irqreturn_t avm_a1p_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val, sval; + u_char val, sval; + u_long flags; - spin_lock(&cs->lock); + spin_lock_irqsave(&cs->lock, flags); while ((sval = (~bytein(cs->hw.avm.cfg_reg+ASL0_OFFSET) & ASL0_R_IRQPENDING))) { if (cs->debug & L1_DEB_INTSTAT) debugl1(cs, "avm IntStatus %x", sval); if (sval & ASL0_R_HSCX) { - val = hscx_read(cs, 1, HSCX_ISTA); + val = ReadHSCX(cs, 1, HSCX_ISTA); if (val) hscx_int_main(cs, val); } if (sval & ASL0_R_ISAC) { - val = isac_read(cs, ISAC_ISTA); + val = ReadISAC(cs, ISAC_ISTA); if (val) isac_interrupt(cs, val); } } - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(cs, 0, HSCX_MASK, 0x0); - hscx_write(cs, 1, HSCX_MASK, 0x0); - spin_unlock(&cs->lock); + WriteHSCX(cs, 0, HSCX_MASK, 0xff); + WriteHSCX(cs, 1, HSCX_MASK, 0xff); + WriteISAC(cs, ISAC_MASK, 0xff); + WriteISAC(cs, ISAC_MASK, 0x00); + WriteHSCX(cs, 0, HSCX_MASK, 0x00); + WriteHSCX(cs, 1, HSCX_MASK, 0x00); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } -static void -avm_a1p_init(struct IsdnCardState *cs) -{ - byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET, - ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE); - inithscxisac(cs); -} - static int -avm_a1p_reset(struct IsdnCardState *cs) +AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); - HZDELAY(HZ / 5 + 1); - byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET); - HZDELAY(HZ / 5 + 1); - byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); + u_long flags; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); + HZDELAY(HZ / 5 + 1); + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET); + HZDELAY(HZ / 5 + 1); + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); + spin_unlock_irqrestore(&cs->lock, flags); + return 0; + + case CARD_RELEASE: + /* free_irq is done in HiSax_closecard(). */ + /* free_irq(cs->irq, cs); */ + return 0; + + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_TDISABLE|ASL0_W_TRESET|ASL0_W_IRQENABLE); + clear_pending_isac_ints(cs); + clear_pending_hscx_ints(cs); + inithscxisac(cs, 1); + inithscxisac(cs, 2); + spin_unlock_irqrestore(&cs->lock, flags); + return 0; + + case CARD_TEST: + /* we really don't need it for the PCMCIA Version */ + return 0; + + default: + /* all card drivers ignore others, so we do the same */ + return 0; + } return 0; } -static struct card_ops avm_a1p_ops = { - .init = avm_a1p_init, - .reset = avm_a1p_reset, - .irq_func = avm_a1p_interrupt, -}; - -static int __init -avm_a1p_probe(struct IsdnCardState *cs, struct IsdnCard *card) +int +setup_avm_a1_pcmcia(struct IsdnCard *card) { - u8 model, vers; + u_char model, vers; + struct IsdnCardState *cs = card->cs; + char tmp[64]; + + + strcpy(tmp, avm_revision); + printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n", + HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_A1_PCMCIA) + return (0); - cs->irq = card->para[0]; cs->hw.avm.cfg_reg = card->para[1]; + cs->irq = card->para[0]; - outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0); + outb(cs->hw.avm.cfg_reg+ASL1_OFFSET, ASL1_W_ENABLE_S0); byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,0x00); HZDELAY(HZ / 5 + 1); byteout(cs->hw.avm.cfg_reg+ASL0_OFFSET,ASL0_W_RESET); @@ -238,26 +244,25 @@ vers = bytein(cs->hw.avm.cfg_reg+VERREG_OFFSET); printk(KERN_INFO "AVM A1 PCMCIA: io 0x%x irq %d model %d version %d\n", - cs->hw.avm.cfg_reg, cs->irq, model, vers); - - cs->card_ops = &avm_a1p_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -int __devinit -setup_avm_a1_pcmcia(struct IsdnCard *card) -{ - char tmp[64]; + cs->hw.avm.cfg_reg, cs->irq, model, vers); - strcpy(tmp, avm_revision); - printk(KERN_INFO "HiSax: AVM A1 PCMCIA driver Rev. %s\n", - HiSax_getrev(tmp)); - if (avm_a1p_probe(card->cs, card)) - return 0; - return 1; + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &AVM_card_msg; + cs->irq_flags = SA_SHIRQ; + cs->irq_func = &avm_a1p_interrupt; + + ISACVersion(cs, "AVM A1 PCMCIA:"); + if (HscxVersion(cs, "AVM A1 PCMCIA:")) { + printk(KERN_WARNING + "AVM A1 PCMCIA: wrong HSCX versions check IO address\n"); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c --- a/drivers/isdn/hisax/avm_pci.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hisax/avm_pci.c Thu Feb 19 23:44:24 2004 @@ -1,4 +1,4 @@ -/* $Id: avm_pci.c,v 1.22.6.6 2001/09/23 22:24:46 kai Exp $ +/* $Id: avm_pci.c,v 1.29.2.4 2004/02/11 13:21:32 keil Exp $ * * low level stuff for AVM Fritz!PCI and ISA PnP isdn cards * @@ -22,8 +22,7 @@ #include extern const char *CardType[]; -static const char *avm_pci_rev = "$Revision: 1.22.6.6 $"; -static spinlock_t avm_pci_lock = SPIN_LOCK_UNLOCKED; +static const char *avm_pci_rev = "$Revision: 1.29.2.4 $"; #define AVM_FRITZ_PCI 1 #define AVM_FRITZ_PNP 2 @@ -76,137 +75,91 @@ /* Interface functions */ -static u8 -ReadISAC(struct IsdnCardState *cs, u8 offset) +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - u8 idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW; - u8 val; - unsigned long flags; + register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW; + register u_char val; - spin_lock_irqsave(&avm_pci_lock, flags); outb(idx, cs->hw.avm.cfg_reg + 4); val = inb(cs->hw.avm.isac + (offset & 0xf)); - spin_unlock_irqrestore(&avm_pci_lock, flags); return (val); } static void -WriteISAC(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - u8 idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW; - unsigned long flags; + register u_char idx = (offset > 0x2f) ? AVM_ISAC_REG_HIGH : AVM_ISAC_REG_LOW; - spin_lock_irqsave(&avm_pci_lock, flags); outb(idx, cs->hw.avm.cfg_reg + 4); outb(value, cs->hw.avm.isac + (offset & 0xf)); - spin_unlock_irqrestore(&avm_pci_lock, flags); } static void -ReadISACfifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { outb(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4); insb(cs->hw.avm.isac, data, size); } static void -WriteISACfifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { outb(AVM_ISAC_FIFO, cs->hw.avm.cfg_reg + 4); outsb(cs->hw.avm.isac, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = ReadISAC, - .write_reg = WriteISAC, - .read_fifo = ReadISACfifo, - .write_fifo = WriteISACfifo, -}; - static inline u_int -ReadHDLCPCI(struct IsdnCardState *cs, int chan, u8 offset) +ReadHDLCPCI(struct IsdnCardState *cs, int chan, u_char offset) { - u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; - u_int val; - unsigned long flags; + register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; + register u_int val; - spin_lock_irqsave(&avm_pci_lock, flags); outl(idx, cs->hw.avm.cfg_reg + 4); val = inl(cs->hw.avm.isac + offset); - spin_unlock_irqrestore(&avm_pci_lock, flags); return (val); } static inline void -WriteHDLCPCI(struct IsdnCardState *cs, int chan, u8 offset, u_int value) +WriteHDLCPCI(struct IsdnCardState *cs, int chan, u_char offset, u_int value) { - u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; - unsigned long flags; + register u_int idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; - spin_lock_irqsave(&avm_pci_lock, flags); outl(idx, cs->hw.avm.cfg_reg + 4); outl(value, cs->hw.avm.isac + offset); - spin_unlock_irqrestore(&avm_pci_lock, flags); } -static inline u8 -ReadHDLCPnP(struct IsdnCardState *cs, int chan, u8 offset) +static inline u_char +ReadHDLCPnP(struct IsdnCardState *cs, int chan, u_char offset) { - u8 idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; - u8 val; - unsigned long flags; + register u_char idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; + register u_char val; - spin_lock_irqsave(&avm_pci_lock, flags); outb(idx, cs->hw.avm.cfg_reg + 4); val = inb(cs->hw.avm.isac + offset); - spin_unlock_irqrestore(&avm_pci_lock, flags); return (val); } static inline void -WriteHDLCPnP(struct IsdnCardState *cs, int chan, u8 offset, u8 value) +WriteHDLCPnP(struct IsdnCardState *cs, int chan, u_char offset, u_char value) { - u8 idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; - unsigned long flags; + register u_char idx = chan ? AVM_HDLC_2 : AVM_HDLC_1; - spin_lock_irqsave(&avm_pci_lock, flags); outb(idx, cs->hw.avm.cfg_reg + 4); outb(value, cs->hw.avm.isac + offset); - spin_unlock_irqrestore(&avm_pci_lock, flags); } -static void -hdlc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int len) +static u_char +ReadHDLC_s(struct IsdnCardState *cs, int chan, u_char offset) { - u8 idx = hscx ? AVM_HDLC_2 : AVM_HDLC_1; - int i; - - if (cs->subtyp == AVM_FRITZ_PCI) { - u32 *ptr = (u32 *) data; - - outl(idx, cs->hw.avm.cfg_reg + 4); - for (i = 0; i < len; i += 4) { -#ifdef __powerpc__ -#ifdef CONFIG_APUS - *ptr++ = in_le32((u32 *)(cs->hw.avm.isac +_IO_BASE)); -#else - *ptr++ = in_be32((u32 *)(cs->hw.avm.isac +_IO_BASE)); -#endif /* CONFIG_APUS */ -#else - *ptr++ = inl(cs->hw.avm.isac); -#endif /* __powerpc__ */ - } - } else { - outb(idx, cs->hw.avm.cfg_reg + 4); - for (i = 0; i < len; i++) { - *data++ = inb(cs->hw.avm.isac); - } - } + return(0xff & ReadHDLCPCI(cs, chan, offset)); } -static struct bc_hw_ops hdlc_hw_ops = { - .read_fifo = hdlc_read_fifo, -}; +static void +WriteHDLC_s(struct IsdnCardState *cs, int chan, u_char offset, u_char value) +{ + WriteHDLCPCI(cs, chan, offset, value); +} static inline struct BCState *Sel_BCS(struct IsdnCardState *cs, int channel) @@ -273,7 +226,7 @@ bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS; write_ctrl(bcs, 1); bcs->hw.hdlc.ctrl.sr.cmd = 0; - sched_b_event(bcs, B_XMTBUFREADY); + schedule_event(bcs, B_XMTBUFREADY); break; case (L1_MODE_HDLC): bcs->mode = mode; @@ -284,7 +237,7 @@ bcs->hw.hdlc.ctrl.sr.cmd = HDLC_CMD_XRS; write_ctrl(bcs, 1); bcs->hw.hdlc.ctrl.sr.cmd = 0; - sched_b_event(bcs, B_XMTBUFREADY); + schedule_event(bcs, B_XMTBUFREADY); break; } } @@ -292,31 +245,89 @@ static inline void hdlc_empty_fifo(struct BCState *bcs, int count) { - recv_empty_fifo_b(bcs, count); + register u_int *ptr; + u_char *p; + u_char idx = bcs->channel ? AVM_HDLC_2 : AVM_HDLC_1; + int cnt=0; + struct IsdnCardState *cs = bcs->cs; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hdlc_empty_fifo %d", count); + if (bcs->hw.hdlc.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "hdlc_empty_fifo: incoming packet too large"); + return; + } + p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx; + ptr = (u_int *)p; + bcs->hw.hdlc.rcvidx += count; + if (cs->subtyp == AVM_FRITZ_PCI) { + outl(idx, cs->hw.avm.cfg_reg + 4); + while (cnt < count) { +#ifdef __powerpc__ +#ifdef CONFIG_APUS + *ptr++ = in_le32((unsigned *)(cs->hw.avm.isac +_IO_BASE)); +#else + *ptr++ = in_be32((unsigned *)(cs->hw.avm.isac +_IO_BASE)); +#endif /* CONFIG_APUS */ +#else + *ptr++ = inl(cs->hw.avm.isac); +#endif /* __powerpc__ */ + cnt += 4; + } + } else { + outb(idx, cs->hw.avm.cfg_reg + 4); + while (cnt < count) { + *p++ = inb(cs->hw.avm.isac); + cnt++; + } + } + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + if (cs->subtyp == AVM_FRITZ_PNP) + p = (u_char *) ptr; + t += sprintf(t, "hdlc_empty_fifo %c cnt %d", + bcs->channel ? 'B' : 'A', count); + QuickHex(t, p, count); + debugl1(cs, bcs->blog); + } } -static void +static inline void hdlc_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - int count, more, cnt =0; + int count, cnt =0; int fifo_size = 32; - unsigned char *p; - unsigned int *ptr; + u_char *p; + u_int *ptr; - p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more); - if (!p) + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hdlc_fill_fifo"); + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) return; - if (more) - bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XME; - else - bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME; - + bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XME; + if (bcs->tx_skb->len > fifo_size) { + count = fifo_size; + } else { + count = bcs->tx_skb->len; + if (bcs->mode != L1_MODE_TRANS) + bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XME; + } + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hdlc_fill_fifo %d/%ld", count, bcs->tx_skb->len); + p = bcs->tx_skb->data; + ptr = (u_int *)p; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.hdlc.count += count; bcs->hw.hdlc.ctrl.sr.xml = ((count == fifo_size) ? 0 : count); write_ctrl(bcs, 3); /* sets the correct index too */ if (cs->subtyp == AVM_FRITZ_PCI) { - ptr = (unsigned int *) p; while (cntdebug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; -static void -reset_xmit(struct BCState *bcs) -{ - bcs->hw.hdlc.ctrl.sr.xml = 0; - bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS; - write_ctrl(bcs, 1); - bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS; - write_ctrl(bcs, 1); - hdlc_fill_fifo(bcs); + if (cs->subtyp == AVM_FRITZ_PNP) + p = (u_char *) ptr; + t += sprintf(t, "hdlc_fill_fifo %c cnt %d", + bcs->channel ? 'B' : 'A', count); + QuickHex(t, p, count); + debugl1(cs, bcs->blog); + } } static inline void -HDLC_irq(struct BCState *bcs, u_int stat) -{ +HDLC_irq(struct BCState *bcs, u_int stat) { int len; + struct sk_buff *skb; if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs, "ch%d stat %#x", bcs->channel, stat); - if (stat & HDLC_INT_RPR) { if (stat & HDLC_STAT_RDO) { if (bcs->cs->debug & L1_DEB_HSCX) @@ -367,7 +376,7 @@ write_ctrl(bcs, 1); bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_RRS; write_ctrl(bcs, 1); - bcs->rcvidx = 0; + bcs->hw.hdlc.rcvidx = 0; } else { if (!(len = (stat & HDLC_STAT_RML_MASK)>>8)) len = 32; @@ -375,21 +384,70 @@ if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) { if (((stat & HDLC_STAT_CRCVFRRAB)==HDLC_STAT_CRCVFR) || (bcs->mode == L1_MODE_TRANS)) { - recv_rme_b(bcs); + if (!(skb = dev_alloc_skb(bcs->hw.hdlc.rcvidx))) + printk(KERN_WARNING "HDLC: receive out of memory\n"); + else { + memcpy(skb_put(skb, bcs->hw.hdlc.rcvidx), + bcs->hw.hdlc.rcvbuf, bcs->hw.hdlc.rcvidx); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.hdlc.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); } else { if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs, "invalid frame"); else debugl1(bcs->cs, "ch%d invalid frame %#x", bcs->channel, stat); - bcs->rcvidx = 0; + bcs->hw.hdlc.rcvidx = 0; } } } } if (stat & HDLC_INT_XDU) { - xmit_xdu_b(bcs, reset_xmit); + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hdlc.count); + bcs->tx_cnt += bcs->hw.hdlc.count; + bcs->hw.hdlc.count = 0; + if (bcs->cs->debug & L1_DEB_WARN) + debugl1(bcs->cs, "ch%d XDU", bcs->channel); + } else if (bcs->cs->debug & L1_DEB_WARN) + debugl1(bcs->cs, "ch%d XDU without skb", bcs->channel); + bcs->hw.hdlc.ctrl.sr.xml = 0; + bcs->hw.hdlc.ctrl.sr.cmd |= HDLC_CMD_XRS; + write_ctrl(bcs, 1); + bcs->hw.hdlc.ctrl.sr.cmd &= ~HDLC_CMD_XRS; + write_ctrl(bcs, 1); + hdlc_fill_fifo(bcs); } else if (stat & HDLC_INT_XPR) { - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + hdlc_fill_fifo(bcs); + return; + } else { + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hdlc.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_irq(bcs->tx_skb); + bcs->hw.hdlc.count = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hdlc.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + hdlc_fill_fifo(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + schedule_event(bcs, B_XMTBUFREADY); + } } } @@ -399,7 +457,6 @@ u_int stat; struct BCState *bcs; - spin_lock(&cs->lock); if (cs->subtyp == AVM_FRITZ_PCI) { stat = ReadHDLCPCI(cs, 0, HDLC_STATUS); } else { @@ -428,37 +485,64 @@ } else HDLC_irq(bcs, stat); } - spin_unlock(&cs->lock); } void hdlc_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->hw.hdlc.count = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "hdlc_l2l1: this shouldn't happen\n"); + } else { + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->hw.hdlc.count = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - modehdlc(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + modehdlc(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - modehdlc(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + modehdlc(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -467,38 +551,69 @@ close_hdlcstate(struct BCState *bcs) { modehdlc(bcs, 0, 0); - bc_close(bcs); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.hdlc.rcvbuf) { + kfree(bcs->hw.hdlc.rcvbuf); + bcs->hw.hdlc.rcvbuf = NULL; + } + if (bcs->blog) { + kfree(bcs->blog); + bcs->blog = NULL; + } + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); + if (bcs->tx_skb) { + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } } int open_hdlcstate(struct IsdnCardState *cs, struct BCState *bcs) { - return bc_open(bcs); + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + if (!(bcs->hw.hdlc.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for hdlc.rcvbuf\n"); + return (1); + } + if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for bcs->blog\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + kfree(bcs->hw.hdlc.rcvbuf); + bcs->hw.hdlc.rcvbuf = NULL; + return (2); + } + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->event = 0; + bcs->hw.hdlc.rcvidx = 0; + bcs->tx_cnt = 0; + return (0); } int setstack_hdlc(struct PStack *st, struct BCState *bcs) { bcs->channel = st->l1.bc; - bcs->unit = bcs->channel; if (open_hdlcstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = hdlc_l2l1; + st->l2.l2l1 = hdlc_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); return (0); } -static struct bc_l1_ops hdlc_l1_ops = { - .fill_fifo = hdlc_fill_fifo, - .open = setstack_hdlc, - .close = close_hdlcstate, -}; - -static void __init -inithdlc(struct IsdnCardState *cs) +void __init +clear_pending_hdlc_ints(struct IsdnCardState *cs) { u_int val; @@ -525,7 +640,15 @@ val = ReadHDLCPnP(cs, 1, HDLC_STATUS + 3); debugl1(cs, "HDLC 2 VIN %x", val); } +} +void __init +inithdlc(struct IsdnCardState *cs) +{ + cs->bcs[0].BC_SetStack = setstack_hdlc; + cs->bcs[1].BC_SetStack = setstack_hdlc; + cs->bcs[0].BC_Close = close_hdlcstate; + cs->bcs[1].BC_Close = close_hdlcstate; modehdlc(cs->bcs, -1, 0); modehdlc(cs->bcs + 1, -1, 1); } @@ -534,13 +657,17 @@ avm_pcipnp_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; - u8 sval; + u_long flags; + u_char val; + u_char sval; + spin_lock_irqsave(&cs->lock, flags); sval = inb(cs->hw.avm.cfg_reg + 2); - if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) + if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK) { /* possible a shared IRQ reqest */ + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_NONE; + } if (!(sval & AVM_STATUS0_IRQ_ISAC)) { val = ReadISAC(cs, ISAC_ISTA); isac_interrupt(cs, val); @@ -550,192 +677,187 @@ } WriteISAC(cs, ISAC_MASK, 0xFF); WriteISAC(cs, ISAC_MASK, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } -static int -avm_pcipnp_reset(struct IsdnCardState *cs) +static void +reset_avmpcipnp(struct IsdnCardState *cs) { printk(KERN_INFO "AVM PCI/PnP: reset\n"); outb(AVM_STATUS0_RESET | AVM_STATUS0_DIS_TIMER, cs->hw.avm.cfg_reg + 2); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + mdelay(10); outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2); outb(AVM_STATUS1_ENA_IOM | cs->irq, cs->hw.avm.cfg_reg + 3); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + mdelay(10); printk(KERN_INFO "AVM PCI/PnP: S1 %x\n", inb(cs->hw.avm.cfg_reg + 3)); - return 0; -} - -static void -avm_pcipnp_init(struct IsdnCardState *cs) -{ - initisac(cs); - inithdlc(cs); - outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER, - cs->hw.avm.cfg_reg + 2); - outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | - AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2); -} - -static void -avm_pcipnp_release(struct IsdnCardState *cs) -{ - outb(0, cs->hw.avm.cfg_reg + 2); - hisax_release_resources(cs); } -static struct card_ops avm_pci_ops = { - .init = avm_pcipnp_init, - .reset = avm_pcipnp_reset, - .release = avm_pcipnp_release, - .irq_func = avm_pcipnp_interrupt, -}; - -static int __init -avm_pcipnp_hw_init(struct IsdnCardState *cs) -{ - cs->bc_hw_ops = &hdlc_hw_ops; - cs->bc_l1_ops = &hdlc_l1_ops; - cs->card_ops = &avm_pci_ops; - avm_pcipnp_reset(cs); - return isac_setup(cs, &isac_ops); -} - -static int __init -avm_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - int rc; - u32 val; - - printk(KERN_INFO "AVM PCI: defined at %#lx IRQ %u\n", - pci_resource_start(pdev, 1), pdev->irq); - - rc = -EBUSY; - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = AVM_FRITZ_PCI; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1); - cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; - if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PCI")) - goto err; - - val = inl(cs->hw.avm.cfg_reg); - printk(KERN_INFO "AVM PCI: stat %#x\n", val); - printk(KERN_INFO "AVM PCI: Class %X Rev %d\n", - val & 0xff, (val>>8) & 0xff); - - if (avm_pcipnp_hw_init(cs)) - goto err; - - return 0; - err: - hisax_release_resources(cs); - return rc; -} - -static int __init -avm_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card) +static int +AVM_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - int rc; - u8 val, ver; + u_long flags; - printk(KERN_INFO "AVM PnP: defined at %#lx IRQ %lu\n", - card->para[1], card->para[0]); - - cs->subtyp = AVM_FRITZ_PNP; - cs->irq = card->para[0]; - cs->hw.avm.cfg_reg = card->para[1]; - cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; - - rc = -EBUSY; - if (!request_io(&cs->rs, cs->hw.avm.cfg_reg, 32, "avm PnP")) - goto err; - - val = inb(cs->hw.avm.cfg_reg); - ver = inb(cs->hw.avm.cfg_reg + 1); - printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver); - - if (avm_pcipnp_hw_init(cs)) - goto err; - - return 0; - err: - hisax_release_resources(cs); - return rc; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_avmpcipnp(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + outb(0, cs->hw.avm.cfg_reg + 2); + release_region(cs->hw.avm.cfg_reg, 32); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + reset_avmpcipnp(cs); + clear_pending_isac_ints(cs); + initisac(cs); + inithdlc(cs); + outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER, + cs->hw.avm.cfg_reg + 2); + WriteISAC(cs, ISAC_MASK, 0); + outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER | + AVM_STATUS0_ENA_IRQ, cs->hw.avm.cfg_reg + 2); + /* RESET Receiver and Transmitter */ + WriteISAC(cs, ISAC_CMDR, 0x41); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); } static struct pci_dev *dev_avm __initdata = NULL; #ifdef __ISAPNP__ -static struct pnp_card *card_avm __initdata = NULL; -static struct pnp_dev *pnp_avm __initdata = NULL; +static struct pnp_card *pnp_avm_c __initdata = NULL; #endif int __init setup_avm_pcipnp(struct IsdnCard *card) { + u_int val, ver; + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, avm_pci_rev); printk(KERN_INFO "HiSax: AVM PCI driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_FRITZPCI) + return (0); if (card->para[1]) { /* old manual method */ - if (avm_pnp_probe(card->cs, card)) - return 0; - return 1; + cs->hw.avm.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + cs->subtyp = AVM_FRITZ_PNP; } else { #ifdef __ISAPNP__ if (isapnp_present()) { - struct pnp_card *ba; - if ((ba = pnp_find_card( + struct pnp_dev *pnp_avm_d = NULL; + if ((pnp_avm_c = pnp_find_card( ISAPNP_VENDOR('A', 'V', 'M'), - ISAPNP_FUNCTION(0x0900), card_avm))) { - card_avm = ba; - pnp_avm = NULL; - if ((pnp_avm = pnp_find_dev(card_avm, + ISAPNP_FUNCTION(0x0900), pnp_avm_c))) { + if ((pnp_avm_d = pnp_find_dev(pnp_avm_c, ISAPNP_VENDOR('A', 'V', 'M'), - ISAPNP_FUNCTION(0x0900), pnp_avm))) { - if (pnp_device_attach(pnp_avm) < 0) { - printk(KERN_ERR "FritzPnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pnp_avm) < 0) { - printk(KERN_ERR "FritzPnP: activate failed\n"); - pnp_device_detach(pnp_avm); - return 0; + ISAPNP_FUNCTION(0x0900), pnp_avm_d))) { + int err; + + pnp_disable_dev(pnp_avm_d); + err = pnp_activate_dev(pnp_avm_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); } - if (!pnp_irq_valid(pnp_avm, 0)) { + cs->hw.avm.cfg_reg = + pnp_port_start(pnp_avm_d, 0); + cs->irq = pnp_irq(pnp_avm_d, 0); + if (!cs->irq) { printk(KERN_ERR "FritzPnP:No IRQ\n"); - pnp_device_detach(pnp_avm); return(0); } - if (!pnp_port_valid(pnp_avm, 0)) { + if (!cs->hw.avm.cfg_reg) { printk(KERN_ERR "FritzPnP:No IO address\n"); - pnp_device_detach(pnp_avm); return(0); } - card->para[1] = pnp_port_start(pnp_avm, 0); - card->para[0] = pnp_irq(pnp_avm, 0); - if (avm_pnp_probe(card->cs, card)) - return 0; - return 1; + cs->subtyp = AVM_FRITZ_PNP; + goto ready; } } + } else { + printk(KERN_INFO "FritzPnP: no ISA PnP present\n"); } #endif -#ifdef CONFIG_PCI +#if CONFIG_PCI if ((dev_avm = pci_find_device(PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, dev_avm))) { - if (avm_pci_probe(card->cs, dev_avm)) - return 0; - return 1; + cs->irq = dev_avm->irq; + if (!cs->irq) { + printk(KERN_ERR "FritzPCI: No IRQ for PCI card found\n"); + return(0); + } + if (pci_enable_device(dev_avm)) + return(0); + cs->hw.avm.cfg_reg = pci_resource_start(dev_avm, 1); + if (!cs->hw.avm.cfg_reg) { + printk(KERN_ERR "FritzPCI: No IO-Adr for PCI card found\n"); + return(0); + } + cs->subtyp = AVM_FRITZ_PCI; + } else { + printk(KERN_WARNING "FritzPCI: No PCI card found\n"); + return(0); } + cs->irq_flags |= SA_SHIRQ; +#else + printk(KERN_WARNING "FritzPCI: NO_PCI_BIOS\n"); + return (0); #endif /* CONFIG_PCI */ } - printk(KERN_WARNING "FritzPCI: No card found\n"); - return 0; +ready: + cs->hw.avm.isac = cs->hw.avm.cfg_reg + 0x10; + if (!request_region(cs->hw.avm.cfg_reg, 32, + (cs->subtyp == AVM_FRITZ_PCI) ? "avm PCI" : "avm PnP")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.avm.cfg_reg, + cs->hw.avm.cfg_reg + 31); + return (0); + } + switch (cs->subtyp) { + case AVM_FRITZ_PCI: + val = inl(cs->hw.avm.cfg_reg); + printk(KERN_INFO "AVM PCI: stat %#x\n", val); + printk(KERN_INFO "AVM PCI: Class %X Rev %d\n", + val & 0xff, (val>>8) & 0xff); + cs->BC_Read_Reg = &ReadHDLC_s; + cs->BC_Write_Reg = &WriteHDLC_s; + break; + case AVM_FRITZ_PNP: + val = inb(cs->hw.avm.cfg_reg); + ver = inb(cs->hw.avm.cfg_reg + 1); + printk(KERN_INFO "AVM PnP: Class %X Rev %d\n", val, ver); + cs->BC_Read_Reg = &ReadHDLCPnP; + cs->BC_Write_Reg = &WriteHDLCPnP; + break; + default: + printk(KERN_WARNING "AVM unknown subtype %d\n", cs->subtyp); + return(0); + } + printk(KERN_INFO "HiSax: %s config irq:%d base:0x%X\n", + (cs->subtyp == AVM_FRITZ_PCI) ? "AVM Fritz!PCI" : "AVM Fritz!PnP", + cs->irq, cs->hw.avm.cfg_reg); + + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Send_Data = &hdlc_fill_fifo; + cs->cardmsg = &AVM_card_msg; + cs->irq_func = &avm_pcipnp_interrupt; + cs->writeisac(cs, ISAC_MASK, 0xFF); + ISACVersion(cs, (cs->subtyp == AVM_FRITZ_PCI) ? "AVM PCI:" : "AVM PnP:"); + return (1); } diff -Nru a/drivers/isdn/hisax/avma1_cs.c b/drivers/isdn/hisax/avma1_cs.c --- a/drivers/isdn/hisax/avma1_cs.c Thu Feb 19 23:44:26 2004 +++ b/drivers/isdn/hisax/avma1_cs.c Thu Feb 19 23:44:26 2004 @@ -26,15 +26,12 @@ #include #include #include +#include "hisax_cfg.h" MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for AVM A1/Fritz!PCMCIA cards"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); -int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot); -void HiSax_closecard(int cardnr); - - /* All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If you do not define PCMCIA_DEBUG at all, all the debug code will be @@ -156,6 +153,15 @@ return NULL; memset(link, 0, sizeof(struct dev_link_t)); + /* Allocate space for private device-specific data */ + local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + if (!local) { + kfree(link); + return NULL; + } + memset(local, 0, sizeof(local_info_t)); + link->priv = local; + /* The io structure describes IO port mapping */ link->io.NumPorts1 = 16; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; @@ -183,15 +189,6 @@ link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; - /* Allocate space for private device-specific data */ - local = kmalloc(sizeof(local_info_t), GFP_KERNEL); - if (!local) { - kfree(link); - return NULL; - } - memset(local, 0, sizeof(local_info_t)); - link->priv = local; - /* Register with Card Services */ link->next = dev_list; dev_list = link; @@ -252,7 +249,7 @@ /* Break the link with Card Services */ if (link->handle) - pcmcia_deregister_client(link->handle); + pcmcia_deregister_client(link->handle); /* Unlink device structure, free pieces */ *linkp = link->next; @@ -303,8 +300,9 @@ cistpl_cftable_entry_t *cf = &parse.cftable_entry; local_info_t *dev; int i; - u8 buf[64]; + u_char buf[64]; char devname[128]; + IsdnCard_t icard; int busy = 0; handle = link->handle; @@ -365,9 +363,9 @@ link->io.BasePort1 = cf->io.win[0].base; link->io.NumPorts1 = cf->io.win[0].len; link->io.NumPorts2 = 0; - printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n", + printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n", link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1 - 1); + link->io.BasePort1+link->io.NumPorts1 - 1); i = pcmcia_request_io(link->handle, &link->io); if (i == CS_SUCCESS) goto found_port; } @@ -391,8 +389,8 @@ } /* - * configure the PCMCIA socket - */ + * configure the PCMCIA socket + */ i = pcmcia_request_configuration(link->handle, &link->conf); if (i != CS_SUCCESS) { cs_error(link->handle, RequestConfiguration, i); @@ -421,15 +419,17 @@ printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n", link->io.BasePort1, link->irq.AssignedIRQ); - if (avm_a1_init_pcmcia((void *)(int)link->io.BasePort1, - link->irq.AssignedIRQ, - &busy, isdnprot) != 0) { - printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1); - return; + icard.para[0] = link->irq.AssignedIRQ; + icard.para[1] = link->io.BasePort1; + icard.protocol = isdnprot; + icard.typ = ISDN_CTYPE_A1_PCMCIA; + + i = hisax_init_pcmcia(link, &busy, &icard); + if (i < 0) { + printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1); + avma1cs_release(link); + return; } - - i = 0; /* no returncode for cardnr :-( */ - dev->node.minor = i; } /* avma1cs_config */ @@ -486,29 +486,28 @@ DEBUG(1, "avma1cs_event(0x%06x)\n", event); switch (event) { - case CS_EVENT_CARD_REMOVAL: - link->state &= ~DEV_PRESENT; - if (link->state & DEV_CONFIG) + case CS_EVENT_CARD_REMOVAL: + if (link->state & DEV_CONFIG) avma1cs_release(link); - break; - case CS_EVENT_CARD_INSERTION: - link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; - avma1cs_config(link); - break; - case CS_EVENT_PM_SUSPEND: - link->state |= DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_RESET_PHYSICAL: - if (link->state & DEV_CONFIG) - pcmcia_release_configuration(link->handle); - break; - case CS_EVENT_PM_RESUME: - link->state &= ~DEV_SUSPEND; - /* Fall through... */ - case CS_EVENT_CARD_RESET: - if (link->state & DEV_CONFIG) - pcmcia_request_configuration(link->handle, &link->conf); - break; + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + avma1cs_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + if (link->state & DEV_CONFIG) + pcmcia_release_configuration(link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (link->state & DEV_CONFIG) + pcmcia_request_configuration(link->handle, &link->conf); + break; } return 0; } /* avma1cs_event */ @@ -521,10 +520,12 @@ .attach = avma1cs_attach, .detach = avma1cs_detach, }; + +/*====================================================================*/ static int __init init_avma1_cs(void) { - return pcmcia_register_driver(&avma1cs_driver); + return(pcmcia_register_driver(&avma1cs_driver)); } static void __exit exit_avma1_cs(void) diff -Nru a/drivers/isdn/hisax/bkm_a4t.c b/drivers/isdn/hisax/bkm_a4t.c --- a/drivers/isdn/hisax/bkm_a4t.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hisax/bkm_a4t.c Thu Feb 19 23:44:24 2004 @@ -1,4 +1,4 @@ -/* $Id: bkm_a4t.c,v 1.13.6.6 2001/09/23 22:24:46 kai Exp $ +/* $Id: bkm_a4t.c,v 1.22.2.4 2004/01/14 16:04:48 keil Exp $ * * low level stuff for T-Berkom A4T * @@ -10,6 +10,7 @@ * */ + #include #include #include "hisax.h" @@ -21,51 +22,47 @@ #include "bkm_ax.h" extern const char *CardType[]; -// FIXME needs per card lock -static spinlock_t bkm_a4t_lock = SPIN_LOCK_UNLOCKED; -const char *bkm_a4t_revision = "$Revision: 1.13.6.6 $"; +const char *bkm_a4t_revision = "$Revision: 1.22.2.4 $"; + -static inline u8 -readreg(unsigned int ale, unsigned long adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned long adr, u_char off) { - u_int ret; - unsigned long flags; + register u_int ret; unsigned int *po = (unsigned int *) adr; /* Postoffice */ - spin_lock_irqsave(&bkm_a4t_lock, flags); + *po = (GCS_2 | PO_WRITE | off); __WAITI20__(po); *po = (ale | PO_READ); __WAITI20__(po); ret = *po; - spin_unlock_irqrestore(&bkm_a4t_lock, flags); return ((unsigned char) ret); } + static inline void -writereg(unsigned int ale, unsigned long adr, u8 off, u8 data) +readfifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size) +{ + int i; + for (i = 0; i < size; i++) + *data++ = readreg(ale, adr, off); +} + + +static inline void +writereg(unsigned int ale, unsigned long adr, u_char off, u_char data) { - unsigned long flags; unsigned int *po = (unsigned int *) adr; /* Postoffice */ - spin_lock_irqsave(&bkm_a4t_lock, flags); *po = (GCS_2 | PO_WRITE | off); __WAITI20__(po); *po = (ale | PO_WRITE | data); __WAITI20__(po); - spin_unlock_irqrestore(&bkm_a4t_lock, flags); } -static inline void -readfifo(unsigned int ale, unsigned long adr, u8 off, u8 * data, int size) -{ - int i; - - for (i = 0; i < size; i++) - *data++ = readreg(ale, adr, off); -} static inline void -writefifo(unsigned int ale, unsigned long adr, u8 off, u8 * data, int size) +writefifo(unsigned int ale, unsigned long adr, u_char off, u_char * data, int size) { int i; @@ -73,84 +70,74 @@ writereg(ale, adr, off, *data++); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) + +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { return (readreg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { writereg(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { readfifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { writefifo(cs->hw.ax.isac_ale, cs->hw.ax.isac_adr, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -jade_read(struct IsdnCardState *cs, int jade, u8 offset) +static u_char +ReadJADE(struct IsdnCardState *cs, int jade, u_char offset) { - return readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80))); + return (readreg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)))); } static void -jade_write(struct IsdnCardState *cs, int jade, u8 offset, u8 value) +WriteJADE(struct IsdnCardState *cs, int jade, u_char offset, u_char value) { writereg(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, offset + (jade == -1 ? 0 : (jade ? 0xC0 : 0x80)), value); } -static void -jade_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - readfifo(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, - (hscx == -1 ? 0 : (hscx ? 0xc0 : 0x80)), data, size); -} +/* + * fast interrupt JADE stuff goes here + */ -static void -jade_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - writefifo(cs->hw.ax.jade_ale, cs->hw.ax.jade_adr, - (hscx == -1 ? 0 : (hscx ? 0xc0 : 0x80)), data, size); -} +#define READJADE(cs, nr, reg) readreg(cs->hw.ax.jade_ale,\ + cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80))) +#define WRITEJADE(cs, nr, reg, data) writereg(cs->hw.ax.jade_ale,\ + cs->hw.ax.jade_adr, reg + (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), data) + +#define READJADEFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.jade_ale,\ + cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt) +#define WRITEJADEFIFO(cs, nr, ptr, cnt) writefifo( cs->hw.ax.jade_ale,\ + cs->hw.ax.jade_adr, (nr == -1 ? 0 : (nr ? 0xC0 : 0x80)), ptr, cnt) -static struct bc_hw_ops jade_ops = { - .read_reg = jade_read, - .write_reg = jade_write, - .read_fifo = jade_read_fifo, - .write_fifo = jade_write_fifo, -}; +#include "jade_irq.c" static irqreturn_t bkm_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val = 0; + u_char val = 0; + u_long flags; I20_REGISTER_FILE *pI20_Regs; - int handled = 0; - spin_lock(&cs->lock); + spin_lock_irqsave(&cs->lock, flags); pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); /* ISDN interrupt pending? */ if (pI20_Regs->i20IntStatus & intISDN) { - handled = 1; /* Reset the ISDN interrupt */ pI20_Regs->i20IntStatus = intISDN; /* Disable ISDN interrupt */ @@ -172,129 +159,101 @@ } /* Reenable ISDN interrupt */ pI20_Regs->i20IntCtrl |= intISDN; + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; + } else { + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_NONE; } - spin_unlock(&cs->lock); - return IRQ_RETVAL(handled); } -static void -enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable) +void +release_io_bkm(struct IsdnCardState *cs) { - I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); - if (bEnable) - pI20_Regs->i20IntCtrl |= (intISDN | intPCI); - else - /* CAUTION: This disables the video capture driver too */ - pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI); + if (cs->hw.ax.base) { + iounmap((void *) cs->hw.ax.base); + cs->hw.ax.base = 0; + } } static void -reset_bkm(struct IsdnCardState *cs) +enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable) { - I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); - /* Issue the I20 soft reset */ - pI20_Regs->i20SysControl = 0xFF; /* all in */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); - /* Remove the soft reset */ - pI20_Regs->i20SysControl = sysRESET | 0xFF; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); - /* Set our configuration */ - pI20_Regs->i20SysControl = sysRESET | sysCFG; - /* Issue ISDN reset */ - pI20_Regs->i20GuestControl = guestWAIT_CFG | - g_A4T_JADE_RES | - g_A4T_ISAR_RES | - g_A4T_ISAC_RES | - g_A4T_JADE_BOOTR | - g_A4T_ISAR_BOOTR; - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); - - /* Remove RESET state from ISDN */ - pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES | - g_A4T_JADE_RES | - g_A4T_ISAR_RES); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); + if (cs->typ == ISDN_CTYPE_BKM_A4T) { + I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); + if (bEnable) + pI20_Regs->i20IntCtrl |= (intISDN | intPCI); + else + /* CAUTION: This disables the video capture driver too */ + pI20_Regs->i20IntCtrl &= ~(intISDN | intPCI); + } } static void -bkm_a4t_init(struct IsdnCardState *cs) +reset_bkm(struct IsdnCardState *cs) { - initisac(cs); - initjade(cs); - /* Enable ints */ - enable_bkm_int(cs, 1); + if (cs->typ == ISDN_CTYPE_BKM_A4T) { + I20_REGISTER_FILE *pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); + /* Issue the I20 soft reset */ + pI20_Regs->i20SysControl = 0xFF; /* all in */ + mdelay(10); + /* Remove the soft reset */ + pI20_Regs->i20SysControl = sysRESET | 0xFF; + mdelay(10); + /* Set our configuration */ + pI20_Regs->i20SysControl = sysRESET | sysCFG; + /* Issue ISDN reset */ + pI20_Regs->i20GuestControl = guestWAIT_CFG | + g_A4T_JADE_RES | + g_A4T_ISAR_RES | + g_A4T_ISAC_RES | + g_A4T_JADE_BOOTR | + g_A4T_ISAR_BOOTR; + mdelay(10); + + /* Remove RESET state from ISDN */ + pI20_Regs->i20GuestControl &= ~(g_A4T_ISAC_RES | + g_A4T_JADE_RES | + g_A4T_ISAR_RES); + mdelay(10); + } } static int -bkm_a4t_reset(struct IsdnCardState *cs) +BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - /* Disable ints */ - enable_bkm_int(cs, 0); - reset_bkm(cs); - return 0; -} - -static void -bkm_a4t_release(struct IsdnCardState *cs) -{ - reset_bkm(cs); - hisax_release_resources(cs); -} - -static struct card_ops bkm_a4t_ops = { - .init = bkm_a4t_init, - .reset = bkm_a4t_reset, - .release = bkm_a4t_release, - .irq_func = bkm_interrupt, -}; + u_long flags; -static int __init -bkm_a4t_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - I20_REGISTER_FILE *pI20_Regs; - int rc; - - printk(KERN_INFO "BKM A4T: defined at %#lx IRQ %u\n", - pci_resource_start(pdev, 0), pdev->irq); - - rc = -EBUSY; - if (pci_enable_device(pdev)) - goto err; - - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.avm.cfg_reg = pci_resource_start(pdev, 1); - - cs->hw.ax.base = (unsigned long)request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "Telekom A4T"); - if (!cs->hw.ax.base) - goto err; - - /* Check suspicious address */ - // FIXME needs to use read[bl] - pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); - if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) { - printk(KERN_WARNING "HiSax: address %lx suspicious\n", - cs->hw.ax.base); - goto err; + switch (mt) { + case CARD_RESET: + /* Disable ints */ + spin_lock_irqsave(&cs->lock, flags); + enable_bkm_int(cs, 0); + reset_bkm(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_RELEASE: + /* Sanity */ + spin_lock_irqsave(&cs->lock, flags); + enable_bkm_int(cs, 0); + reset_bkm(cs); + spin_unlock_irqrestore(&cs->lock, flags); + release_io_bkm(cs); + return (0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + clear_pending_isac_ints(cs); + clear_pending_jade_ints(cs); + initisac(cs); + initjade(cs); + /* Enable ints */ + enable_bkm_int(cs, 1); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_TEST: + return (0); } - cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET; - cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET; - cs->hw.ax.isac_ale = GCS_1; - cs->hw.ax.jade_ale = GCS_3; - - reset_bkm(cs); - cs->card_ops = &bkm_a4t_ops; - isac_setup(cs, &isac_ops); - jade_setup(cs, &jade_ops); - return 0; - - err: - hisax_release_resources(cs); - return rc; + return (0); } static struct pci_dev *dev_a4t __initdata = NULL; @@ -302,10 +261,21 @@ int __init setup_bkm_a4t(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; char tmp[64]; + u_int pci_memaddr = 0, found = 0; + I20_REGISTER_FILE *pI20_Regs; +#if CONFIG_PCI +#endif strcpy(tmp, bkm_a4t_revision); printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ == ISDN_CTYPE_BKM_A4T) { + cs->subtyp = BKM_A4T; + } else + return (0); + +#if CONFIG_PCI while ((dev_a4t = pci_find_device(PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_a4t))) { u16 sub_sys; @@ -313,13 +283,62 @@ sub_vendor = dev_a4t->subsystem_vendor; sub_sys = dev_a4t->subsystem_device; - if (sub_sys == PCI_DEVICE_ID_BERKOM_A4T && - sub_vendor == PCI_VENDOR_ID_BERKOM) { - if (bkm_a4t_probe(card->cs, dev_a4t)) - return 0; - return 1; + if ((sub_sys == PCI_DEVICE_ID_BERKOM_A4T) && (sub_vendor == PCI_VENDOR_ID_BERKOM)) { + if (pci_enable_device(dev_a4t)) + return(0); + found = 1; + pci_memaddr = pci_resource_start(dev_a4t, 0); + cs->irq = dev_a4t->irq; + break; } } - printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]); - return 0; + if (!found) { + printk(KERN_WARNING "HiSax: %s: Card not found\n", CardType[card->typ]); + return (0); + } + if (!cs->irq) { /* IRQ range check ?? */ + printk(KERN_WARNING "HiSax: %s: No IRQ\n", CardType[card->typ]); + return (0); + } + if (!pci_memaddr) { + printk(KERN_WARNING "HiSax: %s: No Memory base address\n", CardType[card->typ]); + return (0); + } + cs->hw.ax.base = (long) ioremap(pci_memaddr, 4096); + /* Check suspecious address */ + pI20_Regs = (I20_REGISTER_FILE *) (cs->hw.ax.base); + if ((pI20_Regs->i20IntStatus & 0x8EFFFFFF) != 0) { + printk(KERN_WARNING "HiSax: %s address %lx-%lx suspecious\n", + CardType[card->typ], cs->hw.ax.base, cs->hw.ax.base + 4096); + iounmap((void *) cs->hw.ax.base); + cs->hw.ax.base = 0; + return (0); + } + cs->hw.ax.isac_adr = cs->hw.ax.base + PO_OFFSET; + cs->hw.ax.jade_adr = cs->hw.ax.base + PO_OFFSET; + cs->hw.ax.isac_ale = GCS_1; + cs->hw.ax.jade_ale = GCS_3; +#else + printk(KERN_WARNING "HiSax: %s: NO_PCI_BIOS\n", CardType[card->typ]); + printk(KERN_WARNING "HiSax: %s: unable to configure\n", CardType[card->typ]); + return (0); +#endif /* CONFIG_PCI */ + printk(KERN_INFO "HiSax: %s: Card configured at 0x%lX IRQ %d\n", + CardType[card->typ], cs->hw.ax.base, cs->irq); + + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadJADE; + cs->BC_Write_Reg = &WriteJADE; + cs->BC_Send_Data = &jade_fill_fifo; + cs->cardmsg = &BKM_card_msg; + cs->irq_func = &bkm_interrupt; + cs->irq_flags |= SA_SHIRQ; + ISACVersion(cs, "Telekom A4T:"); + /* Jade version */ + JadeVersion(cs, "Telekom A4T:"); + return (1); } diff -Nru a/drivers/isdn/hisax/bkm_a8.c b/drivers/isdn/hisax/bkm_a8.c --- a/drivers/isdn/hisax/bkm_a8.c Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/hisax/bkm_a8.c Thu Feb 19 23:44:27 2004 @@ -1,4 +1,4 @@ -/* $Id: bkm_a8.c,v 1.14.6.7 2001/09/23 22:24:46 kai Exp $ +/* $Id: bkm_a8.c,v 1.22.2.4 2004/01/15 14:02:34 keil Exp $ * * low level stuff for Scitel Quadro (4*S0, passive) * @@ -10,6 +10,7 @@ * */ + #include #include #include "hisax.h" @@ -20,11 +21,13 @@ #include #include "bkm_ax.h" +#if CONFIG_PCI + #define ATTEMPT_PCI_REMAPPING /* Required for PLX rev 1 */ extern const char *CardType[]; -static spinlock_t bkm_a8_lock = SPIN_LOCK_UNLOCKED; -const char sct_quadro_revision[] = "$Revision: 1.14.6.7 $"; + +const char sct_quadro_revision[] = "$Revision: 1.22.2.4 $"; static const char *sct_quadro_subtypes[] = { @@ -39,70 +42,174 @@ #define wordout(addr,val) outw(val,addr) #define wordin(addr) inw(addr) -static inline u8 -ipac_read(struct IsdnCardState *cs, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; - - spin_lock_irqsave(&bkm_a8_lock, flags); - wordout(cs->hw.ax.base, off); - ret = wordin(cs->hw.ax.data_adr) & 0xFF; - spin_unlock_irqrestore(&bkm_a8_lock, flags); - return ret; + register u_char ret; + wordout(ale, off); + ret = wordin(adr) & 0xFF; + return (ret); } static inline void -ipac_write(struct IsdnCardState *cs, u8 off, u8 data) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; + int i; + wordout(ale, off); + for (i = 0; i < size; i++) + data[i] = wordin(adr) & 0xFF; +} - spin_lock_irqsave(&bkm_a8_lock, flags); - wordout(cs->hw.ax.base, off); - wordout(cs->hw.ax.data_adr, data); - spin_unlock_irqrestore(&bkm_a8_lock, flags); + +static inline void +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) +{ + wordout(ale, off); + wordout(adr, data); } static inline void -ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 *data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { int i; - - wordout(cs->hw.ax.base, off); + wordout(ale, off); for (i = 0; i < size; i++) - data[i] = wordin(cs->hw.ax.data_adr) & 0xFF; + wordout(adr, data[i]); } -static inline void -ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 *data, int size) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - int i; + return (readreg(cs->hw.ax.base, cs->hw.ax.data_adr, offset | 0x80)); +} - wordout(cs->hw.ax.base, off); - for (i = 0; i < size; i++) - wordout(cs->hw.ax.data_adr, data[i]); +static void +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset | 0x80, value); +} + +static void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + readfifo(cs->hw.ax.base, cs->hw.ax.data_adr, 0x80, data, size); +} + +static void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + writefifo(cs->hw.ax.base, cs->hw.ax.data_adr, 0x80, data, size); } -/* This will generate ipac_dc_ops and ipac_bc_ops using the functions - * above */ -BUILD_IPAC_OPS(ipac); - +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) +{ + return (readreg(cs->hw.ax.base, cs->hw.ax.data_adr, offset + (hscx ? 0x40 : 0))); +} + +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) +{ + writereg(cs->hw.ax.base, cs->hw.ax.data_adr, offset + (hscx ? 0x40 : 0), value); +} + /* Set the specific ipac to active */ static void set_ipac_active(struct IsdnCardState *cs, u_int active) { /* set irq mask */ - ipac_write(cs, IPAC_MASK, active ? 0xc0 : 0xff); + writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, + active ? 0xc0 : 0xff); +} + +/* + * fast interrupt HSCX stuff goes here + */ + +#define READHSCX(cs, nr, reg) readreg(cs->hw.ax.base, \ + cs->hw.ax.data_adr, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.ax.base, \ + cs->hw.ax.data_adr, reg + (nr ? 0x40 : 0), data) +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ax.base, \ + cs->hw.ax.data_adr, (nr ? 0x40 : 0), ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.ax.base, \ + cs->hw.ax.data_adr, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" + +static irqreturn_t +bkm_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char ista, val, icnt = 5; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA); + if (!(ista & 0x3f)) { /* not this IPAC */ + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_NONE; + } + Start_IPAC: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) { + hscx_int_main(cs, val); + } + } + if (ista & 0x20) { + val = 0xfe & readreg(cs->hw.ax.base, cs->hw.ax.data_adr, ISAC_ISTA | 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPAC; + } + if (!icnt) + printk(KERN_WARNING "HiSax: %s (%s) IRQ LOOP\n", + CardType[cs->typ], + sct_quadro_subtypes[cs->subtyp]); + writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xFF); + writereg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_MASK, 0xC0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} + +void +release_io_sct_quadro(struct IsdnCardState *cs) +{ + release_region(cs->hw.ax.base & 0xffffffc0, 128); + if (cs->subtyp == SCT_1) + release_region(cs->hw.ax.plx_adr, 64); } static void enable_bkm_int(struct IsdnCardState *cs, unsigned bEnable) { - if (bEnable) - wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) | 0x41)); - else - wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) & ~0x41)); + if (cs->typ == ISDN_CTYPE_SCT_QUADRO) { + if (bEnable) + wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) | 0x41)); + else + wordout(cs->hw.ax.plx_adr + 0x4C, (wordin(cs->hw.ax.plx_adr + 0x4C) & ~0x41)); + } } static void @@ -110,66 +217,88 @@ { if (cs->subtyp == SCT_1) { wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) & ~4)); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); + mdelay(10); /* Remove the soft reset */ wordout(cs->hw.ax.plx_adr + 0x50, (wordin(cs->hw.ax.plx_adr + 0x50) | 4)); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10 * HZ) / 1000); + mdelay(10); } } -static void -bkm_a8_init(struct IsdnCardState *cs) -{ - cs->debug |= L1_DEB_IPAC; - set_ipac_active(cs, 1); - ipac_init(cs); - /* Enable ints */ - enable_bkm_int(cs, 1); -} - static int -bkm_a8_reset(struct IsdnCardState *cs) +BKM_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - /* Disable ints */ - set_ipac_active(cs, 0); - enable_bkm_int(cs, 0); - reset_bkm(cs); - return 0; + u_long flags; + + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + /* Disable ints */ + set_ipac_active(cs, 0); + enable_bkm_int(cs, 0); + reset_bkm(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_RELEASE: + /* Sanity */ + spin_lock_irqsave(&cs->lock, flags); + set_ipac_active(cs, 0); + enable_bkm_int(cs, 0); + spin_unlock_irqrestore(&cs->lock, flags); + release_io_sct_quadro(cs); + return (0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + cs->debug |= L1_DEB_IPAC; + set_ipac_active(cs, 1); + inithscxisac(cs, 3); + /* Enable ints */ + enable_bkm_int(cs, 1); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_TEST: + return (0); + } + return (0); } -static void -bkm_a8_release(struct IsdnCardState *cs) +int __init +sct_alloc_io(u_int adr, u_int len) { - set_ipac_active(cs, 0); - enable_bkm_int(cs, 0); - hisax_release_resources(cs); + if (!request_region(adr, len, "scitel")) { + printk(KERN_WARNING + "HiSax: Scitel port %#x-%#x already in use\n", + adr, adr + len); + return (1); + } + return(0); } -static struct card_ops bkm_a8_ops = { - .init = bkm_a8_init, - .reset = bkm_a8_reset, - .release = bkm_a8_release, - .irq_func = ipac_irq, -}; - static struct pci_dev *dev_a8 __initdata = NULL; static u16 sub_vendor_id __initdata = 0; static u16 sub_sys_id __initdata = 0; -static u8 pci_irq __initdata = 0; +static u_char pci_bus __initdata = 0; +static u_char pci_device_fn __initdata = 0; +static u_char pci_irq __initdata = 0; + +#endif /* CONFIG_PCI */ int __init setup_sct_quadro(struct IsdnCard *card) { +#if CONFIG_PCI struct IsdnCardState *cs = card->cs; char tmp[64]; - u8 pci_rev_id; + u_char pci_rev_id; u_int found = 0; u_int pci_ioaddr1, pci_ioaddr2, pci_ioaddr3, pci_ioaddr4, pci_ioaddr5; strcpy(tmp, sct_quadro_revision); printk(KERN_INFO "HiSax: T-Berkom driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ == ISDN_CTYPE_SCT_QUADRO) { + cs->subtyp = SCT_1; /* Preset */ + } else + return (0); + /* Identify subtype by para[0] */ if (card->para[0] >= SCT_1 && card->para[0] <= SCT_4) cs->subtyp = card->para[0]; @@ -193,6 +322,8 @@ return(0); pci_ioaddr1 = pci_resource_start(dev_a8, 1); pci_irq = dev_a8->irq; + pci_bus = dev_a8->bus->number; + pci_device_fn = dev_a8->devfn; found = 1; break; } @@ -253,31 +384,40 @@ cs->hw.ax.plx_adr = pci_ioaddr1; /* Enter all ipac_base addresses */ switch(cs->subtyp) { - case 1: - cs->hw.ax.base = pci_ioaddr5 + 0x00; - if (!request_io(&cs->rs, pci_ioaddr1, 128, "scitel")) - goto err; - if (!request_io(&cs->rs, pci_ioaddr5, 64, "scitel")) - goto err; - break; - case 2: - cs->hw.ax.base = pci_ioaddr4 + 0x08; - if (!request_io(&cs->rs, pci_ioaddr4, 64, "scitel")) - goto err; - break; - case 3: - cs->hw.ax.base = pci_ioaddr3 + 0x10; - if (!request_io(&cs->rs, pci_ioaddr3, 64, "scitel")) - goto err; - break; - case 4: - cs->hw.ax.base = pci_ioaddr2 + 0x20; - if (!request_io(&cs->rs, pci_ioaddr2, 64, "scitel")) - goto err; - break; + case 1: + cs->hw.ax.base = pci_ioaddr5 + 0x00; + if (sct_alloc_io(pci_ioaddr1, 128)) + return(0); + if (sct_alloc_io(pci_ioaddr5, 64)) + return(0); + /* disable all IPAC */ + writereg(pci_ioaddr5, pci_ioaddr5 + 4, + IPAC_MASK, 0xFF); + writereg(pci_ioaddr4 + 0x08, pci_ioaddr4 + 0x0c, + IPAC_MASK, 0xFF); + writereg(pci_ioaddr3 + 0x10, pci_ioaddr3 + 0x14, + IPAC_MASK, 0xFF); + writereg(pci_ioaddr2 + 0x20, pci_ioaddr2 + 0x24, + IPAC_MASK, 0xFF); + break; + case 2: + cs->hw.ax.base = pci_ioaddr4 + 0x08; + if (sct_alloc_io(pci_ioaddr4, 64)) + return(0); + break; + case 3: + cs->hw.ax.base = pci_ioaddr3 + 0x10; + if (sct_alloc_io(pci_ioaddr3, 64)) + return(0); + break; + case 4: + cs->hw.ax.base = pci_ioaddr2 + 0x20; + if (sct_alloc_io(pci_ioaddr2, 64)) + return(0); + break; } + /* For isac and hscx data path */ cs->hw.ax.data_adr = cs->hw.ax.base + 4; - ipac_write(cs, IPAC_MASK, 0xFF); printk(KERN_INFO "HiSax: %s (%s) configured at 0x%.4lX, 0x%.4lX, 0x%.4lX and IRQ %d\n", CardType[card->typ], @@ -287,12 +427,25 @@ cs->hw.ax.data_adr, cs->irq); - cs->card_ops = &bkm_a8_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - - return 1; - err: - hisax_release_resources(cs); - return 0; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &BKM_card_msg; + cs->irq_func = &bkm_interrupt_ipac; + + printk(KERN_INFO "HiSax: %s (%s): IPAC Version %d\n", + CardType[card->typ], + sct_quadro_subtypes[cs->subtyp], + readreg(cs->hw.ax.base, cs->hw.ax.data_adr, IPAC_ID)); + return (1); +#else + printk(KERN_ERR "HiSax: bkm_a8 only supported on PCI Systems\n"); +#endif /* CONFIG_PCI */ } diff -Nru a/drivers/isdn/hisax/callc.c b/drivers/isdn/hisax/callc.c --- a/drivers/isdn/hisax/callc.c Thu Feb 19 23:44:25 2004 +++ b/drivers/isdn/hisax/callc.c Thu Feb 19 23:44:25 2004 @@ -1,4 +1,4 @@ -/* $Id: callc.c,v 2.51.6.6 2001/09/23 22:24:46 kai Exp $ +/* $Id: callc.c,v 2.59.2.4 2004/02/11 13:21:32 keil Exp $ * * Author Karsten Keil * Copyright by Karsten Keil @@ -21,8 +21,7 @@ #include "hisax.h" #include - -const char *lli_revision = "$Revision: 2.51.6.6 $"; +const char *lli_revision = "$Revision: 2.59.2.4 $"; extern struct IsdnCard cards[]; extern int nrcards; @@ -32,7 +31,6 @@ static struct Fsm callcfsm; static int chancount; -static spinlock_t callc_lock = SPIN_LOCK_UNLOCKED; /* experimental REJECT after ALERTING for CALLBACK to beat the 4s delay */ #define ALERT_REJECT 0 @@ -205,49 +203,13 @@ } static inline void -mdl_info_setup(struct Channel *chanp) -{ - if (chanp->chan) - chanp->cs->status |= 0x0200; - else - chanp->cs->status |= 0x0100; - - if (chanp->cs->card_ops->led_handler) - chanp->cs->card_ops->led_handler(chanp->cs); -} - -static inline void -mdl_info_connect(struct Channel *chanp) -{ - if (chanp->chan) - chanp->cs->status |= 0x2000; - else - chanp->cs->status |= 0x1000; - - if (chanp->cs->card_ops->led_handler) - chanp->cs->card_ops->led_handler(chanp->cs); -} - -static inline void -mdl_info_release(struct Channel *chanp) -{ - if (chanp->chan) - chanp->cs->status &= ~0x2200; - else - chanp->cs->status &= ~0x1100; - - if (chanp->cs->card_ops->led_handler) - chanp->cs->card_ops->led_handler(chanp->cs); -} - -static void lli_close(struct FsmInst *fi) { struct Channel *chanp = fi->userdata; FsmChangeState(fi, ST_NULL); chanp->Flags = 0; - mdl_info_release(chanp); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); } static void @@ -259,8 +221,7 @@ if (!chanp->leased) return; - - mdl_info_setup(chanp); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); FsmChangeState(fi, ST_IN_WAIT_LL); if (chanp->debug & 1) link_debug(chanp, 0, "STAT_ICALL_LEASED"); @@ -277,11 +238,12 @@ if (chanp->debug & 1) link_debug(chanp, 1, "statcallb ret=%d", ret); if (!ret) { - mdl_info_release(chanp); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); FsmChangeState(fi, ST_NULL); } } + /* * Dial out */ @@ -295,7 +257,7 @@ link_debug(chanp, 0, "STAT_DCONN"); HL_LL(chanp, ISDN_STAT_DCONN); init_b_st(chanp, 0); - L4L3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL); + chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL); } static void @@ -307,12 +269,12 @@ FsmDelTimer(&chanp->dial_timer, 73); chanp->l2_active_protocol = chanp->l2_protocol; chanp->incoming = 0; - mdl_info_setup(chanp); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); if (chanp->leased) { lli_init_bchan_out(fi, event, arg); } else { FsmChangeState(fi, ST_OUT_DIAL); - L4L3(chanp->d_st, CC_SETUP | REQUEST, chanp); + chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | REQUEST, chanp); } } @@ -325,12 +287,12 @@ FsmDelTimer(&chanp->dial_timer, 73); chanp->l2_active_protocol = chanp->l2_protocol; chanp->incoming = 0; - mdl_info_setup(chanp); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); if (chanp->leased) { lli_init_bchan_out(fi, event, arg); } else { FsmChangeState(fi, ST_OUT_DIAL); - L4L3(chanp->d_st, CC_RESUME | REQUEST, chanp); + chanp->d_st->lli.l4l3(chanp->d_st, CC_RESUME | REQUEST, chanp); } } @@ -353,7 +315,7 @@ ic.command = ISDN_STAT_BCONN; ic.arg = chanp->chan; chanp->cs->iif.statcallb(&ic); - mdl_info_connect(chanp); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_CONN, (void *) (long)chanp->chan); } @@ -370,7 +332,7 @@ isdn_ctrl ic; int ret; - mdl_info_setup(chanp); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_SETUP, (void *) (long)chanp->chan); /* * Report incoming calls only once to linklevel, use CallFlags * which is set to 3 with each broadcast message in isdnl1.c @@ -397,34 +359,34 @@ case 1: /* OK, someone likes this call */ FsmDelTimer(&chanp->drel_timer, 61); FsmChangeState(fi, ST_IN_ALERT_SENT); - L4L3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); break; case 5: /* direct redirect */ case 4: /* Proceeding desired */ FsmDelTimer(&chanp->drel_timer, 61); FsmChangeState(fi, ST_IN_PROCEED_SEND); - L4L3(chanp->d_st, CC_PROCEED_SEND | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_PROCEED_SEND | REQUEST, chanp->proc); if (ret == 5) { memcpy(&chanp->setup, &ic.parm.setup, sizeof(setup_parm)); - L4L3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc); } break; case 2: /* Rejecting Call */ break; case 3: /* incomplete number */ FsmDelTimer(&chanp->drel_timer, 61); - L4L3(chanp->d_st, CC_MORE_INFO | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_MORE_INFO | REQUEST, chanp->proc); break; case 0: /* OK, nobody likes this call */ default: /* statcallb problems */ - L4L3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc); - mdl_info_release(chanp); + chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); FsmChangeState(fi, ST_NULL); break; } } else { - L4L3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc); - mdl_info_release(chanp); + chanp->d_st->lli.l4l3(chanp->d_st, CC_IGNORE | REQUEST, chanp->proc); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); } } @@ -434,7 +396,7 @@ struct Channel *chanp = fi->userdata; FsmChangeState(fi, ST_IN_WAIT_CONN_ACK); - L4L3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc); } static void @@ -443,7 +405,7 @@ struct Channel *chanp = fi->userdata; FsmChangeState(fi, ST_IN_ALERT_SENT); - L4L3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); } static void @@ -451,7 +413,7 @@ { struct Channel *chanp = fi->userdata; - L4L3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_REDIR | REQUEST, chanp->proc); } static void @@ -466,7 +428,7 @@ chanp->l2_active_protocol = chanp->l2_protocol; chanp->incoming = !0; init_b_st(chanp, !0); - L4L3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL); + chanp->b_st->lli.l4l3(chanp->b_st, DL_ESTABLISH | REQUEST, NULL); } static void @@ -479,9 +441,9 @@ } else { FsmChangeState(fi, ST_IN_WAIT_CONN_ACK); #ifdef WANT_ALERT - L4L3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); #endif - L4L3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_SETUP | RESPONSE, chanp->proc); } } @@ -492,7 +454,7 @@ { struct Channel *chanp = fi->userdata; - L4L3(chanp->d_st, CC_SUSPEND | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_SUSPEND | REQUEST, chanp->proc); } /* Call clearing */ @@ -524,7 +486,8 @@ FsmChangeState(fi, ST_WAIT_DRELEASE); if (chanp->proc) chanp->proc->para.cause = 0x10; /* Normal Call Clearing */ - L4L3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST, + chanp->proc); } } @@ -539,7 +502,8 @@ FsmChangeState(fi, ST_WAIT_DRELEASE); if (chanp->proc) chanp->proc->para.cause = 0x15; /* Call Rejected */ - L4L3(chanp->d_st, CC_DISCONNECT | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_DISCONNECT | REQUEST, + chanp->proc); } } @@ -571,12 +535,12 @@ #ifndef ALERT_REJECT if (chanp->proc) chanp->proc->para.cause = 0x15; /* Call Rejected */ - L4L3(chanp->d_st, CC_REJECT | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_REJECT | REQUEST, chanp->proc); lli_dhup_close(fi, event, arg); #else FsmRestartTimer(&chanp->drel_timer, 40, EV_HANGUP, NULL, 63); FsmChangeState(fi, ST_IN_ALERT_SENT); - L4L3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_ALERTING | REQUEST, chanp->proc); #endif } @@ -587,7 +551,7 @@ chanp->data_open = 0; FsmChangeState(fi, ST_WAIT_BRELEASE); - L4L3(chanp->b_st, DL_RELEASE | REQUEST, NULL); + chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); } static void @@ -642,7 +606,7 @@ chanp->data_open = 0; FsmChangeState(fi, ST_WAIT_BREL_DISC); - L4L3(chanp->b_st, DL_RELEASE | REQUEST, NULL); + chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); } @@ -672,7 +636,7 @@ struct Channel *chanp = fi->userdata; chanp->data_open = 0; - L4L3(chanp->b_st, DL_RELEASE | REQUEST, NULL); + chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); lli_bhup_dhup(fi, event, arg); } @@ -685,7 +649,8 @@ lli_leased_hup(fi, chanp); } else { FsmChangeState(fi, ST_WAIT_D_REL_CNF); - L4L3(chanp->d_st, CC_RELEASE | REQUEST, chanp->proc); + chanp->d_st->lli.l4l3(chanp->d_st, CC_RELEASE | REQUEST, + chanp->proc); } } @@ -767,7 +732,7 @@ chanp->cs->iif.statcallb(&ic); HL_LL(chanp, ISDN_STAT_DHUP); chanp->Flags = 0; - mdl_info_release(chanp); + chanp->cs->cardmsg(chanp->cs, MDL_INFO_REL, (void *) (long)chanp->chan); } static void @@ -796,7 +761,7 @@ struct Channel *chanp = fi->userdata; chanp->data_open = 0; - L4L3(chanp->b_st, DL_RELEASE | REQUEST, NULL); + chanp->b_st->lli.l4l3(chanp->b_st, DL_RELEASE | REQUEST, NULL); lli_bhup_fail(fi, event, arg); } @@ -890,11 +855,10 @@ static void release_b_st(struct Channel *chanp) { - struct IsdnCardState *cs = chanp->cs; struct PStack *st = chanp->b_st; if(test_and_clear_bit(FLG_START_B, &chanp->Flags)) { - cs->bc_l1_ops->close(chanp->bcs); + chanp->bcs->BC_Close(chanp->bcs); switch (chanp->l2_active_protocol) { case (ISDN_PROTO_L2_X75I): releasestack_isdnl2(st); @@ -954,7 +918,7 @@ ic.driver = cs->myid; ic.command = ISDN_STAT_REDIR; ic.arg = chan; - (ulong)(ic.parm.num[0]) = result; + ic.parm.num[0] = result; cs->iif.statcallb(&ic); } /* stat_redir_result */ @@ -971,7 +935,7 @@ if (pr == (CC_SETUP | INDICATION)) { if (!(chanp = selectfreechannel(pc->st, pc->para.bchannel))) { pc->para.cause = 0x11; /* User busy */ - L4L3(pc->st, CC_REJECT | REQUEST, pc); + pc->st->lli.l4l3(pc->st, CC_REJECT | REQUEST, pc); } else { chanp->proc = pc; pc->chan = chanp; @@ -1054,16 +1018,16 @@ if (!*stp) return -ENOMEM; (*stp)->next = NULL; + (*stp)->l1.l1l2 = dummy_pstack; (*stp)->l1.l1hw = dummy_pstack; (*stp)->l1.l1tei = dummy_pstack; - (*stp)->l1.l2l1 = dummy_pstack; - (*stp)->l2.l1l2 = dummy_pstack; (*stp)->l2.l2tei = dummy_pstack; - (*stp)->l2.l3l2 = dummy_pstack; - (*stp)->l3.l2l3 = dummy_pstack; + (*stp)->l2.l2l1 = dummy_pstack; + (*stp)->l2.l2l3 = dummy_pstack; + (*stp)->l3.l3l2 = dummy_pstack; (*stp)->l3.l3ml3 = dummy_pstack; - (*stp)->l3.l4l3 = dummy_pstack; - (*stp)->lli.l3l4 = dummy_pstack; + (*stp)->l3.l3l4 = dummy_pstack; + (*stp)->lli.l4l3 = dummy_pstack; (*stp)->ma.layer = dummy_pstack; return 0; } @@ -1101,7 +1065,7 @@ setstack_isdnl2(st, tmp); setstack_l3dc(st, chanp); st->lli.userdata = chanp; - st->lli.l3l4 = dchan_l3l4; + st->l3.l3l4 = dchan_l3l4; return 0; } @@ -1175,7 +1139,8 @@ printk(KERN_INFO "HiSax: MAX_WAITING_CALLS added\n"); if (test_bit(FLG_PTP, &csta->channel->d_st->l2.flag)) { printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n"); - L4L3(csta->channel->d_st, DL_ESTABLISH | REQUEST, NULL); + csta->channel->d_st->lli.l4l3(csta->channel->d_st, + DL_ESTABLISH | REQUEST, NULL); } return (0); } @@ -1209,7 +1174,7 @@ kfree(csta->channel[i].b_st); csta->channel[i].b_st = NULL; } else - printk(KERN_WARNING "CallcFreeChan b_st ch%d already freed\n", i); + printk(KERN_WARNING "CallcFreeChan b_st ch%d allready freed\n", i); if (i || test_bit(FLG_TWO_DCHAN, &csta->HW_Flags)) { release_d_st(csta->channel + i); } else @@ -1218,30 +1183,13 @@ } static void -ll_writewakeup(struct Channel *chanp, struct sk_buff *skb) -{ - isdn_ctrl ic; - - if (skb->pkt_type != PACKET_NOACK) { - if (chanp->debug & 0x800) - link_debug(chanp, 0, "llwakeup: %d", skb->truesize); - ic.driver = chanp->cs->myid; - ic.command = ISDN_STAT_BSENT; - ic.arg = chanp->chan; - ic.parm.length = skb->truesize; - chanp->cs->iif.statcallb(&ic); - } - dev_kfree_skb(skb); -} - -static void lldata_handler(struct PStack *st, int pr, void *arg) { struct Channel *chanp = (struct Channel *) st->lli.userdata; struct sk_buff *skb = arg; switch (pr) { - case (DL_DATA | INDICATION): + case (DL_DATA | INDICATION): if (chanp->data_open) { if (chanp->debug & 0x800) link_debug(chanp, 0, "lldata: %d", skb->len); @@ -1251,9 +1199,6 @@ dev_kfree_skb(skb); } break; - case (DL_DATA | CONFIRM): - ll_writewakeup(chanp, skb); - break; case (DL_ESTABLISH | INDICATION): case (DL_ESTABLISH | CONFIRM): FsmEvent(&chanp->fi, EV_BC_EST, NULL); @@ -1286,9 +1231,6 @@ dev_kfree_skb(skb); } break; - case (PH_DATA | CONFIRM): - ll_writewakeup(chanp, skb); - break; case (PH_ACTIVATE | INDICATION): case (PH_ACTIVATE | CONFIRM): FsmEvent(&chanp->fi, EV_BC_EST, NULL); @@ -1304,6 +1246,21 @@ } } +void +lli_writewakeup(struct PStack *st, int len) +{ + struct Channel *chanp = st->lli.userdata; + isdn_ctrl ic; + + if (chanp->debug & 0x800) + link_debug(chanp, 0, "llwakeup: %d", len); + ic.driver = chanp->cs->myid; + ic.command = ISDN_STAT_BSENT; + ic.arg = chanp->chan; + ic.parm.length = len; + chanp->cs->iif.statcallb(&ic); +} + static int init_b_st(struct Channel *chanp, int incoming) { @@ -1335,7 +1292,7 @@ break; } chanp->bcs->conmsg = NULL; - if (cs->bc_l1_ops->open(st, chanp->bcs)) + if (chanp->bcs->BC_SetStack(st, chanp->bcs)) return (-1); st->l2.flag = 0; test_and_set_bit(FLG_LAPB, &st->l2.flag); @@ -1352,8 +1309,10 @@ sprintf(tmp, "Ch%d X.75", chanp->chan); setstack_isdnl2(st, tmp); setstack_l3bc(st, chanp); - st->l3.l2l3 = lldata_handler; + st->l2.l2l3 = lldata_handler; st->lli.userdata = chanp; + test_and_clear_bit(FLG_LLI_L1WAKEUP, &st->lli.flag); + test_and_set_bit(FLG_LLI_L2WAKEUP, &st->lli.flag); st->l2.l2m.debug = chanp->debug & 16; st->l2.debug = chanp->debug & 64; break; @@ -1362,8 +1321,10 @@ case (ISDN_PROTO_L2_TRANS): case (ISDN_PROTO_L2_MODEM): case (ISDN_PROTO_L2_FAX): - st->l2.l1l2 = lltrans_handler; + st->l1.l1l2 = lltrans_handler; st->lli.userdata = chanp; + test_and_set_bit(FLG_LLI_L1WAKEUP, &st->lli.flag); + test_and_clear_bit(FLG_LLI_L2WAKEUP, &st->lli.flag); setstack_transl2(st); setstack_l3bc(st, chanp); break; @@ -1384,7 +1345,7 @@ dev_kfree_skb(skb); break; case (DL_ESTABLISH | REQUEST): - L2L1(st, PH_ACTIVATE | REQUEST, NULL); + st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL); break; case (DL_RELEASE | REQUEST): break; @@ -1462,7 +1423,7 @@ { char *t = tmpbuf; - t += QuickHex(t, (u8 *)cm, (cm->Length>50)? 50: cm->Length); + t += QuickHex(t, (u_char *)cm, (cm->Length>50)? 50: cm->Length); t--; *t= 0; HiSax_putstatus(chanp->cs, "Ch", "%d CAPIMSG %s", chanp->chan, tmpbuf); @@ -1478,11 +1439,11 @@ return; switch(cm->para[3]) { case 4: /* Suspend */ - strlcpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); + strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); FsmEvent(&chanp->fi, EV_SUSPEND, cm); break; case 5: /* Resume */ - strlcpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); + strncpy(chanp->setup.phone, &cm->para[5], cm->para[5] +1); if (chanp->fi.state == ST_NULL) { FsmEvent(&chanp->fi, EV_RESUME, cm); } else { @@ -1495,8 +1456,12 @@ void lli_got_manufacturer(struct Channel *chanp, struct IsdnCardState *cs, capi_msg *cm) { - if (cs->card_ops->aux_ind) - cs->card_ops->aux_ind(cs, cm->para); + if ((cs->typ == ISDN_CTYPE_ELSA) || (cs->typ == ISDN_CTYPE_ELSA_PNP) || + (cs->typ == ISDN_CTYPE_ELSA_PCI)) { + if (cs->hw.elsa.MFlag) { + cs->cardmsg(cs, CARD_AUX_IND, cm->para); + } + } } @@ -1654,15 +1619,16 @@ HiSax_putstatus(csta, "Card", "%d channel %d set leased mode\n", csta->cardnr + 1, num + 1); - chanp->d_st->l2.l1l2 = leased_l1l2; - chanp->d_st->l3.l4l3 = leased_l4l3; - L4L3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL); + chanp->d_st->l1.l1l2 = leased_l1l2; + chanp->d_st->lli.l4l3 = leased_l4l3; + chanp->d_st->lli.l4l3(chanp->d_st, + DL_ESTABLISH | REQUEST, NULL); } break; case (6): /* set B-channel test loop */ num = *(unsigned int *) ic->parm.num; if (csta->stlist) - csta->stlist->l1.l2l1(csta->stlist, + csta->stlist->l2.l2l1(csta->stlist, PH_TESTLOOP | REQUEST, (void *) (long)num); break; case (7): /* set card in PTP mode */ @@ -1676,7 +1642,8 @@ HiSax_putstatus(csta, "set card ", "in PTP mode"); printk(KERN_DEBUG "HiSax: set card in PTP mode\n"); printk(KERN_INFO "LAYER2 WATCHING ESTABLISH\n"); - L4L3(csta->channel[0].d_st, DL_ESTABLISH | REQUEST, NULL); + csta->channel[0].d_st->lli.l4l3(csta->channel[0].d_st, + DL_ESTABLISH | REQUEST, NULL); } else { test_and_clear_bit(FLG_PTP, &csta->channel[0].d_st->l2.flag); test_and_clear_bit(FLG_FIXED_TEI, &csta->channel[0].d_st->l2.flag); @@ -1700,7 +1667,8 @@ printk(KERN_DEBUG "HiSax: set card in FIXED TEI (%d) mode\n", num); } - L4L3(chanp->d_st, DL_ESTABLISH | REQUEST, NULL); + chanp->d_st->lli.l4l3(chanp->d_st, + DL_ESTABLISH | REQUEST, NULL); break; case (11): num = csta->debug & DEB_DLOG_HEX; @@ -1758,8 +1726,8 @@ /* protocol specific io commands */ case (ISDN_CMD_PROT_IO): for (st = csta->stlist; st; st = st->next) - if ((u_int)st->protocol == (ic->arg & 0xFF)) - return(st->l3.l4l3_proto(st, ic)); + if (st->protocol == (ic->arg & 0xFF)) + return(st->lli.l4l3_proto(st, ic)); return(-EINVAL); break; default: @@ -1777,7 +1745,6 @@ struct Channel *chanp; struct PStack *st; int len = skb->len; - unsigned long flags; struct sk_buff *nskb; if (!csta) { @@ -1807,22 +1774,20 @@ return 0; } else if (chanp->debug & 0x800) link_debug(chanp, 1, "writebuf %d/%d/%d", len, chanp->bcs->tx_cnt,MAX_DATA_MEM); - spin_lock_irqsave(&callc_lock, flags); nskb = skb_clone(skb, GFP_ATOMIC); if (nskb) { nskb->truesize = nskb->len; if (!ack) nskb->pkt_type = PACKET_NOACK; if (chanp->l2_active_protocol == ISDN_PROTO_L2_X75I) - L3L2(st, DL_DATA | REQUEST, nskb); + st->l3.l3l2(st, DL_DATA | REQUEST, nskb); else { chanp->bcs->tx_cnt += len; - st->l1.l2l1(st, PH_DATA | REQUEST, nskb); + st->l2.l2l1(st, PH_DATA | REQUEST, nskb); } dev_kfree_skb(skb); } else len = 0; - spin_unlock_irqrestore(&callc_lock, flags); } return (len); } diff -Nru a/drivers/isdn/hisax/cert.c b/drivers/isdn/hisax/cert.c --- a/drivers/isdn/hisax/cert.c Thu Feb 19 23:44:27 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,50 +0,0 @@ -/* $Id: cert.c,v 2.3.6.3 2001/09/23 22:24:47 kai Exp $ - * - * Author Karsten Keil - * Copyright by Karsten Keil - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * For changes and modifications please read - * ../../../Documentation/isdn/HiSax.cert - * - */ - -#include - -int -certification_check(int output) { - -#ifdef CERTIFICATION -#if CERTIFICATION == 0 - if (output) { - printk(KERN_INFO "HiSax: Approval certification valid\n"); - printk(KERN_INFO "HiSax: Approved with ELSA Microlink PCI cards\n"); - printk(KERN_INFO "HiSax: Approved with Eicon Technology Diva 2.01 PCI cards\n"); - printk(KERN_INFO "HiSax: Approved with Sedlbauer Speedfax + cards\n"); - printk(KERN_INFO "HiSax: Approved with HFC-S PCI A based cards\n"); - } - return(0); -#endif -#if CERTIFICATION == 1 - if (output) { - printk(KERN_INFO "HiSax: Approval certification failed because of\n"); - printk(KERN_INFO "HiSax: unauthorized source code changes\n"); - } - return(1); -#endif -#if CERTIFICATION == 127 - if (output) { - printk(KERN_INFO "HiSax: Approval certification not possible\n"); - printk(KERN_INFO "HiSax: because \"md5sum\" is not available\n"); - } - return(2); -#endif -#else - if (output) { - printk(KERN_INFO "HiSax: Certification not verified\n"); - } - return(3); -#endif -} diff -Nru a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c --- a/drivers/isdn/hisax/config.c Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/hisax/config.c Thu Feb 19 23:44:27 2004 @@ -1,4 +1,4 @@ -/* $Id: config.c,v 1.1.4.2.2.1 2001/12/09 20:18:40 kai Exp $ +/* $Id: config.c,v 2.84.2.5 2004/02/11 13:21:33 keil Exp $ * * Author Karsten Keil * Copyright by Karsten Keil @@ -24,7 +24,6 @@ #include #include #include -#include "isdnl1.h" #define HISAX_STATUS_BUFSIZE 4096 #define INCLUDE_INLINE_FUNCS @@ -99,14 +98,9 @@ "Hotplug", "Formula-n enter:now PCI a/b", }; -void HiSax_closecard(int cardnr); -static spinlock_t hisax_config_lock = SPIN_LOCK_UNLOCKED; - #ifdef CONFIG_HISAX_ELSA #define DEFAULT_CARD ISDN_CTYPE_ELSA #define DEFAULT_CFG {0,0,0,0} -int elsa_init_pcmcia(void *, int, int *, int); -EXPORT_SYMBOL(elsa_init_pcmcia); #endif #ifdef CONFIG_HISAX_AVM_A1 @@ -121,8 +115,6 @@ #undef DEFAULT_CFG #define DEFAULT_CARD ISDN_CTYPE_A1_PCMCIA #define DEFAULT_CFG {11,0x170,0,0} -int avm_a1_init_pcmcia(void *, int, int *, int); -EXPORT_SYMBOL(avm_a1_init_pcmcia); #endif #ifdef CONFIG_HISAX_FRITZPCI @@ -193,8 +185,6 @@ #undef DEFAULT_CFG #define DEFAULT_CARD ISDN_CTYPE_SEDLBAUER #define DEFAULT_CFG {11,0x270,0,0} -int sedl_init_pcmcia(void *, int, int *, int); -EXPORT_SYMBOL(sedl_init_pcmcia); #endif #ifdef CONFIG_HISAX_SPORTSTER @@ -237,8 +227,6 @@ #undef DEFAULT_CFG #define DEFAULT_CARD ISDN_CTYPE_HFC_SX #define DEFAULT_CFG {5,0x2E0,0,0} -int hfc_init_pcmcia(void *, int, int *, int); -EXPORT_SYMBOL(hfc_init_pcmcia); #endif @@ -330,10 +318,6 @@ #define DEFAULT_CFG {0,0,0,0} #endif -int hisax_init_pcmcia(void *, int *, struct IsdnCard *); -EXPORT_SYMBOL(hisax_init_pcmcia); -EXPORT_SYMBOL(HiSax_closecard); - #define FIRST_CARD { \ DEFAULT_CARD, \ DEFAULT_PROTO, \ @@ -346,14 +330,14 @@ }; #define HISAX_IDSIZE (HISAX_MAX_CARDS*8) -static char HiSaxID[HISAX_IDSIZE] __devinitdata = { 0, }; +static char HiSaxID[HISAX_IDSIZE] = { 0, }; -char *HiSax_id __devinitdata = HiSaxID; +char *HiSax_id = HiSaxID; #ifdef MODULE /* Variables for insmod */ -static int type[HISAX_MAX_CARDS] __devinitdata = { 0, }; -static int protocol[HISAX_MAX_CARDS] __devinitdata = { 0, }; -static int io[HISAX_MAX_CARDS] __devinitdata = { 0, }; +static int type[HISAX_MAX_CARDS] = { 0, }; +static int protocol[HISAX_MAX_CARDS] = { 0, }; +static int io[HISAX_MAX_CARDS] = { 0, }; #undef IO0_IO1 #ifdef CONFIG_HISAX_16_3 #define IO0_IO1 @@ -368,7 +352,7 @@ #endif static int irq[HISAX_MAX_CARDS] __devinitdata = { 0, }; static int mem[HISAX_MAX_CARDS] __devinitdata = { 0, }; -static char *id __devinitdata = HiSaxID; +static char *id = HiSaxID; #define PARM_PARA "1-" __MODULE_STRING(HISAX_MAX_CARDS) "i" @@ -430,7 +414,6 @@ strcpy(tmp, lli_revision); printk(KERN_INFO "HiSax: LinkLayer Revision %s\n", HiSax_getrev(tmp)); - certification_check(1); } #ifndef MODULE @@ -490,36 +473,125 @@ __setup("hisax=", HiSax_setup); #endif /* MODULES */ +#if CARD_TELES0 extern int setup_teles0(struct IsdnCard *card); +#endif + +#if CARD_TELES3 extern int setup_teles3(struct IsdnCard *card); +#endif + +#if CARD_S0BOX extern int setup_s0box(struct IsdnCard *card); +#endif + +#if CARD_TELESPCI extern int setup_telespci(struct IsdnCard *card); +#endif + +#if CARD_AVM_A1 extern int setup_avm_a1(struct IsdnCard *card); +#endif + +#if CARD_AVM_A1_PCMCIA extern int setup_avm_a1_pcmcia(struct IsdnCard *card); +#endif + +#if CARD_FRITZPCI extern int setup_avm_pcipnp(struct IsdnCard *card); +#endif + +#if CARD_ELSA extern int setup_elsa(struct IsdnCard *card); +#endif + +#if CARD_IX1MICROR2 extern int setup_ix1micro(struct IsdnCard *card); +#endif + +#if CARD_DIEHLDIVA extern int setup_diva(struct IsdnCard *card); +#endif + +#if CARD_ASUSCOM extern int setup_asuscom(struct IsdnCard *card); +#endif + +#if CARD_TELEINT extern int setup_TeleInt(struct IsdnCard *card); +#endif + +#if CARD_SEDLBAUER extern int setup_sedlbauer(struct IsdnCard *card); +#endif + +#if CARD_SPORTSTER extern int setup_sportster(struct IsdnCard *card); +#endif + +#if CARD_MIC extern int setup_mic(struct IsdnCard *card); +#endif + +#if CARD_NETJET_S extern int setup_netjet_s(struct IsdnCard *card); +#endif + +#if CARD_HFCS extern int setup_hfcs(struct IsdnCard *card); +#endif + +#if CARD_HFC_PCI extern int setup_hfcpci(struct IsdnCard *card); +#endif + +#if CARD_HFC_SX extern int setup_hfcsx(struct IsdnCard *card); +#endif + +#if CARD_AMD7930 extern int setup_amd7930(struct IsdnCard *card); +#endif + +#if CARD_NICCY extern int setup_niccy(struct IsdnCard *card); +#endif + +#if CARD_ISURF extern int setup_isurf(struct IsdnCard *card); +#endif + +#if CARD_HSTSAPHIR extern int setup_saphir(struct IsdnCard *card); +#endif + +#if CARD_TESTEMU extern int setup_testemu(struct IsdnCard *card); +#endif + +#if CARD_BKM_A4T extern int setup_bkm_a4t(struct IsdnCard *card); +#endif + +#if CARD_SCT_QUADRO extern int setup_sct_quadro(struct IsdnCard *card); +#endif + +#if CARD_GAZEL extern int setup_gazel(struct IsdnCard *card); +#endif + +#if CARD_W6692 extern int setup_w6692(struct IsdnCard *card); +#endif + +#if CARD_NETJET_U extern int setup_netjet_u(struct IsdnCard *card); +#endif + +#if CARD_FN_ENTERNOW_PCI extern int setup_enternow_pci(struct IsdnCard *card); +#endif /* * Find card with given driverId @@ -546,10 +618,10 @@ return NULL; } -int HiSax_readstatus(u8 * buf, int len, int user, int id, int channel) +int HiSax_readstatus(u_char * buf, int len, int user, int id, int channel) { int count, cnt; - u8 *p = buf; + u_char *p = buf; struct IsdnCardState *cs = hisax_findcard(id); if (cs) { @@ -561,10 +633,9 @@ count = cs->status_end - cs->status_read + 1; if (count >= len) count = len; - if (user) { - if (copy_to_user(p, cs->status_read, count)) - return -EFAULT; - } else + if (user) + copy_to_user(p, cs->status_read, count); + else memcpy(p, cs->status_read, count); cs->status_read += count; if (cs->status_read > cs->status_end) @@ -576,10 +647,9 @@ cnt = HISAX_STATUS_BUFSIZE; else cnt = count; - if (user) { - if (copy_to_user(p, cs->status_read, cnt)) - return -EFAULT; - } else + if (user) + copy_to_user(p, cs->status_read, cnt); + else memcpy(p, cs->status_read, cnt); p += cnt; cs->status_read += cnt % HISAX_STATUS_BUFSIZE; @@ -614,20 +684,24 @@ return 8; } -static char tmpbuf[HISAX_STATUS_BUFSIZE]; +static u_char tmpbuf[HISAX_STATUS_BUFSIZE]; -void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, +void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args) { /* if head == NULL the fmt contains the full info */ - unsigned long flags; - int count, i; - char *p; - isdn_ctrl ic; - int len; + u_long flags; + int count, i; + u_char *p; + isdn_ctrl ic; + int len; - spin_lock_irqsave(&hisax_config_lock, flags); + if (!cs) { + printk(KERN_WARNING "HiSax: No CardStatus for message"); + return; + } + spin_lock_irqsave(&cs->statlock, flags); p = tmpbuf; if (head) { p += jiftime(p, jiffies); @@ -638,19 +712,13 @@ len = p - tmpbuf; p = tmpbuf; } else { - p = (char *) fmt; + p = fmt; len = strlen(fmt); } - if (!cs) { - printk(KERN_WARNING "HiSax: No CardStatus for message %s", - p); - spin_unlock_irqrestore(&hisax_config_lock, flags); - return; - } if (len > HISAX_STATUS_BUFSIZE) { + spin_unlock_irqrestore(&cs->statlock, flags); printk(KERN_WARNING "HiSax: status overflow %d/%d\n", len, HISAX_STATUS_BUFSIZE); - spin_unlock_irqrestore(&hisax_config_lock, flags); return; } count = len; @@ -679,7 +747,7 @@ count++; } #endif - spin_unlock_irqrestore(&hisax_config_lock, flags); + spin_unlock_irqrestore(&cs->statlock, flags); if (count) { ic.command = ISDN_STAT_STAVAIL; ic.driver = cs->myid; @@ -725,15 +793,22 @@ ic.command = ISDN_STAT_UNLOAD; ic.driver = cs->myid; cs->iif.statcallb(&ic); + if (cs->status_buf) + kfree(cs->status_buf); + cs->status_read = NULL; + cs->status_write = NULL; + cs->status_end = NULL; + kfree(cs->dlog); + cs->dlog = NULL; } static void closecard(int cardnr) { struct IsdnCardState *csta = cards[cardnr].cs; - if (csta->bc_l1_ops->close) { - csta->bc_l1_ops->close(csta->bcs + 1); - csta->bc_l1_ops->close(csta->bcs); + if (csta->bcs->BC_Close != NULL) { + csta->bcs->BC_Close(csta->bcs + 1); + csta->bcs->BC_Close(csta->bcs); } skb_queue_purge(&csta->rq); @@ -746,32 +821,34 @@ dev_kfree_skb(csta->tx_skb); csta->tx_skb = NULL; } - if (csta->dc_l1_ops->close) - csta->dc_l1_ops->close(csta); - - if (csta->card_ops->release) - csta->card_ops->release(csta); + if (csta->DC_Close != NULL) { + csta->DC_Close(csta); + } + if (csta->cardmsg) + csta->cardmsg(csta, CARD_RELEASE, NULL); if (csta->dbusytimer.function != NULL) // FIXME? del_timer(&csta->dbusytimer); ll_unload(csta); } -static int __devinit init_card(struct IsdnCardState *cs) +static int init_card(struct IsdnCardState *cs) { - int irq_cnt, cnt = 3; - - cs->card_ops->init(cs); + int irq_cnt, cnt = 3, ret; + if (!cs->irq) { + ret = cs->cardmsg(cs, CARD_INIT, NULL); + return(ret); + } irq_cnt = kstat_irqs(cs->irq); printk(KERN_INFO "%s: IRQ %d count %d\n", CardType[cs->typ], cs->irq, irq_cnt); - if (request_irq(cs->irq, cs->card_ops->irq_func, cs->irq_flags, "HiSax", cs)) { + if (request_irq(cs->irq, cs->irq_func, cs->irq_flags, "HiSax", cs)) { printk(KERN_WARNING "HiSax: couldn't get interrupt %d\n", cs->irq); return 1; } while (cnt) { - cs->card_ops->init(cs); + cs->cardmsg(cs, CARD_INIT, NULL); set_current_state(TASK_UNINTERRUPTIBLE); /* Timeout 10ms */ schedule_timeout((10 * HZ) / 1000); @@ -785,86 +862,74 @@ free_irq(cs->irq, cs); return 2; } else { - if (cs->card_ops->reset) - cs->card_ops->reset(cs); + cs->cardmsg(cs, CARD_RESET, NULL); cnt--; } } else { - if (cs->card_ops->test) - cs->card_ops->test(cs); + cs->cardmsg(cs, CARD_TEST, NULL); return 0; } } return 3; } -static struct IsdnCardState * -alloc_IsdnCardState(void) +static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockowner) { + int ret = 0; + struct IsdnCard *card = cards + cardnr; struct IsdnCardState *cs; - cs = kmalloc(sizeof(*cs), GFP_ATOMIC); // FIXME - if (!cs) - goto err; - - memset(cs, 0, sizeof(*cs)); - - cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC); - if (!cs->dlog) - goto err_cs; - - cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC); - if (!cs->status_buf) - goto err_dlog; - - cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC); - if (!cs->rcvbuf) - goto err_status_buf; - + cs = kmalloc(sizeof(struct IsdnCardState), GFP_ATOMIC); + if (!cs) { + printk(KERN_WARNING + "HiSax: No memory for IsdnCardState(card %d)\n", + cardnr + 1); + goto out; + } + memset(cs, 0, sizeof(struct IsdnCardState)); + card->cs = cs; + spin_lock_init(&cs->statlock); + spin_lock_init(&cs->lock); cs->chanlimit = 2; /* maximum B-channel number */ + cs->logecho = 0; /* No echo logging */ + cs->cardnr = cardnr; cs->debug = L1_DEB_WARN; + cs->HW_Flags = 0; + cs->busy_flag = busy_flag; cs->irq_flags = I4L_IRQ_FLAG; +#if TEI_PER_CARD + if (card->protocol == ISDN_PTYPE_NI1) + test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); +#else + test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); +#endif + cs->protocol = card->protocol; + + if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) { + printk(KERN_WARNING + "HiSax: Card Type %d out of range\n", card->typ); + goto outf_cs; + } + if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for dlog(card %d)\n", cardnr + 1); + goto outf_cs; + } + if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for status_buf(card %d)\n", + cardnr + 1); + goto outf_dlog; + } cs->stlist = NULL; cs->status_read = cs->status_buf; cs->status_write = cs->status_buf; cs->status_end = cs->status_buf + HISAX_STATUS_BUFSIZE - 1; - cs->rcvidx = 0; - cs->tx_skb = NULL; - cs->tx_cnt = 0; - cs->event = 0; - - skb_queue_head_init(&cs->rq); - skb_queue_head_init(&cs->sq); - - spin_lock_init(&cs->lock); - resources_init(&cs->rs); - return cs; - - err_status_buf: - kfree(cs->status_buf); - err_dlog: - kfree(cs->dlog); - err_cs: - kfree(cs); - err: - return NULL; -} - -static void -free_IsdnCardState(struct IsdnCardState *cs) -{ - kfree(cs->rcvbuf); - kfree(cs->status_buf); - kfree(cs->dlog); - kfree(cs); -} - -static void -do_register_isdn(struct IsdnCardState *cs) -{ - if (!cs->iif.owner) - cs->iif.owner = THIS_MODULE; - + cs->typ = card->typ; +#ifdef MODULE + cs->iif.owner = lockowner; +#endif + strcpy(cs->iif.id, id); cs->iif.channels = 2; cs->iif.maxbufsize = MAX_DATA_SIZE; cs->iif.hl_hdrlen = MAX_HEADER_LEN; @@ -892,72 +957,20 @@ register_isdn(&cs->iif); cs->myid = cs->iif.channels; printk(KERN_INFO - "HiSax: Card %d Protocol %s Id=%s (%d)\n", cs->cardnr + 1, - (cs->protocol == ISDN_PTYPE_1TR6) ? "1TR6" : - (cs->protocol == ISDN_PTYPE_EURO) ? "EDSS1" : - (cs->protocol == ISDN_PTYPE_LEASED) ? "LEASED" : - (cs->protocol == ISDN_PTYPE_NI1) ? "NI1" : + "HiSax: Card %d Protocol %s Id=%s (%d)\n", cardnr + 1, + (card->protocol == ISDN_PTYPE_1TR6) ? "1TR6" : + (card->protocol == ISDN_PTYPE_EURO) ? "EDSS1" : + (card->protocol == ISDN_PTYPE_LEASED) ? "LEASED" : + (card->protocol == ISDN_PTYPE_NI1) ? "NI1" : "NONE", cs->iif.id, cs->myid); -} - -static int -do_init(struct IsdnCardState *cs) -{ - int ret; - - init_tei(cs, cs->protocol); - ret = CallcNewChan(cs); - if (ret) - return -EIO; - - /* ISAR needs firmware download first */ - if (!test_bit(HW_ISAR, &cs->HW_Flags)) - ll_run(cs, 0); - - return 0; -} - - -static int __devinit checkcard(int cardnr, char *id, int *busy_flag) -{ - int ret = 0; - struct IsdnCard *card = cards + cardnr; - struct IsdnCardState *cs; - - cs = alloc_IsdnCardState(); - if (!cs) { - printk(KERN_WARNING - "HiSax: No memory for IsdnCardState(card %d)\n", - cardnr + 1); - goto out; - } - card->cs = cs; -#if TEI_PER_CARD - if (card->protocol == ISDN_PTYPE_NI1) - test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); -#else - test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); -#endif - cs->cardnr = cardnr; - cs->protocol = card->protocol; - cs->typ = card->typ; - cs->busy_flag = busy_flag; - - if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) { - printk(KERN_WARNING - "HiSax: Card Type %d out of range\n", card->typ); - goto outf_cs; - } - strcpy(cs->iif.id, id); - do_register_isdn(cs); switch (card->typ) { -#ifdef CONFIG_HISAX_16_0 +#if CARD_TELES0 case ISDN_CTYPE_16_0: case ISDN_CTYPE_8_0: ret = setup_teles0(card); break; #endif -#ifdef CONFIG_HISAX_16_3 +#if CARD_TELES3 case ISDN_CTYPE_16_3: case ISDN_CTYPE_PNP: case ISDN_CTYPE_TELESPCMCIA: @@ -965,32 +978,32 @@ ret = setup_teles3(card); break; #endif -#ifdef CONFIG_HISAX_S0BOX +#if CARD_S0BOX case ISDN_CTYPE_S0BOX: ret = setup_s0box(card); break; #endif -#ifdef CONFIG_HISAX_TELESPCI +#if CARD_TELESPCI case ISDN_CTYPE_TELESPCI: ret = setup_telespci(card); break; #endif -#ifdef CONFIG_HISAX_AVM_A1 +#if CARD_AVM_A1 case ISDN_CTYPE_A1: ret = setup_avm_a1(card); break; #endif -#ifdef CONFIG_HISAX_AVM_A1_PCMCIA +#if CARD_AVM_A1_PCMCIA case ISDN_CTYPE_A1_PCMCIA: ret = setup_avm_a1_pcmcia(card); break; #endif -#ifdef CONFIG_HISAX_FRITZPCI +#if CARD_FRITZPCI case ISDN_CTYPE_FRITZPCI: ret = setup_avm_pcipnp(card); break; #endif -#ifdef CONFIG_HISAX_ELSA +#if CARD_ELSA case ISDN_CTYPE_ELSA: case ISDN_CTYPE_ELSA_PNP: case ISDN_CTYPE_ELSA_PCMCIA: @@ -998,115 +1011,115 @@ ret = setup_elsa(card); break; #endif -#ifdef CONFIG_HISAX_IX1MICROR2 +#if CARD_IX1MICROR2 case ISDN_CTYPE_IX1MICROR2: ret = setup_ix1micro(card); break; #endif -#ifdef CONFIG_HISAX_DIEHLDIVA +#if CARD_DIEHLDIVA case ISDN_CTYPE_DIEHLDIVA: ret = setup_diva(card); break; #endif -#ifdef CONFIG_HISAX_ASUSCOM +#if CARD_ASUSCOM case ISDN_CTYPE_ASUSCOM: ret = setup_asuscom(card); break; #endif -#ifdef CONFIG_HISAX_TELEINT +#if CARD_TELEINT case ISDN_CTYPE_TELEINT: ret = setup_TeleInt(card); break; #endif -#ifdef CONFIG_HISAX_SEDLBAUER +#if CARD_SEDLBAUER case ISDN_CTYPE_SEDLBAUER: case ISDN_CTYPE_SEDLBAUER_PCMCIA: case ISDN_CTYPE_SEDLBAUER_FAX: ret = setup_sedlbauer(card); break; #endif -#ifdef CONFIG_HISAX_SPORTSTER +#if CARD_SPORTSTER case ISDN_CTYPE_SPORTSTER: ret = setup_sportster(card); break; #endif -#ifdef CONFIG_HISAX_MIC +#if CARD_MIC case ISDN_CTYPE_MIC: ret = setup_mic(card); break; #endif -#ifdef CONFIG_HISAX_NETJET +#if CARD_NETJET_S case ISDN_CTYPE_NETJET_S: ret = setup_netjet_s(card); break; #endif -#ifdef CONFIG_HISAX_HFCS +#if CARD_HFCS case ISDN_CTYPE_TELES3C: case ISDN_CTYPE_ACERP10: ret = setup_hfcs(card); break; #endif -#ifdef CONFIG_HISAX_HFC_PCI +#if CARD_HFC_PCI case ISDN_CTYPE_HFC_PCI: ret = setup_hfcpci(card); break; #endif -#ifdef CONFIG_HISAX_HFC_SX +#if CARD_HFC_SX case ISDN_CTYPE_HFC_SX: ret = setup_hfcsx(card); break; #endif -#ifdef CONFIG_HISAX_NICCY +#if CARD_NICCY case ISDN_CTYPE_NICCY: ret = setup_niccy(card); break; #endif -#ifdef CONFIG_HISAX_AMD7930 +#if CARD_AMD7930 case ISDN_CTYPE_AMD7930: ret = setup_amd7930(card); break; #endif -#ifdef CONFIG_HISAX_ISURF +#if CARD_ISURF case ISDN_CTYPE_ISURF: ret = setup_isurf(card); break; #endif -#ifdef CONFIG_HISAX_HSTSAPHIR +#if CARD_HSTSAPHIR case ISDN_CTYPE_HSTSAPHIR: ret = setup_saphir(card); break; #endif -#ifdef CONFIG_HISAX_TESTEMU +#if CARD_TESTEMU case ISDN_CTYPE_TESTEMU: ret = setup_testemu(card); break; #endif -#ifdef CONFIG_HISAX_BKM_A4T +#if CARD_BKM_A4T case ISDN_CTYPE_BKM_A4T: ret = setup_bkm_a4t(card); break; #endif -#ifdef CONFIG_HISAX_SCT_QUADRO +#if CARD_SCT_QUADRO case ISDN_CTYPE_SCT_QUADRO: ret = setup_sct_quadro(card); break; #endif -#ifdef CONFIG_HISAX_GAZEL +#if CARD_GAZEL case ISDN_CTYPE_GAZEL: ret = setup_gazel(card); break; #endif -#ifdef CONFIG_HISAX_W6692 +#if CARD_W6692 case ISDN_CTYPE_W6692: ret = setup_w6692(card); break; #endif -#ifdef CONFIG_HISAX_NETJET_U +#if CARD_NETJET_U case ISDN_CTYPE_NETJET_U: ret = setup_netjet_u(card); break; #endif -#ifdef CONFIG_HISAX_ENTERNOW_PCI +#if CARD_FN_ENTERNOW_PCI case ISDN_CTYPE_ENTERNOW: ret = setup_enternow_pci(card); break; @@ -1125,40 +1138,62 @@ ll_unload(cs); goto outf_cs; } + if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) { + printk(KERN_WARNING "HiSax: No memory for isac rcvbuf\n"); + ll_unload(cs); + goto outf_cs; + } + cs->rcvidx = 0; + cs->tx_skb = NULL; + cs->tx_cnt = 0; + cs->event = 0; + cs->tqueue.data = cs; + + skb_queue_head_init(&cs->rq); + skb_queue_head_init(&cs->sq); + init_bcstate(cs, 0); init_bcstate(cs, 1); /* init_card only handles interrupts which are not */ /* used here for the loadable driver */ switch (card->typ) { - case ISDN_CTYPE_DYNAMIC: - ret = 0; - break; - default: - ret = init_card(cs); - break; + case ISDN_CTYPE_DYNAMIC: + ret = 0; + break; + default: + ret = init_card(cs); + break; } if (ret) { closecard(cardnr); ret = 0; goto outf_cs; } - if (do_init(cs)) { + init_tei(cs, cs->protocol); + ret = CallcNewChan(cs); + if (ret) { closecard(cardnr); ret = 0; goto outf_cs; } + /* ISAR needs firmware download first */ + if (!test_bit(HW_ISAR, &cs->HW_Flags)) + ll_run(cs, 0); + ret = 1; goto out; + outf_dlog: + kfree(cs->dlog); outf_cs: - free_IsdnCardState(cs); + kfree(cs); card->cs = NULL; out: return ret; } -void __devinit HiSax_shiftcards(int idx) +void HiSax_shiftcards(int idx) { int i; @@ -1166,7 +1201,7 @@ memcpy(&cards[i], &cards[i + 1], sizeof(cards[i])); } -int __devinit HiSax_inithardware(int *busy_flag) +int HiSax_inithardware(int *busy_flag) { int foundcards = 0; int i = 0; @@ -1196,13 +1231,16 @@ else sprintf(ids, "%s%d", id, i); } - if (checkcard(i, ids, busy_flag)) { + if (checkcard(i, ids, busy_flag, THIS_MODULE)) { foundcards++; i++; } else { - printk(KERN_WARNING - "HiSax: Card type %d not installed !\n", - cards[i].typ); + /* make sure we don't oops the module */ + if (cards[i].typ > 0 && cards[i].typ <= ISDN_CTYPE_COUNT) { + printk(KERN_WARNING + "HiSax: Card %s not installed !\n", + CardType[cards[i].typ]); + } HiSax_shiftcards(i); nrcards--; } @@ -1214,7 +1252,7 @@ { int i, last = nrcards - 1; - if (cardnr > last) + if (cardnr > last || cardnr < 0) return; if (cards[cardnr].cs) { ll_stop(cards[cardnr].cs); @@ -1492,182 +1530,9 @@ printk(KERN_INFO "HiSax module removed\n"); } -#ifdef CONFIG_HISAX_ELSA -int elsa_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) -{ -#ifdef MODULE - int i; - - nrcards = 0; - /* Initialize all structs, even though we only accept - two pcmcia cards - */ - for (i = 0; i < HISAX_MAX_CARDS; i++) { - cards[i].para[0] = irq[i]; - cards[i].para[1] = io[i]; - cards[i].typ = type[i]; - if (protocol[i]) { - cards[i].protocol = protocol[i]; - } else { - cards[i].protocol = DEFAULT_PROTO; - } - } - cards[0].para[0] = pcm_irq; - cards[0].para[1] = (int) pcm_iob; - cards[0].protocol = prot; - cards[0].typ = ISDN_CTYPE_ELSA_PCMCIA; - - if (!HiSax_id) - HiSax_id = HiSaxID; - if (!HiSaxID[0]) - strcpy(HiSaxID, "HiSax"); - for (i = 0; i < HISAX_MAX_CARDS; i++) - if (cards[i].typ > 0) - nrcards++; - printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", - nrcards, (nrcards > 1) ? "s" : ""); - - if (!HiSax_inithardware(busy_flag)) - return -ENODEV; - printk(KERN_NOTICE "HiSax: module installed\n"); -#endif - return 0; -} -#endif - -#ifdef CONFIG_HISAX_HFC_SX -int hfc_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) -{ -#ifdef MODULE - int i; - - nrcards = 0; - /* Initialize all structs, even though we only accept - two pcmcia cards - */ - for (i = 0; i < HISAX_MAX_CARDS; i++) { - cards[i].para[0] = irq[i]; - cards[i].para[1] = io[i]; - cards[i].typ = type[i]; - if (protocol[i]) { - cards[i].protocol = protocol[i]; - } else { - cards[i].protocol = DEFAULT_PROTO; - } - } - cards[0].para[0] = pcm_irq; - cards[0].para[1] = (int) pcm_iob; - cards[0].protocol = prot; - cards[0].typ = ISDN_CTYPE_HFC_SP_PCMCIA; - - if (!HiSax_id) - HiSax_id = HiSaxID; - if (!HiSaxID[0]) - strcpy(HiSaxID, "HiSax"); - for (i = 0; i < HISAX_MAX_CARDS; i++) - if (cards[i].typ > 0) - nrcards++; - printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", - nrcards, (nrcards > 1) ? "s" : ""); - - if (!HiSax_inithardware(busy_flag)) - return -ENODEV; - printk(KERN_NOTICE "HiSax: module installed\n"); -#endif - return 0; -} -#endif - -#ifdef CONFIG_HISAX_SEDLBAUER -int sedl_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) +int hisax_init_pcmcia(void *pcm_iob, int *busy_flag, struct IsdnCard *card) { -#ifdef MODULE - int i; - - nrcards = 0; - /* Initialize all structs, even though we only accept - two pcmcia cards - */ - for (i = 0; i < HISAX_MAX_CARDS; i++) { - cards[i].para[0] = irq[i]; - cards[i].para[1] = io[i]; - cards[i].typ = type[i]; - if (protocol[i]) { - cards[i].protocol = protocol[i]; - } else { - cards[i].protocol = DEFAULT_PROTO; - } - } - cards[0].para[0] = pcm_irq; - cards[0].para[1] = (int) pcm_iob; - cards[0].protocol = prot; - cards[0].typ = ISDN_CTYPE_SEDLBAUER_PCMCIA; - - if (!HiSax_id) - HiSax_id = HiSaxID; - if (!HiSaxID[0]) - strcpy(HiSaxID, "HiSax"); - for (i = 0; i < HISAX_MAX_CARDS; i++) - if (cards[i].typ > 0) - nrcards++; - printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", - nrcards, (nrcards > 1) ? "s" : ""); - - if (!HiSax_inithardware(busy_flag)) - return -ENODEV; - printk(KERN_NOTICE "HiSax: module installed\n"); -#endif - return 0; -} -#endif - -#ifdef CONFIG_HISAX_AVM_A1_PCMCIA -int avm_a1_init_pcmcia(void *pcm_iob, int pcm_irq, int *busy_flag, int prot) -{ -#ifdef MODULE - int i; - - nrcards = 0; - /* Initialize all structs, even though we only accept - two pcmcia cards - */ - for (i = 0; i < HISAX_MAX_CARDS; i++) { - cards[i].para[0] = irq[i]; - cards[i].para[1] = io[i]; - cards[i].typ = type[i]; - if (protocol[i]) { - cards[i].protocol = protocol[i]; - } else { - cards[i].protocol = DEFAULT_PROTO; - } - } - cards[0].para[0] = pcm_irq; - cards[0].para[1] = (int) pcm_iob; - cards[0].protocol = prot; - cards[0].typ = ISDN_CTYPE_A1_PCMCIA; - - if (!HiSax_id) - HiSax_id = HiSaxID; - if (!HiSaxID[0]) - strcpy(HiSaxID, "HiSax"); - for (i = 0; i < HISAX_MAX_CARDS; i++) - if (cards[i].typ > 0) - nrcards++; - printk(KERN_DEBUG "HiSax: Total %d card%s defined\n", - nrcards, (nrcards > 1) ? "s" : ""); - - if (!HiSax_inithardware(busy_flag)) - return -ENODEV; - printk(KERN_NOTICE "HiSax: module installed\n"); -#endif - return 0; -} -#endif - -int __devinit hisax_init_pcmcia(void *pcm_iob, int *busy_flag, - struct IsdnCard *card) -{ - u8 ids[16]; + u_char ids[16]; int ret = -1; cards[nrcards] = *card; @@ -1675,14 +1540,18 @@ sprintf(ids, "HiSax%d", nrcards); else sprintf(ids, "HiSax"); - if (!checkcard(nrcards, ids, busy_flag)) { - return -1; - } + if (!checkcard(nrcards, ids, busy_flag, THIS_MODULE)) + goto error; + ret = nrcards; nrcards++; +error: return ret; } +EXPORT_SYMBOL(hisax_init_pcmcia); +EXPORT_SYMBOL(HiSax_closecard); + #include "hisax_if.h" EXPORT_SYMBOL(hisax_register); @@ -1692,68 +1561,47 @@ static void hisax_b_l1l2(struct hisax_if *ifc, int pr, void *arg); static void hisax_d_l2l1(struct PStack *st, int pr, void *arg); static void hisax_b_l2l1(struct PStack *st, int pr, void *arg); +static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg); static int hisax_bc_setstack(struct PStack *st, struct BCState *bcs); static void hisax_bc_close(struct BCState *bcs); -static void hisax_bh(void *data); +static void hisax_bh(struct IsdnCardState *cs); static void EChannel_proc_rcv(struct hisax_d_if *d_if); -static int -hisax_l1_open(struct PStack *st, struct IsdnCardState *cs) -{ - st->l1.l2l1 = hisax_d_l2l1; - return 0; -} - -static struct dc_l1_ops hisax_l1_ops = { - .open = hisax_l1_open, - .bh_func = hisax_bh, -}; - -static struct bc_l1_ops hisax_bc_l1_ops = { - .open = hisax_bc_setstack, - .close = hisax_bc_close, -}; - int hisax_register(struct hisax_d_if *hisax_d_if, struct hisax_b_if *b_if[], char *name, int protocol) { - int i; + int i, retval; + char id[20]; struct IsdnCardState *cs; - + for (i = 0; i < HISAX_MAX_CARDS; i++) { if (!cards[i].typ) break; } - + if (i >= HISAX_MAX_CARDS) return -EBUSY; - - nrcards++; - - cs = alloc_IsdnCardState(); - if (!cs) - return -ENOMEM; - -#if TEI_PER_CARD - if (protocol == ISDN_PTYPE_NI1) - test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); -#else - test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags); -#endif - cs->cardnr = i; - cs->protocol = protocol; - cs->typ = ISDN_CTYPE_DYNAMIC; - - sprintf(cs->iif.id, "%s%d", name, i); - do_register_isdn(cs); + cards[i].typ = ISDN_CTYPE_DYNAMIC; + cards[i].protocol = protocol; + sprintf(id, "%s%d", name, i); + nrcards++; + retval = checkcard(i, id, 0, hisax_d_if->owner); + if (retval == 0) { // yuck + cards[i].typ = 0; + nrcards--; + return retval; + } + cs = cards[i].cs; hisax_d_if->cs = cs; cs->hw.hisax_d_if = hisax_d_if; - cs->iif.owner = hisax_d_if->owner; - dc_l1_init(cs, &hisax_l1_ops); - cs->bc_l1_ops = &hisax_bc_l1_ops; - + cs->cardmsg = hisax_cardmsg; + INIT_WORK(&cs->tqueue, (void *)(void *)hisax_bh, cs); + cs->channel[0].d_st->l2.l2l1 = hisax_d_l2l1; for (i = 0; i < 2; i++) { + cs->bcs[i].BC_SetStack = hisax_bc_setstack; + cs->bcs[i].BC_Close = hisax_bc_close; + b_if[i]->ifc.l1l2 = hisax_b_l1l2; hisax_d_if->b_if[i] = b_if[i]; @@ -1762,8 +1610,6 @@ skb_queue_head_init(&hisax_d_if->erq); clear_bit(0, &hisax_d_if->ph_state); - do_init(cs); - return 0; } @@ -1776,9 +1622,14 @@ #include "isdnl1.h" -static void hisax_bh(void *data) +static void hisax_sched_event(struct IsdnCardState *cs, int event) +{ + test_and_set_bit(event, &cs->event); + schedule_work(&cs->tqueue); +} + +static void hisax_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; struct PStack *st; int pr; @@ -1792,11 +1643,17 @@ else pr = PH_DEACTIVATE | INDICATION; for (st = cs->stlist; st; st = st->next) - L1L2(st, pr, NULL); + st->l1.l1l2(st, pr, NULL); } } +static void hisax_b_sched_event(struct BCState *bcs, int event) +{ + test_and_set_bit(event, &bcs->event); + schedule_work(&bcs->tqueue); +} + static inline void D_L2L1(struct hisax_d_if *d_if, int pr, void *arg) { struct hisax_if *ifc = (struct hisax_if *) d_if; @@ -1819,15 +1676,15 @@ switch (pr) { case PH_ACTIVATE | INDICATION: set_bit(0, &d_if->ph_state); - sched_d_event(cs, D_L1STATECHANGE); + hisax_sched_event(cs, D_L1STATECHANGE); break; case PH_DEACTIVATE | INDICATION: clear_bit(0, &d_if->ph_state); - sched_d_event(cs, D_L1STATECHANGE); + hisax_sched_event(cs, D_L1STATECHANGE); break; case PH_DATA | INDICATION: skb_queue_tail(&cs->rq, arg); - sched_d_event(cs, D_RCVBUFREADY); + hisax_sched_event(cs, D_RCVBUFREADY); break; case PH_DATA | CONFIRM: skb = skb_dequeue(&cs->sq); @@ -1838,14 +1695,14 @@ clear_bit(FLG_L1_DBUSY, &cs->HW_Flags); for (st = cs->stlist; st; st = st->next) { if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags)) { - L1L2(st, PH_PULL | CONFIRM, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); break; } } break; case PH_DATA_E | INDICATION: skb_queue_tail(&d_if->erq, arg); - sched_d_event(cs, E_RCVBUFREADY); + hisax_sched_event(cs, E_RCVBUFREADY); break; default: printk("pr %#x\n", pr); @@ -1863,22 +1720,27 @@ // FIXME use isdnl1? switch (pr) { case PH_ACTIVATE | INDICATION: - L1L2(st, pr, NULL); + st->l1.l1l2(st, pr, NULL); break; case PH_DEACTIVATE | INDICATION: - L1L2(st, pr, NULL); + st->l1.l1l2(st, pr, NULL); clear_bit(BC_FLG_BUSY, &bcs->Flag); skb_queue_purge(&bcs->squeue); bcs->hw.b_if = NULL; break; case PH_DATA | INDICATION: skb_queue_tail(&bcs->rqueue, arg); - sched_b_event(bcs, B_RCVBUFREADY); + hisax_b_sched_event(bcs, B_RCVBUFREADY); break; case PH_DATA | CONFIRM: - skb = arg; - bcs->tx_cnt -= skb->truesize; - xmit_complete_b(bcs); + bcs->tx_cnt -= (int) arg; + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += (int) arg; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } skb = skb_dequeue(&bcs->squeue); if (skb) { B_L2L1(b_if, PH_DATA | REQUEST, skb); @@ -1886,7 +1748,7 @@ } clear_bit(BC_FLG_BUSY, &bcs->Flag); if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags)) { - L1L2(st, PH_PULL | CONFIRM, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); } break; default: @@ -1917,7 +1779,7 @@ break; case PH_PULL | REQUEST: if (!test_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - L1L2(st, PH_PULL | CONFIRM, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); else set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; @@ -1927,6 +1789,11 @@ } } +static int hisax_cardmsg(struct IsdnCardState *cs, int mt, void *arg) +{ + return 0; +} + static void hisax_b_l2l1(struct PStack *st, int pr, void *arg) { struct BCState *bcs = st->l1.bcs; @@ -1947,7 +1814,7 @@ break; case PH_PULL | REQUEST: if (!test_bit(BC_FLG_BUSY, &bcs->Flag)) - L1L2(st, PH_PULL | CONFIRM, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); else set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; @@ -1971,7 +1838,7 @@ hisax_d_if->b_if[st->l1.bc]->bcs = bcs; st->l1.bcs = bcs; - st->l1.l2l1 = hisax_b_l2l1; + st->l2.l2l1 = hisax_b_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); @@ -1991,7 +1858,7 @@ static void EChannel_proc_rcv(struct hisax_d_if *d_if) { struct IsdnCardState *cs = d_if->cs; - u8 *ptr; + u_char *ptr; struct sk_buff *skb; while ((skb = skb_dequeue(&d_if->erq)) != NULL) { @@ -2017,103 +1884,9 @@ } } -void -resources_init(struct resources *rs) -{ - INIT_LIST_HEAD(&rs->res_head); -} - -void -resources_release(struct resources *rs) -{ - struct res *r; - - list_for_each_entry(r, &rs->res_head, node) { - if (r->flags & IORESOURCE_IO) { - release_region(r->start, r->end - r->start + 1); - } - if (r->flags & IORESOURCE_MEM) { - iounmap(r->r_u.ioremap_addr); - release_mem_region(r->start, r->end - r->start + 1); - } - } -} - -unsigned long -request_io(struct resources *rs, unsigned long start, int len, - const char *name) -{ - struct res *r; - - r = kmalloc(sizeof(*r), GFP_KERNEL); - if (!r) { - printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__); - goto err; - } - if (!request_region(start, len, name)) { - printk(KERN_WARNING "%s: IO %#lx-%#lx already in use\n", - __FUNCTION__, start, start + len - 1); - goto err_free; - } - r->flags = IORESOURCE_IO; - r->start = start; - r->end = start + len - 1; - r->name = name; - list_add_tail(&r->node, &rs->res_head); - - return r->start; - - err_free: - kfree(r); - err: - return 0; -} - -void * -request_mmio(struct resources *rs, unsigned long start, int len, - const char *name) -{ - struct res *r; - - r = kmalloc(sizeof(*r), GFP_KERNEL); - if (!r) { - printk(KERN_WARNING "%s: out of memory\n", __FUNCTION__); - goto err; - } - if (!request_mem_region(start, len, name)) { - printk(KERN_WARNING "%s: MMIO %#lx-%#lx already in use\n", - __FUNCTION__, start, start + len - 1); - goto err_free; - } - r->flags = IORESOURCE_MEM; - r->start = start; - r->end = start + len - 1; - r->name = name; - r->r_u.ioremap_addr = ioremap(start, len); - if (!r->r_u.ioremap_addr) - goto err_release; - - list_add_tail(&r->node, &rs->res_head); - - return r->r_u.ioremap_addr; - - err_release: - release_mem_region(r->start, r->end - r->start + 1); - err_free: - kfree(r); - err: - return 0; -} - -void -hisax_release_resources(struct IsdnCardState *cs) -{ - resources_release(&cs->rs); -} - #include -static struct pci_device_id hisax_pci_tbl[] = { +static struct pci_device_id hisax_pci_tbl[] __initdata = { #ifdef CONFIG_HISAX_FRITZPCI {PCI_VENDOR_ID_AVM, PCI_DEVICE_ID_AVM_A1, PCI_ANY_ID, PCI_ANY_ID}, #endif @@ -2121,7 +1894,9 @@ {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20, PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA20_U, PCI_ANY_ID, PCI_ANY_ID}, {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA201, PCI_ANY_ID, PCI_ANY_ID}, +//######################################################################################### {PCI_VENDOR_ID_EICON, PCI_DEVICE_ID_EICON_DIVA202, PCI_ANY_ID, PCI_ANY_ID}, +//######################################################################################### #endif #ifdef CONFIG_HISAX_ELSA {PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK, PCI_ANY_ID, PCI_ANY_ID}, diff -Nru a/drivers/isdn/hisax/diva.c b/drivers/isdn/hisax/diva.c --- a/drivers/isdn/hisax/diva.c Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/hisax/diva.c Thu Feb 19 23:44:28 2004 @@ -1,4 +1,4 @@ -/* $Id: diva.c,v 1.25.6.5 2001/09/23 22:24:47 kai Exp $ +/* $Id: diva.c,v 1.33.2.6 2004/02/11 13:21:33 keil Exp $ * * low level stuff for Eicon.Diehl Diva Family ISDN cards * @@ -28,8 +28,7 @@ extern const char *CardType[]; -const char *Diva_revision = "$Revision: 1.25.6.5 $"; -static spinlock_t diva_lock = SPIN_LOCK_UNLOCKED; +const char *Diva_revision = "$Revision: 1.33.2.6 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -82,376 +81,715 @@ #endif #define PITA_INT0_STATUS 0x02 -static inline u8 -readreg(unsigned int ale, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&diva_lock, flags); byteout(ale, off); ret = bytein(adr); - spin_unlock_irqrestore(&diva_lock, flags); - return ret; + return (ret); } static inline void -writereg(unsigned int ale, unsigned int adr, u8 off, u8 data) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; - - spin_lock_irqsave(&diva_lock, flags); byteout(ale, off); - byteout(adr, data); - spin_unlock_irqrestore(&diva_lock, flags); + insb(adr, data, size); } + static inline void -readfifo(unsigned int ale, unsigned int adr, u8 off, u8 * data, int size) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { byteout(ale, off); - insb(adr, data, size); + byteout(adr, data); } static inline void -writefifo(unsigned int ale, unsigned int adr, u8 off, u8 *data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char *data, int size) { byteout(ale, off); outsb(adr, data, size); } -static inline u8 -memreadreg(unsigned long adr, u8 off) +static inline u_char +memreadreg(unsigned long adr, u_char off) { - return readb(((unsigned int *)adr) + off); + return(*((unsigned char *) + (((unsigned int *)adr) + off))); } static inline void -memwritereg(unsigned long adr, u8 off, u8 data) +memwritereg(unsigned long adr, u_char off, u_char data) { - writeb(data, ((unsigned int *)adr) + off); + register u_char *p; + + p = (unsigned char *)(((unsigned int *)adr) + off); + *p = data; } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset); + return(readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char *data, int size) { readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char *data, int size) { writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, - offset + (hscx ? 0x40 : 0)); + return (readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset+0x80)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, - offset + (hscx ? 0x40 : 0), value); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset|0x80, value); } static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - readfifo(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, hscx ? 0x40 : 0, data, size); + readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size); } static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, hscx ? 0x40 : 0, data, size); + writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, 0x80, data, size); } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static inline u8 -ipac_read(struct IsdnCardState *cs, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - return readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset); + return(readreg(cs->hw.diva.hscx_adr, + cs->hw.diva.hscx, offset + (hscx ? 0x40 : 0))); } -static inline void -ipac_write(struct IsdnCardState *cs, u8 offset, u8 value) +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, value); + writereg(cs->hw.diva.hscx_adr, + cs->hw.diva.hscx, offset + (hscx ? 0x40 : 0), value); } -static inline void -ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +static u_char +MemReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) { - readfifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, data, size); + return (memreadreg(cs->hw.diva.cfg_reg, offset+0x80)); } -static inline void -ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +static void +MemWriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writefifo(cs->hw.diva.isac_adr, cs->hw.diva.isac, offset, data, size); + memwritereg(cs->hw.diva.cfg_reg, offset|0x80, value); } -/* This will generate ipac_dc_ops and ipac_bc_ops using the functions - * above */ - -BUILD_IPAC_OPS(ipac); - -static inline u8 -mem_ipac_read(struct IsdnCardState *cs, u8 offset) +static void +MemReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - return memreadreg(cs->hw.diva.cfg_reg, offset); + while(size--) + *data++ = memreadreg(cs->hw.diva.cfg_reg, 0x80); } -static inline void -mem_ipac_write(struct IsdnCardState *cs, u8 offset, u8 value) +static void +MemWriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - memwritereg(cs->hw.diva.cfg_reg, offset, value); + while(size--) + memwritereg(cs->hw.diva.cfg_reg, 0x80, *data++); } -static inline void -mem_ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +static u_char +MemReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - while(size--) - *data++ = memreadreg(cs->hw.diva.cfg_reg, offset); + return(memreadreg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0))); } -static inline void -mem_ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +static void +MemWriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - while(size--) - memwritereg(cs->hw.diva.cfg_reg, offset, *data++); + memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? 0x40 : 0), value); } -/* This will generate mem_ipac_dc_ops and mem_ipac_bc_ops using the functions - * above */ - -BUILD_IPAC_OPS(mem_ipac); - /* IO-Functions for IPACX type cards */ -static u8 -ipacx_dc_read(struct IsdnCardState *cs, u8 offset) +static u_char +MemReadISAC_IPACX(struct IsdnCardState *cs, u_char offset) { - return memreadreg(cs->hw.diva.cfg_reg, offset); + return (memreadreg(cs->hw.diva.cfg_reg, offset)); } static void -ipacx_dc_write(struct IsdnCardState *cs, u8 offset, u8 value) +MemWriteISAC_IPACX(struct IsdnCardState *cs, u_char offset, u_char value) { memwritereg(cs->hw.diva.cfg_reg, offset, value); } static void -ipacx_dc_read_fifo(struct IsdnCardState *cs, u8 *data, int size) +MemReadISACfifo_IPACX(struct IsdnCardState *cs, u_char * data, int size) { while(size--) *data++ = memreadreg(cs->hw.diva.cfg_reg, 0); } static void -ipacx_dc_write_fifo(struct IsdnCardState *cs, u8 *data, int size) +MemWriteISACfifo_IPACX(struct IsdnCardState *cs, u_char * data, int size) { while(size--) memwritereg(cs->hw.diva.cfg_reg, 0, *data++); } -static struct dc_hw_ops ipacx_dc_ops = { - .read_reg = ipacx_dc_read, - .write_reg = ipacx_dc_write, - .read_fifo = ipacx_dc_read_fifo, - .write_fifo = ipacx_dc_write_fifo, -}; - -static u8 -ipacx_bc_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +MemReadHSCX_IPACX(struct IsdnCardState *cs, int hscx, u_char offset) { - return memreadreg(cs->hw.diva.cfg_reg, offset + - (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1)); + return(memreadreg(cs->hw.diva.cfg_reg, offset + + (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1))); } static void -ipacx_bc_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +MemWriteHSCX_IPACX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { memwritereg(cs->hw.diva.cfg_reg, offset + (hscx ? IPACX_OFF_B2 : IPACX_OFF_B1), value); } -static void -ipacx_bc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int len) -{ - int i; +/* + * fast interrupt HSCX stuff goes here + */ - for (i = 0; i < len ; i++) - *data++ = ipacx_bc_read(cs, hscx, IPACX_RFIFOB); -} +#define READHSCX(cs, nr, reg) readreg(cs->hw.diva.hscx_adr, \ + cs->hw.diva.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.diva.hscx_adr, \ + cs->hw.diva.hscx, reg + (nr ? 0x40 : 0), data) -static struct bc_hw_ops ipacx_bc_ops = { - .read_reg = ipacx_bc_read, - .write_reg = ipacx_bc_write, - .read_fifo = ipacx_bc_read_fifo, -}; +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.diva.hscx_adr, \ + cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.diva.hscx_adr, \ + cs->hw.diva.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" static irqreturn_t diva_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 sval; + u_char val, sval; + u_long flags; int cnt=5; + spin_lock_irqsave(&cs->lock, flags); while (((sval = bytein(cs->hw.diva.ctrl)) & DIVA_IRQ_REQ) && cnt) { - hscxisac_irq(intno, dev_id, regs); + val = readreg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_ISTA + 0x40); + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA); + if (val) + isac_interrupt(cs, val); + cnt--; } if (!cnt) printk(KERN_WARNING "Diva: IRQ LOOP\n"); + writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_MASK, 0x0); + writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK, 0x0); + writereg(cs->hw.diva.hscx_adr, cs->hw.diva.hscx, HSCX_MASK + 0x40, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } static irqreturn_t -diva_ipac_pci_irq(int intno, void *dev_id, struct pt_regs *regs) +diva_irq_ipac_isa(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; + u_char ista,val; + u_long flags; + int icnt=5; + + spin_lock_irqsave(&cs->lock, flags); + ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA); +Start_IPACISA: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) + hscx_int_main(cs, val); + } + if (ista & 0x20) { + val = 0xfe & readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, ISAC_ISTA + 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPACISA; + } + if (!icnt) + printk(KERN_WARNING "DIVA IPAC IRQ LOOP\n"); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xFF); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xC0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} - val = readb(cs->hw.diva.pci_cfg); - if (!(val & PITA_INT0_STATUS)) - return IRQ_NONE; /* other shared IRQ */ - writeb(PITA_INT0_STATUS, cs->hw.diva.pci_cfg); /* Reset pending INT0 */ +static inline void +MemwaitforCEC(struct IsdnCardState *cs, int hscx) +{ + int to = 50; - return ipac_irq(intno, dev_id, regs); + while ((MemReadHSCX(cs, hscx, HSCX_STAR) & 0x04) && to) { + udelay(1); + to--; + } + if (!to) + printk(KERN_WARNING "HiSax: waitforCEC timeout\n"); } -static irqreturn_t -diva_ipacx_pci_irq(int intno, void *dev_id, struct pt_regs *regs) + +static inline void +MemwaitforXFW(struct IsdnCardState *cs, int hscx) { - struct IsdnCardState *cs = dev_id; - u8 val; + int to = 50; - val = readb(cs->hw.diva.pci_cfg); - if (!(val &PITA_INT0_STATUS)) - return IRQ_NONE; // other shared IRQ - interrupt_ipacx(cs); // handler for chip - writeb(PITA_INT0_STATUS, cs->hw.diva.pci_cfg); // Reset PLX interrupt - return IRQ_HANDLED; + while ((!(MemReadHSCX(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) { + udelay(1); + to--; + } + if (!to) + printk(KERN_WARNING "HiSax: waitforXFW timeout\n"); } -static void -diva_release(struct IsdnCardState *cs) +static inline void +MemWriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data) { - del_timer_sync(&cs->hw.diva.tl); - if (cs->hw.diva.cfg_reg) - byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */ + MemwaitforCEC(cs, hscx); + MemWriteHSCX(cs, hscx, HSCX_CMDR, data); +} - hisax_release_resources(cs); +static void +Memhscx_empty_fifo(struct BCState *bcs, int count) +{ + u_char *ptr; + struct IsdnCardState *cs = bcs->cs; + int cnt; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hscx_empty_fifo"); + + if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "hscx_empty_fifo: incoming packet too large"); + MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); + bcs->hw.hscx.rcvidx = 0; + return; + } + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + cnt = count; + while (cnt--) + *ptr++ = memreadreg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0); + MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + bcs->hw.hscx.rcvidx += count; + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "hscx_empty_fifo %c cnt %d", + bcs->hw.hscx.hscx ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } static void -diva_ipac_pci_release(struct IsdnCardState *cs) +Memhscx_fill_fifo(struct BCState *bcs) { - writel(0, cs->hw.diva.pci_cfg); /* disable INT0/1 */ - writel(2, cs->hw.diva.pci_cfg); /* reset pending INT0 */ - hisax_release_resources(cs); + struct IsdnCardState *cs = bcs->cs; + int more, count, cnt; + int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; + u_char *ptr,*p; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hscx_fill_fifo"); + + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) + return; + + more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; + if (bcs->tx_skb->len > fifo_size) { + more = !0; + count = fifo_size; + } else + count = bcs->tx_skb->len; + cnt = count; + MemwaitforXFW(cs, bcs->hw.hscx.hscx); + p = ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.hscx.count += count; + while(cnt--) + memwritereg(cs->hw.diva.cfg_reg, bcs->hw.hscx.hscx ? 0x40 : 0, + *p++); + MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "hscx_fill_fifo %c cnt %d", + bcs->hw.hscx.hscx ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } -static int -diva_ipac_isa_reset(struct IsdnCardState *cs) +static inline void +Memhscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) { - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0); - return 0; + u_char r; + struct BCState *bcs = cs->bcs + hscx; + struct sk_buff *skb; + int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; + int count; + + if (!test_bit(BC_FLG_INIT, &bcs->Flag)) + return; + + if (val & 0x80) { /* RME */ + r = MemReadHSCX(cs, hscx, HSCX_RSTA); + if ((r & 0xf0) != 0xa0) { + if (!(r & 0x80)) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX invalid frame"); + if ((r & 0x40) && bcs->mode) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX RDO mode=%d", + bcs->mode); + if (!(r & 0x20)) + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX CRC error"); + MemWriteHSCXCMDR(cs, hscx, 0x80); + } else { + count = MemReadHSCX(cs, hscx, HSCX_RBCL) & ( + test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f); + if (count == 0) + count = fifo_size; + Memhscx_empty_fifo(bcs, count); + if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { + if (cs->debug & L1_DEB_HSCX_FIFO) + debugl1(cs, "HX Frame %d", count); + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "HSCX: receive out of memory\n"); + else { + memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); + skb_queue_tail(&bcs->rqueue, skb); + } + } + } + bcs->hw.hscx.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); + } + if (val & 0x40) { /* RPF */ + Memhscx_empty_fifo(bcs, fifo_size); + if (bcs->mode == L1_MODE_TRANS) { + /* receive audio data */ + if (!(skb = dev_alloc_skb(fifo_size))) + printk(KERN_WARNING "HiSax: receive out of memory\n"); + else { + memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.hscx.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); + } + } + if (val & 0x10) { /* XPR */ + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + Memhscx_fill_fifo(bcs); + return; + } else { + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hscx.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_irq(bcs->tx_skb); + bcs->hw.hscx.count = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hscx.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + Memhscx_fill_fifo(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + schedule_event(bcs, B_XMTBUFREADY); + } + } } -static int -diva_ipac_pci_reset(struct IsdnCardState *cs) +static inline void +Memhscx_int_main(struct IsdnCardState *cs, u_char val) +{ + + u_char exval; + struct BCState *bcs; + + if (val & 0x01) { // EXB + bcs = cs->bcs + 1; + exval = MemReadHSCX(cs, 1, HSCX_EXIR); + if (exval & 0x40) { + if (bcs->mode == 1) + Memhscx_fill_fifo(bcs); + else { + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hscx.count); + bcs->tx_cnt += bcs->hw.hscx.count; + bcs->hw.hscx.count = 0; + } + MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX B EXIR %x Lost TX", exval); + } + } else if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX B EXIR %x", exval); + } + if (val & 0xf8) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX B interrupt %x", val); + Memhscx_interrupt(cs, val, 1); + } + if (val & 0x02) { // EXA + bcs = cs->bcs; + exval = MemReadHSCX(cs, 0, HSCX_EXIR); + if (exval & 0x40) { + if (bcs->mode == L1_MODE_TRANS) + Memhscx_fill_fifo(bcs); + else { + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hscx.count); + bcs->tx_cnt += bcs->hw.hscx.count; + bcs->hw.hscx.count = 0; + } + MemWriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX A EXIR %x Lost TX", exval); + } + } else if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX A EXIR %x", exval); + } + if (val & 0x04) { // ICA + exval = MemReadHSCX(cs, 0, HSCX_ISTA); + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX A interrupt %x", exval); + Memhscx_interrupt(cs, exval, 0); + } +} + +static irqreturn_t +diva_irq_ipac_pci(int intno, void *dev_id, struct pt_regs *regs) { - unsigned long misc_reg = cs->hw.diva.pci_cfg + PITA_MISC_REG; + struct IsdnCardState *cs = dev_id; + u_char ista,val; + int icnt=5; + u_char *cfg; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + cfg = (u_char *) cs->hw.diva.pci_cfg; + val = *cfg; + if (!(val & PITA_INT0_STATUS)) { + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_NONE; /* other shared IRQ */ + } + *cfg = PITA_INT0_STATUS; /* Reset pending INT0 */ + ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA); +Start_IPACPCI: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = memreadreg(cs->hw.diva.cfg_reg, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) + Memhscx_int_main(cs, val); + } + if (ista & 0x20) { + val = 0xfe & memreadreg(cs->hw.diva.cfg_reg, ISAC_ISTA + 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = memreadreg(cs->hw.diva.cfg_reg, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPACPCI; + } + if (!icnt) + printk(KERN_WARNING "DIVA IPAC PCI IRQ LOOP\n"); + memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xFF); + memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xC0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} - writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE, misc_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writel(PITA_PARA_MPX_MODE, misc_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0); - return 0; +static irqreturn_t +diva_irq_ipacx_pci(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val; + u_char *cfg; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + cfg = (u_char *) cs->hw.diva.pci_cfg; + val = *cfg; + if (!(val &PITA_INT0_STATUS)) { + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_NONE; // other shared IRQ + } + interrupt_ipacx(cs); // handler for chip + *cfg = PITA_INT0_STATUS; // Reset PLX interrupt + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; } -static int -diva_ipacx_pci_reset(struct IsdnCardState *cs) +void +release_io_diva(struct IsdnCardState *cs) { - unsigned long misc_reg = cs->hw.diva.pci_cfg + PITA_MISC_REG; + int bytecnt; - writel(PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE, misc_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writel(PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET, misc_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - ipacx_dc_write(cs, IPACX_MASK, 0xff); // Interrupts off - return 0; + if ((cs->subtyp == DIVA_IPAC_PCI) || + (cs->subtyp == DIVA_IPACX_PCI) ) { + u_int *cfg = (unsigned int *)cs->hw.diva.pci_cfg; + + *cfg = 0; /* disable INT0/1 */ + *cfg = 2; /* reset pending INT0 */ + iounmap((void *)cs->hw.diva.cfg_reg); + iounmap((void *)cs->hw.diva.pci_cfg); + return; + } else if (cs->subtyp != DIVA_IPAC_ISA) { + del_timer(&cs->hw.diva.tl); + if (cs->hw.diva.cfg_reg) + byteout(cs->hw.diva.ctrl, 0); /* LED off, Reset */ + } + if ((cs->subtyp == DIVA_ISA) || (cs->subtyp == DIVA_IPAC_ISA)) + bytecnt = 8; + else + bytecnt = 32; + if (cs->hw.diva.cfg_reg) { + release_region(cs->hw.diva.cfg_reg, bytecnt); + } } -static int -diva_reset(struct IsdnCardState *cs) +static void +reset_diva(struct IsdnCardState *cs) { - /* DIVA 2.0 */ - cs->hw.diva.ctrl_reg = 0; /* Reset On */ - byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */ - byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - if (cs->subtyp == DIVA_ISA) { - cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A; - } else { - /* Workaround PCI9060 */ - byteout(cs->hw.diva.pci_cfg + 0x69, 9); - cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A; + if (cs->subtyp == DIVA_IPAC_ISA) { + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x20); + mdelay(10); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_POTA2, 0x00); + mdelay(10); + writereg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_MASK, 0xc0); + } else if (cs->subtyp == DIVA_IPAC_PCI) { + unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg + + PITA_MISC_REG); + *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE; + mdelay(10); + *ireg = PITA_PARA_MPX_MODE; + mdelay(10); + memwritereg(cs->hw.diva.cfg_reg, IPAC_MASK, 0xc0); + } else if (cs->subtyp == DIVA_IPACX_PCI) { + unsigned int *ireg = (unsigned int *)(cs->hw.diva.pci_cfg + + PITA_MISC_REG); + *ireg = PITA_PARA_SOFTRESET | PITA_PARA_MPX_MODE; + mdelay(10); + *ireg = PITA_PARA_MPX_MODE | PITA_SER_SOFTRESET; + mdelay(10); + MemWriteISAC_IPACX(cs, IPACX_MASK, 0xff); // Interrupts off + } else { /* DIVA 2.0 */ + cs->hw.diva.ctrl_reg = 0; /* Reset On */ + byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); + mdelay(10); + cs->hw.diva.ctrl_reg |= DIVA_RESET; /* Reset Off */ + byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); + mdelay(10); + if (cs->subtyp == DIVA_ISA) + cs->hw.diva.ctrl_reg |= DIVA_ISA_LED_A; + else { + /* Workaround PCI9060 */ + byteout(cs->hw.diva.pci_cfg + 0x69, 9); + cs->hw.diva.ctrl_reg |= DIVA_PCI_LED_A; + } + byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); } - byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - return 0; } +#define DIVA_ASSIGN 1 + static void diva_led_handler(struct IsdnCardState *cs) { int blink = 0; - if (cs->status & 0x0001) + if ((cs->subtyp == DIVA_IPAC_ISA) || + (cs->subtyp == DIVA_IPAC_PCI) || + (cs->subtyp == DIVA_IPACX_PCI) ) + return; + del_timer(&cs->hw.diva.tl); + if (cs->hw.diva.status & DIVA_ASSIGN) cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_A : DIVA_PCI_LED_A; else { @@ -459,10 +797,10 @@ DIVA_ISA_LED_A : DIVA_PCI_LED_A; blink = 250; } - if (cs->status & 0xf000) + if (cs->hw.diva.status & 0xf000) cs->hw.diva.ctrl_reg |= (DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_B : DIVA_PCI_LED_B; - else if (cs->status & 0x0f00) { + else if (cs->hw.diva.status & 0x0f00) { cs->hw.diva.ctrl_reg ^= (DIVA_ISA == cs->subtyp) ? DIVA_ISA_LED_B : DIVA_PCI_LED_B; blink = 500; @@ -471,212 +809,90 @@ DIVA_ISA_LED_B : DIVA_PCI_LED_B); byteout(cs->hw.diva.ctrl, cs->hw.diva.ctrl_reg); - if (blink) - mod_timer(&cs->hw.diva.tl, jiffies + (blink * HZ) / 1000); -} - -static void -diva_ipacx_pci_init(struct IsdnCardState *cs) -{ - writel(PITA_INT0_ENABLE, cs->hw.diva.pci_cfg); - init_ipacx(cs, 3); // init chip and enable interrupts -} - -static void -diva_ipac_pci_init(struct IsdnCardState *cs) -{ - writel(PITA_INT0_ENABLE, cs->hw.diva.pci_cfg); - ipac_init(cs); -} - -static struct card_ops diva_ops = { - .init = inithscxisac, - .reset = diva_reset, - .release = diva_release, - .led_handler = diva_led_handler, - .irq_func = diva_interrupt, -}; - -static struct card_ops diva_ipac_isa_ops = { - .init = ipac_init, - .reset = diva_ipac_isa_reset, - .release = hisax_release_resources, - .irq_func = ipac_irq, -}; - -static struct card_ops diva_ipac_pci_ops = { - .init = diva_ipac_pci_init, - .reset = diva_ipac_pci_reset, - .release = diva_ipac_pci_release, - .irq_func = diva_ipac_pci_irq, -}; - -static struct card_ops diva_ipacx_pci_ops = { - .init = diva_ipacx_pci_init, - .reset = diva_ipacx_pci_reset, - .release = diva_ipac_pci_release, - .irq_func = diva_ipacx_pci_irq, -}; - -static int __init -diva_ipac_probe(struct IsdnCardState *cs) -{ - u8 val; - - // request_io - val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR, - cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID); - printk(KERN_INFO "Diva: IPAC version %x\n", val); - return (val == 1 || val == 2); -} - -static int __init -diva_ipac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->subtyp = DIVA_IPAC_ISA; - cs->irq = card->para[0]; - cs->hw.diva.cfg_reg = card->para[1]; - cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA; - cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR; - printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", - "IPAC ISA", cs->hw.diva.cfg_reg, cs->irq); - if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn")) - goto err; - diva_ipac_isa_reset(cs); - cs->card_ops = &diva_ipac_isa_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -diva_isac_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->subtyp = DIVA_ISA; - cs->irq = card->para[0]; - cs->hw.diva.cfg_reg = card->para[1]; - cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL; - cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA; - cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA; - cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR; - cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR; - printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", - "ISA", cs->hw.diva.cfg_reg, cs->irq); - if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn")) - goto err; - diva_reset(cs); - init_timer(&cs->hw.diva.tl); - cs->hw.diva.tl.function = (void *) diva_led_handler; - cs->hw.diva.tl.data = (long) cs; - cs->card_ops = &diva_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -diva_isa_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - int is_ipac; - cs->hw.diva.cfg_reg = card->para[1]; - if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 8, "diva isdn")) - return -EBUSY; - - is_ipac = diva_ipac_probe(cs); - hisax_release_resources(cs); - - if (is_ipac) - return diva_ipac_isa_probe(cs, card); - else - return diva_isac_isa_probe(cs, card); + if (blink) { + init_timer(&cs->hw.diva.tl); + cs->hw.diva.tl.expires = jiffies + ((blink * HZ) / 1000); + add_timer(&cs->hw.diva.tl); + } } -static int __init -diva_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +static int +Diva_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - if (pci_enable_device(pdev)) - goto err; + u_int *ireg; + u_long flags; - cs->subtyp = DIVA_PCI; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.diva.cfg_reg = pci_resource_start(pdev, 2); - cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL; - cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA; - cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA; - cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR; - cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR; - printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", - "PCI", cs->hw.diva.cfg_reg, cs->irq); - printk(KERN_INFO "Diva: %s space at %#lx\n", - "PCI", cs->hw.diva.pci_cfg); - if (!request_io(&cs->rs, cs->hw.diva.cfg_reg, 32, "diva isdn")) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -diva_ipac_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = DIVA_IPAC_PCI; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.diva.pci_cfg = (unsigned long)request_mmio( - &cs->rs, pci_resource_start(pdev, 0), 4096, "diva"); - cs->hw.diva.cfg_reg = (unsigned long)request_mmio( - &cs->rs, pci_resource_start(pdev, 1), 4096, "diva"); - printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", - "IPAC PCI", cs->hw.diva.cfg_reg, cs->irq); - printk(KERN_INFO "Diva: %s space at %#lx\n", - "IPAC PCI", cs->hw.diva.pci_cfg); - diva_ipac_pci_reset(cs); - cs->card_ops = &diva_ipac_pci_ops; - if (ipac_setup(cs, &mem_ipac_dc_ops, &mem_ipac_bc_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -diva_ipacx_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = DIVA_IPACX_PCI; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - printk(KERN_INFO "Diva: %s card configured at %#lx IRQ %d\n", - "IPACX PCI", cs->hw.diva.cfg_reg, cs->irq); - printk(KERN_INFO "Diva: %s space at %#lx\n", - "IPACX PCI", cs->hw.diva.pci_cfg); - diva_ipacx_pci_reset(cs); - cs->card_ops = &diva_ipacx_pci_ops; - if (ipacx_setup(cs, &ipacx_dc_ops, &ipacx_bc_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_diva(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_diva(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + reset_diva(cs); + if (cs->subtyp == DIVA_IPACX_PCI) { + ireg = (unsigned int *)cs->hw.diva.pci_cfg; + *ireg = PITA_INT0_ENABLE; + init_ipacx(cs, 3); // init chip and enable interrupts + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + } + if (cs->subtyp == DIVA_IPAC_PCI) { + ireg = (unsigned int *)cs->hw.diva.pci_cfg; + *ireg = PITA_INT0_ENABLE; + } + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + case (MDL_REMOVE | REQUEST): + cs->hw.diva.status = 0; + break; + case (MDL_ASSIGN | REQUEST): + cs->hw.diva.status |= DIVA_ASSIGN; + break; + case MDL_INFO_SETUP: + if ((long)arg) + cs->hw.diva.status |= 0x0200; + else + cs->hw.diva.status |= 0x0100; + break; + case MDL_INFO_CONN: + if ((long)arg) + cs->hw.diva.status |= 0x2000; + else + cs->hw.diva.status |= 0x1000; + break; + case MDL_INFO_REL: + if ((long)arg) { + cs->hw.diva.status &= ~0x2000; + cs->hw.diva.status &= ~0x0200; + } else { + cs->hw.diva.status &= ~0x1000; + cs->hw.diva.status &= ~0x0100; + } + break; + } + if ((cs->subtyp != DIVA_IPAC_ISA) && + (cs->subtyp != DIVA_IPAC_PCI) && + (cs->subtyp != DIVA_IPACX_PCI)) { + spin_lock_irqsave(&cs->lock, flags); + diva_led_handler(cs); + spin_unlock_irqrestore(&cs->lock, flags); + } + return(0); } static struct pci_dev *dev_diva __initdata = NULL; static struct pci_dev *dev_diva_u __initdata = NULL; static struct pci_dev *dev_diva201 __initdata = NULL; +static struct pci_dev *dev_diva202 __initdata = NULL; + #ifdef __ISAPNP__ static struct isapnp_device_id diva_ids[] __initdata = { { ISAPNP_VENDOR('G', 'D', 'I'), ISAPNP_FUNCTION(0x51), @@ -700,99 +916,268 @@ { 0, } }; -static struct isapnp_device_id *pdev = &diva_ids[0]; +static struct isapnp_device_id *ipid __initdata = &diva_ids[0]; static struct pnp_card *pnp_c __devinitdata = NULL; #endif + int __init setup_diva(struct IsdnCard *card) { + int bytecnt = 8; + u_char val; + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, Diva_revision); printk(KERN_INFO "HiSax: Eicon.Diehl Diva driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_DIEHLDIVA) + return(0); + cs->hw.diva.status = 0; if (card->para[1]) { - if (diva_isa_probe(card->cs, card) < 0) - return 0; - return 1; - - } + cs->hw.diva.ctrl_reg = 0; + cs->hw.diva.cfg_reg = card->para[1]; + val = readreg(cs->hw.diva.cfg_reg + DIVA_IPAC_ADR, + cs->hw.diva.cfg_reg + DIVA_IPAC_DATA, IPAC_ID); + printk(KERN_INFO "Diva: IPAC version %x\n", val); + if ((val == 1) || (val==2)) { + cs->subtyp = DIVA_IPAC_ISA; + cs->hw.diva.ctrl = 0; + cs->hw.diva.isac = card->para[1] + DIVA_IPAC_DATA; + cs->hw.diva.hscx = card->para[1] + DIVA_IPAC_DATA; + cs->hw.diva.isac_adr = card->para[1] + DIVA_IPAC_ADR; + cs->hw.diva.hscx_adr = card->para[1] + DIVA_IPAC_ADR; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + } else { + cs->subtyp = DIVA_ISA; + cs->hw.diva.ctrl = card->para[1] + DIVA_ISA_CTRL; + cs->hw.diva.isac = card->para[1] + DIVA_ISA_ISAC_DATA; + cs->hw.diva.hscx = card->para[1] + DIVA_HSCX_DATA; + cs->hw.diva.isac_adr = card->para[1] + DIVA_ISA_ISAC_ADR; + cs->hw.diva.hscx_adr = card->para[1] + DIVA_HSCX_ADR; + } + cs->irq = card->para[0]; + } else { #ifdef __ISAPNP__ - if (isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; - - while(pdev->card_vendor) { - if ((pb = pnp_find_card(pdev->card_vendor, - pdev->card_device, pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - pdev->vendor, - pdev->function, - pd))) { - printk(KERN_INFO "HiSax: %s detected\n", - (char *)pdev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "Diva PnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "Diva PnP: activate failed\n"); - pnp_device_detach(pd); - return 0; - } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { - printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); - return(0); - } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); - if (pdev->function == ISAPNP_FUNCTION(0xA1)) { - if (diva_ipac_isa_probe(card->cs, card)) - return 0; - return 1; + if (isapnp_present()) { + struct pnp_dev *pnp_d; + while(ipid->card_vendor) { + if ((pnp_c = pnp_find_card(ipid->card_vendor, + ipid->card_device, pnp_c))) { + pnp_d = NULL; + if ((pnp_d = pnp_find_dev(pnp_c, + ipid->vendor, ipid->function, pnp_d))) { + int err; + + printk(KERN_INFO "HiSax: %s detected\n", + (char *)ipid->driver_data); + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); + } + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[0] = pnp_irq(pnp_d, 0); + if (!card->para[0] || !card->para[1]) { + printk(KERN_ERR "Diva PnP:some resources are missing %ld/%lx\n", + card->para[0], card->para[1]); + pnp_disable_dev(pnp_d); + return(0); + } + cs->hw.diva.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + if (ipid->function == ISAPNP_FUNCTION(0xA1)) { + cs->subtyp = DIVA_IPAC_ISA; + cs->hw.diva.ctrl = 0; + cs->hw.diva.isac = + card->para[1] + DIVA_IPAC_DATA; + cs->hw.diva.hscx = + card->para[1] + DIVA_IPAC_DATA; + cs->hw.diva.isac_adr = + card->para[1] + DIVA_IPAC_ADR; + cs->hw.diva.hscx_adr = + card->para[1] + DIVA_IPAC_ADR; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + } else { + cs->subtyp = DIVA_ISA; + cs->hw.diva.ctrl = + card->para[1] + DIVA_ISA_CTRL; + cs->hw.diva.isac = + card->para[1] + DIVA_ISA_ISAC_DATA; + cs->hw.diva.hscx = + card->para[1] + DIVA_HSCX_DATA; + cs->hw.diva.isac_adr = + card->para[1] + DIVA_ISA_ISAC_ADR; + cs->hw.diva.hscx_adr = + card->para[1] + DIVA_HSCX_ADR; + } + goto ready; } else { - if (diva_isac_isa_probe(card->cs, card)) - return 0; - return 1; + printk(KERN_ERR "Diva PnP: PnP error card found, no device\n"); + return(0); } - } else { - printk(KERN_ERR "Diva PnP: PnP error card found, no device\n"); - return(0); } - pdev++; + ipid++; pnp_c=NULL; } - if (!pdev->card_vendor) { + if (!ipid->card_vendor) { printk(KERN_INFO "Diva PnP: no ISAPnP card found\n"); } } - } #endif -#ifdef CONFIG_PCI - if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, - PCI_DEVICE_ID_EICON_DIVA20, - dev_diva))) { - if (diva_pci_probe(card->cs, dev_diva)) - return 0; - return 1; - } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON, - PCI_DEVICE_ID_EICON_DIVA20_U, - dev_diva_u))) { - if (diva_pci_probe(card->cs, dev_diva_u)) - return 0; - return 1; - } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON, - PCI_DEVICE_ID_EICON_DIVA201, - dev_diva201))) { - if (diva_ipac_pci_probe(card->cs, dev_diva201)) - return 0; - return 1; - } - printk(KERN_WARNING "Diva: No PCI card found\n"); +#if CONFIG_PCI + cs->subtyp = 0; + if ((dev_diva = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_DIVA20, dev_diva))) { + if (pci_enable_device(dev_diva)) + return(0); + cs->subtyp = DIVA_PCI; + cs->irq = dev_diva->irq; + cs->hw.diva.cfg_reg = pci_resource_start(dev_diva, 2); + } else if ((dev_diva_u = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_DIVA20_U, dev_diva_u))) { + if (pci_enable_device(dev_diva_u)) + return(0); + cs->subtyp = DIVA_PCI; + cs->irq = dev_diva_u->irq; + cs->hw.diva.cfg_reg = pci_resource_start(dev_diva_u, 2); + } else if ((dev_diva201 = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_DIVA201, dev_diva201))) { + if (pci_enable_device(dev_diva201)) + return(0); + cs->subtyp = DIVA_IPAC_PCI; + cs->irq = dev_diva201->irq; + cs->hw.diva.pci_cfg = + (ulong) ioremap(pci_resource_start(dev_diva201, 0), 4096); + cs->hw.diva.cfg_reg = + (ulong) ioremap(pci_resource_start(dev_diva201, 1), 4096); + } else if ((dev_diva202 = pci_find_device(PCI_VENDOR_ID_EICON, + PCI_DEVICE_ID_EICON_DIVA202, dev_diva202))) { + if (pci_enable_device(dev_diva202)) + return(0); + cs->subtyp = DIVA_IPACX_PCI; + cs->irq = dev_diva202->irq; + cs->hw.diva.pci_cfg = + (ulong) ioremap(pci_resource_start(dev_diva202, 0), 4096); + cs->hw.diva.cfg_reg = + (ulong) ioremap(pci_resource_start(dev_diva202, 1), 4096); + } else { + printk(KERN_WARNING "Diva: No PCI card found\n"); + return(0); + } + + if (!cs->irq) { + printk(KERN_WARNING "Diva: No IRQ for PCI card found\n"); + return(0); + } + + if (!cs->hw.diva.cfg_reg) { + printk(KERN_WARNING "Diva: No IO-Adr for PCI card found\n"); + return(0); + } + cs->irq_flags |= SA_SHIRQ; +#else + printk(KERN_WARNING "Diva: cfgreg 0 and NO_PCI_BIOS\n"); + printk(KERN_WARNING "Diva: unable to config DIVA PCI\n"); + return (0); #endif /* CONFIG_PCI */ - return 0; + if ((cs->subtyp == DIVA_IPAC_PCI) || + (cs->subtyp == DIVA_IPACX_PCI) ) { + cs->hw.diva.ctrl = 0; + cs->hw.diva.isac = 0; + cs->hw.diva.hscx = 0; + cs->hw.diva.isac_adr = 0; + cs->hw.diva.hscx_adr = 0; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + bytecnt = 0; + } else { + cs->hw.diva.ctrl = cs->hw.diva.cfg_reg + DIVA_PCI_CTRL; + cs->hw.diva.isac = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_DATA; + cs->hw.diva.hscx = cs->hw.diva.cfg_reg + DIVA_HSCX_DATA; + cs->hw.diva.isac_adr = cs->hw.diva.cfg_reg + DIVA_PCI_ISAC_ADR; + cs->hw.diva.hscx_adr = cs->hw.diva.cfg_reg + DIVA_HSCX_ADR; + bytecnt = 32; + } + } +ready: + printk(KERN_INFO + "Diva: %s card configured at %#lx IRQ %d\n", + (cs->subtyp == DIVA_PCI) ? "PCI" : + (cs->subtyp == DIVA_ISA) ? "ISA" : + (cs->subtyp == DIVA_IPAC_ISA) ? "IPAC ISA" : + (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI", + cs->hw.diva.cfg_reg, cs->irq); + if ((cs->subtyp == DIVA_IPAC_PCI) || + (cs->subtyp == DIVA_IPACX_PCI) || + (cs->subtyp == DIVA_PCI) ) + printk(KERN_INFO "Diva: %s space at %#lx\n", + (cs->subtyp == DIVA_PCI) ? "PCI" : + (cs->subtyp == DIVA_IPAC_PCI) ? "IPAC PCI" : "IPACX PCI", + cs->hw.diva.pci_cfg); + if ((cs->subtyp != DIVA_IPAC_PCI) && + (cs->subtyp != DIVA_IPACX_PCI) ) { + if (!request_region(cs->hw.diva.cfg_reg, bytecnt, "diva isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %lx-%lx already in use\n", + CardType[card->typ], + cs->hw.diva.cfg_reg, + cs->hw.diva.cfg_reg + bytecnt); + return (0); + } + } + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &Diva_card_msg; + setup_isac(cs); + if (cs->subtyp == DIVA_IPAC_ISA) { + cs->readisac = &ReadISAC_IPAC; + cs->writeisac = &WriteISAC_IPAC; + cs->readisacfifo = &ReadISACfifo_IPAC; + cs->writeisacfifo = &WriteISACfifo_IPAC; + cs->irq_func = &diva_irq_ipac_isa; + val = readreg(cs->hw.diva.isac_adr, cs->hw.diva.isac, IPAC_ID); + printk(KERN_INFO "Diva: IPAC version %x\n", val); + } else if (cs->subtyp == DIVA_IPAC_PCI) { + cs->readisac = &MemReadISAC_IPAC; + cs->writeisac = &MemWriteISAC_IPAC; + cs->readisacfifo = &MemReadISACfifo_IPAC; + cs->writeisacfifo = &MemWriteISACfifo_IPAC; + cs->BC_Read_Reg = &MemReadHSCX; + cs->BC_Write_Reg = &MemWriteHSCX; + cs->BC_Send_Data = &Memhscx_fill_fifo; + cs->irq_func = &diva_irq_ipac_pci; + val = memreadreg(cs->hw.diva.cfg_reg, IPAC_ID); + printk(KERN_INFO "Diva: IPAC version %x\n", val); + } else if (cs->subtyp == DIVA_IPACX_PCI) { + cs->readisac = &MemReadISAC_IPACX; + cs->writeisac = &MemWriteISAC_IPACX; + cs->readisacfifo = &MemReadISACfifo_IPACX; + cs->writeisacfifo = &MemWriteISACfifo_IPACX; + cs->BC_Read_Reg = &MemReadHSCX_IPACX; + cs->BC_Write_Reg = &MemWriteHSCX_IPACX; + cs->BC_Send_Data = 0; // function located in ipacx module + cs->irq_func = &diva_irq_ipacx_pci; + printk(KERN_INFO "Diva: IPACX Design Id: %x\n", + MemReadISAC_IPACX(cs, IPACX_ID) &0x3F); + } else { /* DIVA 2.0 */ + cs->hw.diva.tl.function = (void *) diva_led_handler; + cs->hw.diva.tl.data = (long) cs; + init_timer(&cs->hw.diva.tl); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->irq_func = &diva_interrupt; + ISACVersion(cs, "Diva:"); + if (HscxVersion(cs, "Diva:")) { + printk(KERN_WARNING + "Diva: wrong HSCX versions check IO address\n"); + release_io_diva(cs); + return (0); + } + } + return (1); } diff -Nru a/drivers/isdn/hisax/elsa.c b/drivers/isdn/hisax/elsa.c --- a/drivers/isdn/hisax/elsa.c Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/elsa.c Thu Feb 19 23:44:23 2004 @@ -1,4 +1,4 @@ -/* $Id: elsa.c,v 2.26.6.6 2001/09/23 22:24:47 kai Exp $ +/* $Id: elsa.c,v 2.32.2.4 2004/01/24 20:47:21 keil Exp $ * * low level stuff for Elsa isdn cards * @@ -32,9 +32,8 @@ #include extern const char *CardType[]; -static spinlock_t elsa_lock = SPIN_LOCK_UNLOCKED; -const char *Elsa_revision = "$Revision: 2.26.6.6 $"; +const char *Elsa_revision = "$Revision: 2.32.2.4 $"; const char *Elsa_Types[] = {"None", "PC", "PCC-8", "PCC-16", "PCF", "PCF-Pro", "PCMCIA", "QS 1000", "QS 3000", "Microlink PCI", "QS 3000 PCI", @@ -106,6 +105,7 @@ /* Status Flags */ #define ELSA_TIMER_AKTIV 1 #define ELSA_BAD_PWR 2 +#define ELSA_ASSIGN 4 #define RS_ISR_PASS_LIMIT 256 #define _INLINE_ inline @@ -141,163 +141,123 @@ #include "elsa_ser.c" #endif /* ARCOFI_USE */ -static inline u8 -readreg(struct IsdnCardState *cs, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&elsa_lock, flags); - byteout(cs->hw.elsa.ale, off); + byteout(ale, off); ret = bytein(adr); - spin_unlock_irqrestore(&elsa_lock, flags); - return ret; + return (ret); } static inline void -writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; - - spin_lock_irqsave(&elsa_lock, flags); - byteout(cs->hw.elsa.ale, off); - byteout(adr, data); - spin_unlock_irqrestore(&elsa_lock, flags); + byteout(ale, off); + insb(adr, data, size); } + static inline void -readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { - byteout(cs->hw.elsa.ale, off); - insb(adr, data, size); + byteout(ale, off); + byteout(adr, data); } static inline void -writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - byteout(cs->hw.elsa.ale, off); + byteout(ale, off); outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.elsa.isac, offset); + return (readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.elsa.isac, offset, value); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - readfifo(cs, cs->hw.elsa.isac, 0, data, size); + readfifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs, cs->hw.elsa.isac, 0, data, size); + writefifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0)); + return (readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset+0x80)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0), value); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, offset|0x80, value); } static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs, cs->hw.elsa.hscx, hscx ? 0x40 : 0, data, size); + readfifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0x80, data, size); } static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - writefifo(cs, cs->hw.elsa.hscx, hscx ? 0x40 : 0, data, size); -} - -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static inline u8 -ipac_read(struct IsdnCardState *cs, u8 offset) -{ - return readreg(cs, cs->hw.elsa.isac, offset); -} - -static inline void -ipac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - writereg(cs, cs->hw.elsa.isac, offset, value); + writefifo(cs->hw.elsa.ale, cs->hw.elsa.isac, 0x80, data, size); } -static inline void -ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - readfifo(cs, cs->hw.elsa.isac, offset, data, size); + return (readreg(cs->hw.elsa.ale, + cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0))); } -static inline void -ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - writefifo(cs, cs->hw.elsa.isac, offset, data, size); + writereg(cs->hw.elsa.ale, + cs->hw.elsa.hscx, offset + (hscx ? 0x40 : 0), value); } -/* This will generate ipac_dc_ops and ipac_bc_ops using the functions - * above */ - -BUILD_IPAC_OPS(ipac); - -static inline u8 -readitac(struct IsdnCardState *cs, u8 off) +static inline u_char +readitac(struct IsdnCardState *cs, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&elsa_lock, flags); byteout(cs->hw.elsa.ale, off); ret = bytein(cs->hw.elsa.itac); - spin_unlock_irqrestore(&elsa_lock, flags); - return ret; + return (ret); } static inline void -writeitac(struct IsdnCardState *cs, u8 off, u8 data) +writeitac(struct IsdnCardState *cs, u_char off, u_char data) { - unsigned long flags; - - spin_lock_irqsave(&elsa_lock, flags); byteout(cs->hw.elsa.ale, off); byteout(cs->hw.elsa.itac, data); - spin_unlock_irqrestore(&elsa_lock, flags); } static inline int TimerRun(struct IsdnCardState *cs) { - register u8 v; + register u_char v; v = bytein(cs->hw.elsa.cfg); if ((cs->subtyp == ELSA_QS1000) || (cs->subtyp == ELSA_QS3000)) @@ -306,12 +266,30 @@ return (v & ELSA_TIMER_RUN_PCC8); return (v & ELSA_TIMER_RUN); } +/* + * fast interrupt HSCX stuff goes here + */ + +#define READHSCX(cs, nr, reg) readreg(cs->hw.elsa.ale, \ + cs->hw.elsa.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.elsa.ale, \ + cs->hw.elsa.hscx, reg + (nr ? 0x40 : 0), data) + +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.elsa.ale, \ + cs->hw.elsa.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.elsa.ale, \ + cs->hw.elsa.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" static irqreturn_t elsa_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; + u_long flags; + u_char val; + int icnt=5; if ((cs->typ == ISDN_CTYPE_ELSA_PCMCIA) && (*cs->busy_flag == 1)) { /* The card tends to generate interrupts while being removed @@ -319,19 +297,45 @@ printk(KERN_WARNING "Elsa: card not available!\n"); return IRQ_NONE; } + spin_lock_irqsave(&cs->lock, flags); #if ARCOFI_USE if (cs->hw.elsa.MFlag) { val = serial_inp(cs, UART_IIR); if (!(val & UART_IIR_NO_INT)) { debugl1(cs,"IIR %02x", val); - spin_lock(&cs->lock); rs_interrupt_elsa(intno, cs); - spin_unlock(&cs->lock); } } #endif - hscxisac_irq(intno, dev_id, regs); - + val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40); + Start_HSCX: + if (val) { + hscx_int_main(cs, val); + } + val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA); + Start_ISAC: + if (val) { + isac_interrupt(cs, val); + } + val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40); + if (val && icnt) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + icnt--; + goto Start_HSCX; + } + val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA); + if (val && icnt) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + icnt--; + goto Start_ISAC; + } + if (!icnt) + printk(KERN_WARNING"ELSA IRQ LOOP\n"); + writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0xFF); if (cs->hw.elsa.status & ELSA_TIMER_AKTIV) { if (!TimerRun(cs)) { /* Timer Restart */ @@ -351,6 +355,10 @@ #endif if (cs->hw.elsa.trig) byteout(cs->hw.elsa.trig, 0x00); + writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK, 0x0); + writereg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_MASK + 0x40, 0x0); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_MASK, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } @@ -358,35 +366,70 @@ elsa_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; + u_long flags; + u_char ista,val; + int icnt=5; - if (!cs) { - printk(KERN_WARNING "Elsa: Spurious interrupt!\n"); - return IRQ_NONE; - } + spin_lock_irqsave(&cs->lock, flags); if (cs->subtyp == ELSA_QS1000PCI || cs->subtyp == ELSA_QS3000PCI) { val = bytein(cs->hw.elsa.cfg + 0x4c); /* PCI IRQ */ - if (!test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags) && - !(val & ELSA_PCI_IRQ_MASK)) + if (!(val & ELSA_PCI_IRQ_MASK)) { + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_NONE; + } } #if ARCOFI_USE if (cs->hw.elsa.MFlag) { val = serial_inp(cs, UART_IIR); if (!(val & UART_IIR_NO_INT)) { debugl1(cs,"IIR %02x", val); - spin_lock(&cs->lock); rs_interrupt_elsa(intno, cs); - spin_unlock(&cs->lock); } } #endif - return ipac_irq(intno, dev_id, regs); + ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA); +Start_IPAC: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = readreg(cs->hw.elsa.ale, cs->hw.elsa.hscx, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) + hscx_int_main(cs, val); + } + if (ista & 0x20) { + val = 0xfe & readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, ISAC_ISTA + 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPAC; + } + if (!icnt) + printk(KERN_WARNING "ELSA IRQ LOOP\n"); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xFF); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xC0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; } -static void -elsa_release(struct IsdnCardState *cs) +void +release_io_elsa(struct IsdnCardState *cs) { + int bytecnt = 8; + del_timer(&cs->hw.elsa.tl); #if ARCOFI_USE clear_arcofi(cs); @@ -395,28 +438,33 @@ byteout(cs->hw.elsa.ctrl, 0); /* LEDs Out */ if (cs->subtyp == ELSA_QS1000PCI) { byteout(cs->hw.elsa.cfg + 0x4c, 0x01); /* disable IRQ */ - writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff); + bytecnt = 2; + release_region(cs->hw.elsa.cfg, 0x80); } if (cs->subtyp == ELSA_QS3000PCI) { byteout(cs->hw.elsa.cfg + 0x4c, 0x03); /* disable ELSA PCI IRQ */ - writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff); + release_region(cs->hw.elsa.cfg, 0x80); } if (cs->subtyp == ELSA_PCMCIA_IPAC) { - writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff); } -#if ARCOFI_USE if ((cs->subtyp == ELSA_PCFPRO) || (cs->subtyp == ELSA_QS3000) || (cs->subtyp == ELSA_PCF) || (cs->subtyp == ELSA_QS3000PCI)) { + bytecnt = 16; +#if ARCOFI_USE release_modem(cs); - } #endif - hisax_release_resources(cs); + } + if (cs->hw.elsa.base) + release_region(cs->hw.elsa.base, bytecnt); } -static int -elsa_reset(struct IsdnCardState *cs) +static void +reset_elsa(struct IsdnCardState *cs) { if (cs->hw.elsa.timer) { /* Wait 1 Timer */ @@ -437,28 +485,25 @@ byteout(cs->hw.elsa.trig, 0xff); } if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) { - writereg(cs, cs->hw.elsa.isac, IPAC_POTA2, 0x20); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - writereg(cs, cs->hw.elsa.isac, IPAC_POTA2, 0x00); - set_current_state(TASK_UNINTERRUPTIBLE); - writereg(cs, cs->hw.elsa.isac, IPAC_MASK, 0xc0); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x20); + mdelay(10); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_POTA2, 0x00); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_MASK, 0xc0); + mdelay(10); if (cs->subtyp != ELSA_PCMCIA_IPAC) { - writereg(cs, cs->hw.elsa.isac, IPAC_ACFG, 0x0); - writereg(cs, cs->hw.elsa.isac, IPAC_AOE, 0x3c); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x0); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0x3c); } else { - writereg(cs, cs->hw.elsa.isac, IPAC_PCFG, 0x10); - writereg(cs, cs->hw.elsa.isac, IPAC_ACFG, 0x4); - writereg(cs, cs->hw.elsa.isac, IPAC_AOE, 0xf8); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_PCFG, 0x10); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ACFG, 0x4); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_AOE, 0xf8); } - writereg(cs, cs->hw.elsa.isac, IPAC_ATX, 0xff); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, 0xff); if (cs->subtyp == ELSA_QS1000PCI) byteout(cs->hw.elsa.cfg + 0x4c, 0x41); /* enable ELSA PCI IRQ */ else if (cs->subtyp == ELSA_QS3000PCI) byteout(cs->hw.elsa.cfg + 0x4c, 0x43); /* enable ELSA PCI IRQ */ } - return 0; } #if ARCOFI_USE @@ -476,7 +521,7 @@ int arcofi_present = 0; char tmp[40]; char *t; - u8 *p; + u_char *p; if (!cs->dc.isac.mon_tx) if (!(cs->dc.isac.mon_tx=kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { @@ -525,14 +570,28 @@ "Elsa: %s detected modem at 0x%lx\n", Elsa_Types[cs->subtyp], cs->hw.elsa.base+8); - request_io(&cs->rs, cs->hw.elsa.base+8, 8, "elsa isdn modem"); + release_region(cs->hw.elsa.base, 8); + if (!request_region(cs->hw.elsa.base, 16, "elsa isdn modem")) { + printk(KERN_WARNING + "HiSax: %s config port %lx-%lx already in use\n", + Elsa_Types[cs->subtyp], + cs->hw.elsa.base + 8, + cs->hw.elsa.base + 16); + } } else if (cs->subtyp==ELSA_PCC16) { cs->subtyp = ELSA_PCF; printk(KERN_INFO "Elsa: %s detected modem at 0x%lx\n", Elsa_Types[cs->subtyp], cs->hw.elsa.base+8); - request_io(&cs->rs, cs->hw.elsa.base+8, 8, "elsa isdn modem"); + release_region(cs->hw.elsa.base, 8); + if (!request_region(cs->hw.elsa.base, 16, "elsa isdn modem")) { + printk(KERN_WARNING + "HiSax: %s config port %lx-%lx already in use\n", + Elsa_Types[cs->subtyp], + cs->hw.elsa.base + 8, + cs->hw.elsa.base + 16); + } } else printk(KERN_INFO "Elsa: %s detected modem at 0x%lx\n", @@ -553,15 +612,8 @@ if (cs->subtyp == ELSA_PCMCIA || cs->subtyp == ELSA_PCMCIA_IPAC) return; - - if (cs->typ == ISDN_CTYPE_ELSA) { - int pwr = bytein(cs->hw.elsa.ale); - if (pwr & 0x08) - cs->hw.elsa.status |= ELSA_BAD_PWR; - else - cs->hw.elsa.status &= ~ELSA_BAD_PWR; - } - if (cs->status & 0x0001) + del_timer(&cs->hw.elsa.tl); + if (cs->hw.elsa.status & ELSA_ASSIGN) cs->hw.elsa.ctrl_reg |= ELSA_STAT_LED; else if (cs->hw.elsa.status & ELSA_BAD_PWR) cs->hw.elsa.ctrl_reg &= ~ELSA_STAT_LED; @@ -569,9 +621,9 @@ cs->hw.elsa.ctrl_reg ^= ELSA_STAT_LED; blink = 250; } - if (cs->status & 0xf000) + if (cs->hw.elsa.status & 0xf000) cs->hw.elsa.ctrl_reg |= ELSA_LINE_LED; - else if (cs->status & 0x0f00) { + else if (cs->hw.elsa.status & 0x0f00) { cs->hw.elsa.ctrl_reg ^= ELSA_LINE_LED; blink = 500; } else @@ -579,159 +631,148 @@ if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) { - u8 led = 0xff; + u_char led = 0xff; if (cs->hw.elsa.ctrl_reg & ELSA_LINE_LED) led ^= ELSA_IPAC_LINE_LED; if (cs->hw.elsa.ctrl_reg & ELSA_STAT_LED) led ^= ELSA_IPAC_STAT_LED; - writereg(cs, cs->hw.elsa.isac, IPAC_ATX, led); + writereg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ATX, led); } else byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); - - if (blink) - mod_timer(&cs->hw.elsa.tl, jiffies + (blink * HZ) / 1000); -} - -#if ARCOFI_USE -static void -elsa_aux_ind(struct IsdnCardState *cs, void *arg) -{ - if (cs->hw.elsa.MFlag) { - int len; - u8 *msg; - - if (!arg) - return; - msg = arg; - len = *msg; - msg++; - modem_write_cmd(cs, msg, len); - } -} -#else -#define elsa_aux_ind NULL -#endif - -static void -elsa_init(struct IsdnCardState *cs) -{ - if (cs->subtyp == ELSA_QS1000 || cs->subtyp == ELSA_QS3000) - byteout(cs->hw.elsa.timer, 0); - - if (cs->hw.elsa.trig) - byteout(cs->hw.elsa.trig, 0xff); - - inithscxisac(cs); + if (blink) { + init_timer(&cs->hw.elsa.tl); + cs->hw.elsa.tl.expires = jiffies + ((blink * HZ) / 1000); + add_timer(&cs->hw.elsa.tl); + } } -static void -elsa_ipac_init(struct IsdnCardState *cs) +static int +Elsa_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - if (cs->hw.elsa.trig) - byteout(cs->hw.elsa.trig, 0xff); - - ipac_init(cs); -} + int ret = 0; + u_long flags; -static void -elsa_test(struct IsdnCardState *cs) -{ - if ((cs->subtyp == ELSA_PCMCIA) || - (cs->subtyp == ELSA_PCMCIA_IPAC) || - (cs->subtyp == ELSA_QS1000PCI)) { - return; - } - if (cs->subtyp != ELSA_QS3000PCI) { - cs->hw.elsa.counter = 0; - cs->hw.elsa.ctrl_reg |= ELSA_ENA_TIMER_INT; - cs->hw.elsa.status |= ELSA_TIMER_AKTIV; - byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); - byteout(cs->hw.elsa.timer, 0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((110*HZ)/1000); - cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT; - byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); - cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV; - printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n", - cs->hw.elsa.counter); - if ((cs->hw.elsa.counter > 10) && - (cs->hw.elsa.counter < 16)) { - printk(KERN_INFO "Elsa: timer and irq OK\n"); - } else { - printk(KERN_WARNING - "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n", - cs->hw.elsa.counter, cs->irq); - } - } + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_elsa(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_elsa(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + cs->debug |= L1_DEB_IPAC; + reset_elsa(cs); + inithscxisac(cs, 1); + if ((cs->subtyp == ELSA_QS1000) || + (cs->subtyp == ELSA_QS3000)) + { + byteout(cs->hw.elsa.timer, 0); + } + if (cs->hw.elsa.trig) + byteout(cs->hw.elsa.trig, 0xff); + inithscxisac(cs, 2); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + if ((cs->subtyp == ELSA_PCMCIA) || + (cs->subtyp == ELSA_PCMCIA_IPAC) || + (cs->subtyp == ELSA_QS1000PCI)) { + return(0); + } else if (cs->subtyp == ELSA_QS3000PCI) { + ret = 0; + } else { + spin_lock_irqsave(&cs->lock, flags); + cs->hw.elsa.counter = 0; + cs->hw.elsa.ctrl_reg |= ELSA_ENA_TIMER_INT; + cs->hw.elsa.status |= ELSA_TIMER_AKTIV; + byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); + byteout(cs->hw.elsa.timer, 0); + spin_unlock_irqrestore(&cs->lock, flags); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((110*HZ)/1000); + spin_lock_irqsave(&cs->lock, flags); + cs->hw.elsa.ctrl_reg &= ~ELSA_ENA_TIMER_INT; + byteout(cs->hw.elsa.ctrl, cs->hw.elsa.ctrl_reg); + cs->hw.elsa.status &= ~ELSA_TIMER_AKTIV; + spin_unlock_irqrestore(&cs->lock, flags); + printk(KERN_INFO "Elsa: %d timer tics in 110 msek\n", + cs->hw.elsa.counter); + if ((cs->hw.elsa.counter > 10) && + (cs->hw.elsa.counter < 16)) { + printk(KERN_INFO "Elsa: timer and irq OK\n"); + ret = 0; + } else { + printk(KERN_WARNING + "Elsa: timer tic problem (%d/12) maybe an IRQ(%d) conflict\n", + cs->hw.elsa.counter, cs->irq); + ret = 1; + } + } #if ARCOFI_USE - if (check_arcofi(cs)) { - init_modem(cs); - } + if (check_arcofi(cs)) { + init_modem(cs); + } #endif - elsa_led_handler(cs); -} - -static struct card_ops elsa_ops = { - .init = elsa_init, - .test = elsa_test, - .reset = elsa_reset, - .release = elsa_release, - .aux_ind = elsa_aux_ind, - .led_handler = elsa_led_handler, - .irq_func = elsa_interrupt, -}; - -static struct card_ops elsa_ipac_ops = { - .init = elsa_ipac_init, - .test = elsa_test, - .reset = elsa_reset, - .release = elsa_release, - .aux_ind = elsa_aux_ind, - .led_handler = elsa_led_handler, - .irq_func = elsa_interrupt_ipac, -}; - -static void __init -elsa_arcofi_init(struct IsdnCardState *cs) -{ + elsa_led_handler(cs); + return(ret); + case (MDL_REMOVE | REQUEST): + cs->hw.elsa.status &= 0; + break; + case (MDL_ASSIGN | REQUEST): + cs->hw.elsa.status |= ELSA_ASSIGN; + break; + case MDL_INFO_SETUP: + if ((long) arg) + cs->hw.elsa.status |= 0x0200; + else + cs->hw.elsa.status |= 0x0100; + break; + case MDL_INFO_CONN: + if ((long) arg) + cs->hw.elsa.status |= 0x2000; + else + cs->hw.elsa.status |= 0x1000; + break; + case MDL_INFO_REL: + if ((long) arg) { + cs->hw.elsa.status &= ~0x2000; + cs->hw.elsa.status &= ~0x0200; + } else { + cs->hw.elsa.status &= ~0x1000; + cs->hw.elsa.status &= ~0x0100; + } + break; #if ARCOFI_USE - init_arcofi(cs); + case CARD_AUX_IND: + if (cs->hw.elsa.MFlag) { + int len; + u_char *msg; + + if (!arg) + return(0); + msg = arg; + len = *msg; + msg++; + modem_write_cmd(cs, msg, len); + } + break; #endif -} - -static void __init -elsa_timer_init(struct IsdnCardState *cs) -{ - cs->hw.elsa.tl.function = (void *) elsa_led_handler; - cs->hw.elsa.tl.data = (long) cs; - init_timer(&cs->hw.elsa.tl); -} - -static int __init -elsa_timer_test(struct IsdnCardState *cs) -{ - /* test timer */ - byteout(cs->hw.elsa.trig, 0xff); - byteout(cs->hw.elsa.timer, 0); - if (!TimerRun(cs)) { - byteout(cs->hw.elsa.timer, 0); /* second attempt */ - if (!TimerRun(cs)) { - printk(KERN_WARNING "Elsa: timer does not start\n"); - goto err; - } } - HZDELAY(10 * HZ / 1000); /* wait >=10 ms */ - if (TimerRun(cs)) { - printk(KERN_WARNING "Elsa: timer does not run\n"); - goto err; - } - printk(KERN_INFO "Elsa: timer OK; resetting card\n"); - return 0; - err: - return -EBUSY; + if (cs->typ == ISDN_CTYPE_ELSA) { + int pwr = bytein(cs->hw.elsa.ale); + if (pwr & 0x08) + cs->hw.elsa.status |= ELSA_BAD_PWR; + else + cs->hw.elsa.status &= ~ELSA_BAD_PWR; + } + elsa_led_handler(cs); + return(ret); } -static unsigned char __init +static unsigned char probe_elsa_adr(unsigned int adr, int typ) { int i, in1, in2, p16_1 = 0, p16_2 = 0, p8_1 = 0, p8_2 = 0, pc_1 = 0, @@ -740,13 +781,18 @@ /* In case of the elsa pcmcia card, this region is in use, reserved for us by the card manager. So we do not check it here, it would fail. */ - if (typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(adr, 8, "elsa")) { - printk(KERN_WARNING "Elsa: probing port 0x%x: in use\n", adr); - return 0; + if (typ != ISDN_CTYPE_ELSA_PCMCIA) { + if (request_region(adr, 8, "elsa card")) { + release_region(adr, 8); + } else { + printk(KERN_WARNING + "Elsa: Probing Port 0x%x: already in use\n", adr); + return (0); + } } for (i = 0; i < 16; i++) { - in1 = inb(adr + ELSA_CONFIG); /* 'toggels' at */ - in2 = inb(adr + ELSA_CONFIG); /* each access */ + in1 = inb(adr + ELSA_CONFIG); /* 'toggelt' bei */ + in2 = inb(adr + ELSA_CONFIG); /* jedem Zugriff */ p16_1 += 0x04 & in1; p16_2 += 0x04 & in2; p8_1 += 0x02 & in1; @@ -756,7 +802,6 @@ pfp_1 += 0x40 & in1; pfp_2 += 0x40 & in2; } - release_region(adr, 8); printk(KERN_INFO "Elsa: Probing IO 0x%x", adr); if (65 == ++p16_1 * ++p16_2) { printk(" PCC-16/PCF found\n"); @@ -776,227 +821,18 @@ } } -static int __init -elsa_probe(struct IsdnCardState *cs, struct IsdnCard *card) +static unsigned int +probe_elsa(struct IsdnCardState *cs) { - u8 val; - int i, bytecnt = 8; - unsigned int CARD_portlist[] = {0x160, 0x170, 0x260, 0x360, 0}; - - cs->hw.elsa.base = card->para[0]; - printk(KERN_INFO "Elsa: Microlink IO probing\n"); - if (cs->hw.elsa.base) { - cs->subtyp = probe_elsa_adr(cs->hw.elsa.base, cs->typ); - if (!cs->subtyp) { - printk(KERN_WARNING "Elsa: no Microlink at %#lx\n", - cs->hw.elsa.base); - goto err; - } - } else { - for (i = 0; CARD_portlist[i]; i++) { - cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ); - if (cs->subtyp) - cs->hw.elsa.base = CARD_portlist[i]; - break; - } - } - if (!cs->hw.elsa.base) - goto err; - - cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; - cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; - cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; - cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; - cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC; - cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; - cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; - cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; - val = bytein(cs->hw.elsa.cfg); - if (cs->subtyp == ELSA_PC) { - const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0}; - cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2]; - } else if (cs->subtyp == ELSA_PCC8) { - const u8 CARD_IrqTab[8] = {7, 3, 5, 9, 0, 0, 0, 0}; - cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4]; - } else { - const u8 CARD_IrqTab[8] = {15, 10, 15, 3, 11, 5, 11, 9}; - cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3]; - } - val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE; - if (val < 3) - val |= 8; - val += 'A' - 3; - if (val == 'B' || val == 'C') - val ^= 1; - if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G')) - val = 'C'; - printk(KERN_INFO "Elsa: %s found at %#lx Rev.:%c IRQ %d\n", - Elsa_Types[cs->subtyp], cs->hw.elsa.base, val, cs->irq); - val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD; - if (val) { - printk(KERN_WARNING "Elsa: Microlink S0 bus power bad\n"); - cs->hw.elsa.status |= ELSA_BAD_PWR; - } - switch (cs->subtyp) { - case ELSA_PCFPRO: bytecnt = 16; break; - } - if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn")) - goto err; - elsa_arcofi_init(cs); - elsa_timer_init(cs); - if (elsa_timer_test(cs)) - goto err; - elsa_reset(cs); - cs->card_ops = &elsa_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - if (cs->subtyp == ELSA_PC) { - val = readitac(cs, ITAC_SYS); - printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]); - writeitac(cs, ITAC_ISEN, 0); - writeitac(cs, ITAC_RFIE, 0); - writeitac(cs, ITAC_XFIE, 0); - writeitac(cs, ITAC_SCIE, 0); - writeitac(cs, ITAC_STIE, 0); - } - return 0; - err: - elsa_release(cs); - return -EBUSY; -} - -static int __init -elsa_qs_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - int bytecnt = 8; + int i; + unsigned int CARD_portlist[] = + {0x160, 0x170, 0x260, 0x360, 0}; - cs->irq = card->para[0]; - cs->hw.elsa.base = card->para[1]; - cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; - cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; - cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; - cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; - cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; - cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; - cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; - printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n", - Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq); - switch (cs->subtyp) { - case ELSA_QS3000: bytecnt = 16; break; - } - if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn")) - goto err; - elsa_arcofi_init(cs); - elsa_timer_init(cs); - if (elsa_timer_test(cs)) - goto err; - elsa_reset(cs); - cs->card_ops = &elsa_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - elsa_release(cs); - return -EBUSY; -} - -static int __init -elsa_qs1000_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->subtyp = ELSA_QS1000; - return elsa_qs_probe(cs, card); -} - -static int __init -elsa_qs3000_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->subtyp = ELSA_QS3000; - return elsa_qs_probe(cs, card); -} - -static int __init -elsa_pcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - u8 val; - - cs->irq = card->para[0]; - cs->hw.elsa.base = card->para[1]; - cs->hw.elsa.ale = cs->hw.elsa.base + 0; - val = readreg(cs, cs->hw.elsa.base + 2, IPAC_ID); - if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */ - cs->subtyp = ELSA_PCMCIA_IPAC; - cs->hw.elsa.isac = cs->hw.elsa.base + 2; - } else { - cs->subtyp = ELSA_PCMCIA; - cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM; - cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM; - cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; - } - cs->hw.elsa.timer = 0; - cs->hw.elsa.trig = 0; - cs->hw.elsa.ctrl = 0; - printk(KERN_INFO "Elsa: %s defined at %#lx IRQ %d\n", - Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->irq); - elsa_arcofi_init(cs); - elsa_reset(cs); - if (cs->subtyp == ELSA_PCMCIA_IPAC) { - cs->card_ops = &elsa_ipac_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - } else { - cs->card_ops = &elsa_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - } - return 0; - err: - elsa_release(cs); - return -EBUSY; -} - -static int __init -elsa_qs_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev, - int subtyp) -{ - int bytecnt = 2; - u8 pci_rev; - - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = subtyp; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.elsa.cfg = pci_resource_start(pdev, 1); - cs->hw.elsa.base = pci_resource_start(pdev, 3); - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - if (cs->hw.elsa.cfg & 0x80 && pci_rev == 1) { - printk(KERN_INFO "Elsa: PLX9050 rev1 workaround activated\n"); - __set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags); - } - cs->hw.elsa.ale = cs->hw.elsa.base; - cs->hw.elsa.isac = cs->hw.elsa.base +1; - cs->hw.elsa.hscx = cs->hw.elsa.base +1; - printk(KERN_INFO "Elsa: %s defined at %#lx/%#x IRQ %d\n", - Elsa_Types[cs->subtyp], cs->hw.elsa.base, cs->hw.elsa.cfg, - cs->irq); - switch (cs->subtyp) { - case ELSA_QS3000PCI: bytecnt = 16; break; + for (i = 0; CARD_portlist[i]; i++) { + if ((cs->subtyp = probe_elsa_adr(CARD_portlist[i], cs->typ))) + break; } - if (!request_io(&cs->rs, cs->hw.elsa.base, bytecnt, "elsa isdn")) - goto err; - if (!request_io(&cs->rs, cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) - goto err; - elsa_arcofi_init(cs); - elsa_timer_init(cs); - elsa_reset(cs); - cs->card_ops = &elsa_ipac_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - return 0; - err: - elsa_release(cs); - return -EBUSY; + return (CARD_portlist[i]); } static struct pci_dev *dev_qs1000 __devinitdata = NULL; @@ -1013,109 +849,343 @@ { 0, } }; -static struct isapnp_device_id *pdev = &elsa_ids[0]; +static struct isapnp_device_id *ipid __initdata = &elsa_ids[0]; static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __devinit setup_elsa(struct IsdnCard *card) { + int bytecnt; + u_char val; + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, Elsa_revision); printk(KERN_INFO "HiSax: Elsa driver Rev. %s\n", HiSax_getrev(tmp)); - - if (card->typ == ISDN_CTYPE_ELSA) { - if (elsa_probe(card->cs, card)) - return 0; - return 1; - } else if (card->typ == ISDN_CTYPE_ELSA_PNP) { + cs->hw.elsa.ctrl_reg = 0; + cs->hw.elsa.status = 0; + cs->hw.elsa.MFlag = 0; + cs->subtyp = 0; + if (cs->typ == ISDN_CTYPE_ELSA) { + cs->hw.elsa.base = card->para[0]; + printk(KERN_INFO "Elsa: Microlink IO probing\n"); + if (cs->hw.elsa.base) { + if (!(cs->subtyp = probe_elsa_adr(cs->hw.elsa.base, + cs->typ))) { + printk(KERN_WARNING + "Elsa: no Elsa Microlink at %#lx\n", + cs->hw.elsa.base); + return (0); + } + } else + cs->hw.elsa.base = probe_elsa(cs); + if (cs->hw.elsa.base) { + cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; + cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; + cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; + cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; + cs->hw.elsa.itac = cs->hw.elsa.base + ELSA_ITAC; + cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; + cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; + cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; + val = bytein(cs->hw.elsa.cfg); + if (cs->subtyp == ELSA_PC) { + const u_char CARD_IrqTab[8] = + {7, 3, 5, 9, 0, 0, 0, 0}; + cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PC) >> 2]; + } else if (cs->subtyp == ELSA_PCC8) { + const u_char CARD_IrqTab[8] = + {7, 3, 5, 9, 0, 0, 0, 0}; + cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX_PCC8) >> 4]; + } else { + const u_char CARD_IrqTab[8] = + {15, 10, 15, 3, 11, 5, 11, 9}; + cs->irq = CARD_IrqTab[(val & ELSA_IRQ_IDX) >> 3]; + } + val = bytein(cs->hw.elsa.ale) & ELSA_HW_RELEASE; + if (val < 3) + val |= 8; + val += 'A' - 3; + if (val == 'B' || val == 'C') + val ^= 1; + if ((cs->subtyp == ELSA_PCFPRO) && (val = 'G')) + val = 'C'; + printk(KERN_INFO + "Elsa: %s found at %#lx Rev.:%c IRQ %d\n", + Elsa_Types[cs->subtyp], + cs->hw.elsa.base, + val, cs->irq); + val = bytein(cs->hw.elsa.ale) & ELSA_S0_POWER_BAD; + if (val) { + printk(KERN_WARNING + "Elsa: Microlink S0 bus power bad\n"); + cs->hw.elsa.status |= ELSA_BAD_PWR; + } + } else { + printk(KERN_WARNING + "No Elsa Microlink found\n"); + return (0); + } + } else if (cs->typ == ISDN_CTYPE_ELSA_PNP) { #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; - - while(pdev->card_vendor) { - if ((pb = pnp_find_card(pdev->card_vendor, - pdev->card_device, - pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - pdev->vendor, - pdev->function, - pd))) { + struct pnp_dev *pnp_d; + while(ipid->card_vendor) { + if ((pnp_c = pnp_find_card(ipid->card_vendor, + ipid->card_device, pnp_c))) { + pnp_d = NULL; + if ((pnp_d = pnp_find_dev(pnp_c, + ipid->vendor, ipid->function, pnp_d))) { + int err; + printk(KERN_INFO "HiSax: %s detected\n", - (char *)pdev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "Elsa PnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - pnp_device_detach(pd); - printk(KERN_ERR "Elsa PnP: activate failed\n"); - return 0; + (char *)ipid->driver_data); + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); } - if (!pnp_port_valid(pd, 0) || - !pnp_irq_valid(pd, 0)) { + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[0] = pnp_irq(pnp_d, 0); + + if (!card->para[0] || !card->para[1]) { printk(KERN_ERR "Elsa PnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); + card->para[0], card->para[1]); + pnp_disable_dev(pnp_d); return(0); } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); - if (pdev->function == ISAPNP_FUNCTION(0x133)) { - if (elsa_qs1000_probe(card->cs, card)) - return 0; - return 1; - } else { - if (elsa_qs3000_probe(card->cs, card)) - return 0; - return 1; - } + if (ipid->function == ISAPNP_FUNCTION(0x133)) + cs->subtyp = ELSA_QS1000; + else + cs->subtyp = ELSA_QS3000; break; } else { printk(KERN_ERR "Elsa PnP: PnP error card found, no device\n"); return(0); } } - pdev++; + ipid++; pnp_c=NULL; } - if (!pdev->card_vendor) { + if (!ipid->card_vendor) { printk(KERN_INFO "Elsa PnP: no ISAPnP card found\n"); return(0); } } #endif - if (elsa_qs1000_probe(card->cs, card)) - return 0; - return 1; - - } else if (card->typ == ISDN_CTYPE_ELSA_PCMCIA) { - if (elsa_pcmcia_probe(card->cs, card)) - return 0; - return 1; - } else if (card->typ == ISDN_CTYPE_ELSA_PCI) { -#ifdef CONFIG_PCI + if (card->para[1] && card->para[0]) { + cs->hw.elsa.base = card->para[1]; + cs->irq = card->para[0]; + if (!cs->subtyp) + cs->subtyp = ELSA_QS1000; + } else { + printk(KERN_ERR "Elsa PnP: no parameter\n"); + } + cs->hw.elsa.cfg = cs->hw.elsa.base + ELSA_CONFIG; + cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE; + cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC; + cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; + cs->hw.elsa.trig = cs->hw.elsa.base + ELSA_TRIG_IRQ; + cs->hw.elsa.timer = cs->hw.elsa.base + ELSA_START_TIMER; + cs->hw.elsa.ctrl = cs->hw.elsa.base + ELSA_CONTROL; + printk(KERN_INFO + "Elsa: %s defined at %#lx IRQ %d\n", + Elsa_Types[cs->subtyp], + cs->hw.elsa.base, + cs->irq); + } else if (cs->typ == ISDN_CTYPE_ELSA_PCMCIA) { + cs->hw.elsa.base = card->para[1]; + cs->irq = card->para[0]; + val = readreg(cs->hw.elsa.base + 0, cs->hw.elsa.base + 2, IPAC_ID); + if ((val == 1) || (val == 2)) { /* IPAC version 1.1/1.2 */ + cs->subtyp = ELSA_PCMCIA_IPAC; + cs->hw.elsa.ale = cs->hw.elsa.base + 0; + cs->hw.elsa.isac = cs->hw.elsa.base + 2; + cs->hw.elsa.hscx = cs->hw.elsa.base + 2; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + } else { + cs->subtyp = ELSA_PCMCIA; + cs->hw.elsa.ale = cs->hw.elsa.base + ELSA_ALE_PCM; + cs->hw.elsa.isac = cs->hw.elsa.base + ELSA_ISAC_PCM; + cs->hw.elsa.hscx = cs->hw.elsa.base + ELSA_HSCX; + } + cs->hw.elsa.timer = 0; + cs->hw.elsa.trig = 0; + cs->hw.elsa.ctrl = 0; + cs->irq_flags |= SA_SHIRQ; + printk(KERN_INFO + "Elsa: %s defined at %#lx IRQ %d\n", + Elsa_Types[cs->subtyp], + cs->hw.elsa.base, + cs->irq); + } else if (cs->typ == ISDN_CTYPE_ELSA_PCI) { +#if CONFIG_PCI + cs->subtyp = 0; if ((dev_qs1000 = pci_find_device(PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_MICROLINK, dev_qs1000))) { - if (elsa_qs_pci_probe(card->cs, dev_qs1000, - ELSA_QS1000PCI)) - return 0; - return 1; + if (pci_enable_device(dev_qs1000)) + return(0); + cs->subtyp = ELSA_QS1000PCI; + cs->irq = dev_qs1000->irq; + cs->hw.elsa.cfg = pci_resource_start(dev_qs1000, 1); + cs->hw.elsa.base = pci_resource_start(dev_qs1000, 3); } else if ((dev_qs3000 = pci_find_device(PCI_VENDOR_ID_ELSA, PCI_DEVICE_ID_ELSA_QS3000, dev_qs3000))) { - if (elsa_qs_pci_probe(card->cs, dev_qs3000, - ELSA_QS3000PCI)) - return 0; - return 1; + if (pci_enable_device(dev_qs3000)) + return(0); + cs->subtyp = ELSA_QS3000PCI; + cs->irq = dev_qs3000->irq; + cs->hw.elsa.cfg = pci_resource_start(dev_qs3000, 1); + cs->hw.elsa.base = pci_resource_start(dev_qs3000, 3); } else { printk(KERN_WARNING "Elsa: No PCI card found\n"); - return 0; + return(0); + } + if (!cs->irq) { + printk(KERN_WARNING "Elsa: No IRQ for PCI card found\n"); + return(0); + } + + if (!(cs->hw.elsa.base && cs->hw.elsa.cfg)) { + printk(KERN_WARNING "Elsa: No IO-Adr for PCI card found\n"); + return(0); + } + if ((cs->hw.elsa.cfg & 0xff) || (cs->hw.elsa.base & 0xf)) { + printk(KERN_WARNING "Elsa: You may have a wrong PCI bios\n"); + printk(KERN_WARNING "Elsa: If your system hangs now, read\n"); + printk(KERN_WARNING "Elsa: Documentation/isdn/README.HiSax\n"); } + cs->hw.elsa.ale = cs->hw.elsa.base; + cs->hw.elsa.isac = cs->hw.elsa.base +1; + cs->hw.elsa.hscx = cs->hw.elsa.base +1; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + cs->hw.elsa.timer = 0; + cs->hw.elsa.trig = 0; + cs->irq_flags |= SA_SHIRQ; + printk(KERN_INFO + "Elsa: %s defined at %#lx/0x%x IRQ %d\n", + Elsa_Types[cs->subtyp], + cs->hw.elsa.base, + cs->hw.elsa.cfg, + cs->irq); +#else + printk(KERN_WARNING "Elsa: Elsa PCI and NO_PCI_BIOS\n"); + printk(KERN_WARNING "Elsa: unable to config Elsa PCI\n"); + return (0); #endif /* CONFIG_PCI */ + } else + return (0); + + switch (cs->subtyp) { + case ELSA_PC: + case ELSA_PCC8: + case ELSA_PCC16: + case ELSA_QS1000: + case ELSA_PCMCIA: + case ELSA_PCMCIA_IPAC: + bytecnt = 8; + break; + case ELSA_PCFPRO: + case ELSA_PCF: + case ELSA_QS3000: + case ELSA_QS3000PCI: + bytecnt = 16; + break; + case ELSA_QS1000PCI: + bytecnt = 2; + break; + default: + printk(KERN_WARNING + "Unknown ELSA subtype %d\n", cs->subtyp); + return (0); + } + /* In case of the elsa pcmcia card, this region is in use, + reserved for us by the card manager. So we do not check it + here, it would fail. */ + if (cs->typ != ISDN_CTYPE_ELSA_PCMCIA && !request_region(cs->hw.elsa.base, bytecnt, "elsa isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %#lx-%#lx already in use\n", + CardType[card->typ], + cs->hw.elsa.base, + cs->hw.elsa.base + bytecnt); + return (0); + } + if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI)) { + if (!request_region(cs->hw.elsa.cfg, 0x80, "elsa isdn pci")) { + printk(KERN_WARNING + "HiSax: %s pci port %x-%x already in use\n", + CardType[card->typ], + cs->hw.elsa.cfg, + cs->hw.elsa.cfg + 0x80); + release_region(cs->hw.elsa.base, bytecnt); + return (0); + } + } +#if ARCOFI_USE + init_arcofi(cs); +#endif + setup_isac(cs); + cs->hw.elsa.tl.function = (void *) elsa_led_handler; + cs->hw.elsa.tl.data = (long) cs; + init_timer(&cs->hw.elsa.tl); + /* Teste Timer */ + if (cs->hw.elsa.timer) { + byteout(cs->hw.elsa.trig, 0xff); + byteout(cs->hw.elsa.timer, 0); + if (!TimerRun(cs)) { + byteout(cs->hw.elsa.timer, 0); /* 2. Versuch */ + if (!TimerRun(cs)) { + printk(KERN_WARNING + "Elsa: timer do not start\n"); + release_io_elsa(cs); + return (0); + } + } + HZDELAY((HZ/100) + 1); /* wait >=10 ms */ + if (TimerRun(cs)) { + printk(KERN_WARNING "Elsa: timer do not run down\n"); + release_io_elsa(cs); + return (0); + } + printk(KERN_INFO "Elsa: timer OK; resetting card\n"); + } + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &Elsa_card_msg; + if ((cs->subtyp == ELSA_QS1000PCI) || (cs->subtyp == ELSA_QS3000PCI) || (cs->subtyp == ELSA_PCMCIA_IPAC)) { + cs->readisac = &ReadISAC_IPAC; + cs->writeisac = &WriteISAC_IPAC; + cs->readisacfifo = &ReadISACfifo_IPAC; + cs->writeisacfifo = &WriteISACfifo_IPAC; + cs->irq_func = &elsa_interrupt_ipac; + val = readreg(cs->hw.elsa.ale, cs->hw.elsa.isac, IPAC_ID); + printk(KERN_INFO "Elsa: IPAC version %x\n", val); + } else { + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->irq_func = &elsa_interrupt; + ISACVersion(cs, "Elsa:"); + if (HscxVersion(cs, "Elsa:")) { + printk(KERN_WARNING + "Elsa: wrong HSCX versions check IO address\n"); + release_io_elsa(cs); + return (0); + } + } + if (cs->subtyp == ELSA_PC) { + val = readitac(cs, ITAC_SYS); + printk(KERN_INFO "Elsa: ITAC version %s\n", ITACVer[val & 7]); + writeitac(cs, ITAC_ISEN, 0); + writeitac(cs, ITAC_RFIE, 0); + writeitac(cs, ITAC_XFIE, 0); + writeitac(cs, ITAC_SCIE, 0); + writeitac(cs, ITAC_STIE, 0); } - return 0; + return (1); } diff -Nru a/drivers/isdn/hisax/elsa_cs.c b/drivers/isdn/hisax/elsa_cs.c --- a/drivers/isdn/hisax/elsa_cs.c Thu Feb 19 23:44:25 2004 +++ b/drivers/isdn/hisax/elsa_cs.c Thu Feb 19 23:44:25 2004 @@ -53,6 +53,7 @@ #include #include #include +#include "hisax_cfg.h" MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Elsa PCM cards"); MODULE_AUTHOR("Klaus Lichtenwalder"); @@ -71,7 +72,7 @@ MODULE_PARM(pc_debug, "i"); #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); static char *version = -"elsa_cs.c $Revision: 1.1.2.2 $ $Date: 2001/09/23 22:24:47 $ (K.Lichtenwalder)"; +"elsa_cs.c $Revision: 1.2.2.4 $ $Date: 2004/01/25 15:07:06 $ (K.Lichtenwalder)"; #else #define DEBUG(n, args...) #endif @@ -93,8 +94,6 @@ static int protocol = 2; /* EURO-ISDN Default */ MODULE_PARM(protocol, "i"); -extern int elsa_init_pcmcia(int, int, int*, int); - /*====================================================================*/ /* @@ -168,6 +167,7 @@ dev_link_t link; dev_node_t node; int busy; + int cardnr; } local_info_t; /*====================================================================== @@ -188,7 +188,6 @@ dev_link_t *link; local_info_t *local; int ret, i; - void elsa_interrupt(int, void *, struct pt_regs *); DEBUG(0, "elsa_cs_attach()\n"); @@ -196,6 +195,7 @@ local = kmalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return NULL; memset(local, 0, sizeof(local_info_t)); + local->cardnr = -1; link = &local->link; link->priv = local; /* Interrupt setup */ @@ -337,6 +337,7 @@ int i, j, last_fn; u_short buf[128]; cistpl_cftable_entry_t *cf = &parse.cftable_entry; + IsdnCard_t icard; DEBUG(0, "elsa_config(0x%p)\n", link); handle = link->handle; @@ -430,9 +431,19 @@ link->state &= ~DEV_CONFIG_PENDING; - elsa_init_pcmcia(link->io.BasePort1, link->irq.AssignedIRQ, - &(((local_info_t*)link->priv)->busy), - protocol); + icard.para[0] = link->irq.AssignedIRQ; + icard.para[1] = link->io.BasePort1; + icard.protocol = protocol; + icard.typ = ISDN_CTYPE_ELSA_PCMCIA; + + i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard); + if (i < 0) { + printk(KERN_ERR "elsa_cs: failed to initialize Elsa PCMCIA %d at i/o %#x\n", + i, link->io.BasePort1); + elsa_cs_release(link); + } else + ((local_info_t*)link->priv)->cardnr = i; + return; cs_failed: cs_error(link->handle, last_fn, i); @@ -449,9 +460,16 @@ static void elsa_cs_release(dev_link_t *link) { + local_info_t *local = link->priv; DEBUG(0, "elsa_cs_release(0x%p)\n", link); + if (local) { + if (local->cardnr >= 0) { + /* no unregister function with hisax */ + HiSax_closecard(local->cardnr); + } + } /* Unlink the device chain */ link->dev = NULL; diff -Nru a/drivers/isdn/hisax/elsa_ser.c b/drivers/isdn/hisax/elsa_ser.c --- a/drivers/isdn/hisax/elsa_ser.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hisax/elsa_ser.c Thu Feb 19 23:44:24 2004 @@ -1,4 +1,4 @@ -/* $Id: elsa_ser.c,v 2.10.6.4 2001/09/23 22:24:47 kai Exp $ +/* $Id: elsa_ser.c,v 2.14.2.3 2004/02/11 13:21:33 keil Exp $ * * stuff for the serial modem on ELSA cards * @@ -26,11 +26,10 @@ //#define SERIAL_DEBUG_REG 1 #ifdef SERIAL_DEBUG_REG -static u8 deb[32]; +static u_char deb[32]; const char *ModemIn[] = {"RBR","IER","IIR","LCR","MCR","LSR","MSR","SCR"}; const char *ModemOut[] = {"THR","IER","FCR","LCR","MCR","LSR","MSR","SCR"}; #endif -static spinlock_t elsa_ser_lock = SPIN_LOCK_UNLOCKED; static char *MInit_1 = "AT&F&C1E0&D2\r\0"; static char *MInit_2 = "ATL2M1S64=13\r\0"; @@ -111,7 +110,6 @@ int quot = 0, baud_base; unsigned cval, fcr = 0; int bits; - unsigned long flags; /* byte size and parity */ @@ -135,23 +133,17 @@ serial_outp(cs, UART_IER, cs->hw.elsa.IER); debugl1(cs,"modem quot=0x%x", quot); - spin_lock_irqsave(&elsa_ser_lock, flags); serial_outp(cs, UART_LCR, cval | UART_LCR_DLAB);/* set DLAB */ serial_outp(cs, UART_DLL, quot & 0xff); /* LS of divisor */ serial_outp(cs, UART_DLM, quot >> 8); /* MS of divisor */ serial_outp(cs, UART_LCR, cval); /* reset DLAB */ serial_inp(cs, UART_RX); - spin_unlock_irqrestore(&elsa_ser_lock, flags); } static int mstartup(struct IsdnCardState *cs) { - unsigned long flags; int retval=0; - - spin_lock_irqsave(&elsa_ser_lock, flags); - /* * Clear the FIFO buffers and disable them * (they will be reenabled in change_speed()) @@ -207,7 +199,6 @@ change_speed(cs, BASE_BAUD); cs->hw.elsa.MFlag = 1; errout: - spin_unlock_irqrestore(&elsa_ser_lock, flags); return retval; } @@ -217,15 +208,11 @@ */ static void mshutdown(struct IsdnCardState *cs) { - unsigned long flags; - #ifdef SERIAL_DEBUG_OPEN printk(KERN_DEBUG"Shutting down serial ...."); #endif - spin_lock_irqsave(&elsa_ser_lock, flags); /* Disable interrupts */ - /* * clear delta_msr_wait queue to avoid mem leaks: we may free the irq * here so the queue might never be waken up @@ -245,7 +232,6 @@ serial_outp(cs, UART_FCR, (UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT)); serial_inp(cs, UART_RX); /* read data port to reset things */ - spin_unlock_irqrestore(&elsa_ser_lock, flags); #ifdef SERIAL_DEBUG_OPEN printk(" done\n"); #endif @@ -255,14 +241,12 @@ write_modem(struct BCState *bcs) { int ret=0; struct IsdnCardState *cs = bcs->cs; - u_int count, len, fp; - unsigned long flags; + int count, len, fp; if (!bcs->tx_skb) return 0; if (bcs->tx_skb->len <= 0) return 0; - spin_lock_irqsave(&elsa_ser_lock, flags); len = bcs->tx_skb->len; if (len > MAX_MODEM_BUF - cs->hw.elsa.transcnt) len = MAX_MODEM_BUF - cs->hw.elsa.transcnt; @@ -288,14 +272,37 @@ cs->hw.elsa.IER |= UART_IER_THRI; serial_outp(cs, UART_IER, cs->hw.elsa.IER); } - spin_unlock_irqrestore(&elsa_ser_lock, flags); return(ret); } -static void -modem_fill(struct BCState *bcs) -{ - xmit_xpr_b(bcs); +inline void +modem_fill(struct BCState *bcs) { + + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + write_modem(bcs); + return; + } else { + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hscx.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hscx.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + write_modem(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + schedule_event(bcs, B_XMTBUFREADY); + } } static inline void receive_chars(struct IsdnCardState *cs, @@ -329,7 +336,7 @@ cs->hw.elsa.rcvcnt); skb_queue_tail(& cs->hw.elsa.bcs->rqueue, skb); } - sched_b_event(cs->hw.elsa.bcs, B_RCVBUFREADY); + schedule_event(cs->hw.elsa.bcs, B_RCVBUFREADY); } else { char tmp[128]; char *t = tmp; @@ -375,6 +382,7 @@ } } + static void rs_interrupt_elsa(int irq, struct IsdnCardState *cs) { int status, iir, msr; @@ -419,10 +427,10 @@ { modehscx(bcs, 0, bcs->channel); if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { - if (bcs->rcvbuf) { + if (bcs->hw.hscx.rcvbuf) { if (bcs->mode != L1_MODE_MODEM) - kfree(bcs->rcvbuf); - bcs->rcvbuf = NULL; + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; } skb_queue_purge(&bcs->rqueue); skb_queue_purge(&bcs->squeue); @@ -435,16 +443,13 @@ } void -modem_write_cmd(struct IsdnCardState *cs, u8 *buf, u_int len) { - u_int count, fp; - u8 *msg = buf; - unsigned long flags; +modem_write_cmd(struct IsdnCardState *cs, u_char *buf, int len) { + int count, fp; + u_char *msg = buf; if (!len) return; - spin_lock_irqsave(&elsa_ser_lock, flags); if (len > (MAX_MODEM_BUF - cs->hw.elsa.transcnt)) { - spin_unlock_irqrestore(&elsa_ser_lock, flags); return; } fp = cs->hw.elsa.transcnt + cs->hw.elsa.transp; @@ -465,16 +470,13 @@ cs->hw.elsa.IER |= UART_IER_THRI; serial_outp(cs, UART_IER, cs->hw.elsa.IER); } - spin_unlock_irqrestore(&elsa_ser_lock, flags); } void modem_set_init(struct IsdnCardState *cs) { - unsigned long flags; int timeout; #define RCV_DELAY 20000 - spin_lock_irqsave(&elsa_ser_lock, flags); modem_write_cmd(cs, MInit_1, strlen(MInit_1)); timeout = 1000; while(timeout-- && cs->hw.elsa.transcnt) @@ -517,16 +519,13 @@ udelay(1000); debugl1(cs, "msi tout=%d", timeout); udelay(RCV_DELAY); - spin_unlock_irqrestore(&elsa_ser_lock, flags); } void modem_set_dial(struct IsdnCardState *cs, int outgoing) { - unsigned long flags; int timeout; #define RCV_DELAY 20000 - spin_lock_irqsave(&elsa_ser_lock, flags); modem_write_cmd(cs, MInit_speed28800, strlen(MInit_speed28800)); timeout = 1000; while(timeout-- && cs->hw.elsa.transcnt) @@ -542,40 +541,39 @@ udelay(1000); debugl1(cs, "msi tout=%d", timeout); udelay(RCV_DELAY); - spin_unlock_irqrestore(&elsa_ser_lock, flags); } void modem_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; - unsigned long flags; + u_long flags; if (pr == (PH_DATA | REQUEST)) { - spin_lock_irqsave(&elsa_ser_lock, flags); - if (st->l1.bcs->tx_skb) { - skb_queue_tail(&st->l1.bcs->squeue, skb); - spin_unlock_irqrestore(&elsa_ser_lock, flags); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); } else { - st->l1.bcs->tx_skb = skb; - test_and_set_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - st->l1.bcs->count = 0; - spin_unlock_irqrestore(&elsa_ser_lock, flags); - write_modem(st->l1.bcs); + bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->hw.hscx.count = 0; + write_modem(bcs); } + spin_unlock_irqrestore(&bcs->cs->lock, flags); } else if (pr == (PH_ACTIVATE | REQUEST)) { - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - L1L2(st, PH_ACTIVATE | CONFIRM, NULL); - set_arcofi(st->l1.bcs->cs, st->l1.bc); - mstartup(st->l1.bcs->cs); - modem_set_dial(st->l1.bcs->cs, test_bit(FLG_ORIG, &st->l2.flag)); - st->l1.bcs->cs->hw.elsa.MFlag=2; + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); + set_arcofi(bcs->cs, st->l1.bc); + mstartup(bcs->cs); + modem_set_dial(bcs->cs, test_bit(FLG_ORIG, &st->l2.flag)); + bcs->cs->hw.elsa.MFlag=2; } else if (pr == (PH_DEACTIVATE | REQUEST)) { - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - st->l1.bcs->cs->dc.isac.arcofi_bc = st->l1.bc; - arcofi_fsm(st->l1.bcs->cs, ARCOFI_START, &ARCOFI_XOP_0); - interruptible_sleep_on(&st->l1.bcs->cs->dc.isac.arcofi_wait); - st->l1.bcs->cs->hw.elsa.MFlag=1; + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + bcs->cs->dc.isac.arcofi_bc = st->l1.bc; + arcofi_fsm(bcs->cs, ARCOFI_START, &ARCOFI_XOP_0); + interruptible_sleep_on(&bcs->cs->dc.isac.arcofi_wait); + bcs->cs->hw.elsa.MFlag=1; } else { printk(KERN_WARNING"ElsaSer: unknown pr %x\n", pr); } @@ -591,24 +589,22 @@ case L1_MODE_TRANS: if (open_hscxstate(st->l1.hardware, bcs)) return (-1); - st->l1.l2l1 = hscx_l2l1; - // bcs->cs->BC_Send_Data = hscx_fill_fifo; FIXME + st->l2.l2l1 = hscx_l2l1; break; case L1_MODE_MODEM: bcs->mode = L1_MODE_MODEM; if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { - bcs->rcvbuf = bcs->cs->hw.elsa.rcvbuf; + bcs->hw.hscx.rcvbuf = bcs->cs->hw.elsa.rcvbuf; skb_queue_head_init(&bcs->rqueue); skb_queue_head_init(&bcs->squeue); } bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->event = 0; - bcs->rcvidx = 0; + bcs->hw.hscx.rcvidx = 0; bcs->tx_cnt = 0; bcs->cs->hw.elsa.bcs = bcs; - st->l1.l2l1 = modem_l2l1; -// bcs->cs->bc_l1_ops = &modem_l1_ops; + st->l2.l2l1 = modem_l2l1; break; } st->l1.bcs = bcs; @@ -618,17 +614,13 @@ return (0); } -static struct bc_l1_ops modem_l1_ops = { - .fill_fifo = modem_fill, - .open = setstack_elsa, - .close = close_elsastate, -}; - void -init_modem(struct IsdnCardState *cs) -{ - cs->bc_l1_ops = &modem_l1_ops; +init_modem(struct IsdnCardState *cs) { + cs->bcs[0].BC_SetStack = setstack_elsa; + cs->bcs[1].BC_SetStack = setstack_elsa; + cs->bcs[0].BC_Close = close_elsastate; + cs->bcs[1].BC_Close = close_elsastate; if (!(cs->hw.elsa.rcvbuf = kmalloc(MAX_MODEM_BUF, GFP_ATOMIC))) { printk(KERN_WARNING diff -Nru a/drivers/isdn/hisax/enternow.h b/drivers/isdn/hisax/enternow.h --- a/drivers/isdn/hisax/enternow.h Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/enternow.h Thu Feb 19 23:44:23 2004 @@ -40,3 +40,12 @@ * den TigerJet i/o-Raum gemappt * -> 0x01 des AMD bei hw.njet.base + 0C4 */ #define TJ_AMD_PORT 0xC0 + + + +/* ***************************************************************************************** * + * *************************************** Prototypen ************************************** * + * ***************************************************************************************** */ + +BYTE ReadByteAmd7930(struct IsdnCardState *cs, BYTE offset); +void WriteByteAmd7930(struct IsdnCardState *cs, BYTE offset, BYTE value); diff -Nru a/drivers/isdn/hisax/enternow_pci.c b/drivers/isdn/hisax/enternow_pci.c --- a/drivers/isdn/hisax/enternow_pci.c Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/hisax/enternow_pci.c Thu Feb 19 23:44:27 2004 @@ -74,13 +74,14 @@ -const char *enternow_pci_rev = "$Revision: 1.1.2.1 $"; +const char *enternow_pci_rev = "$Revision: 1.1.4.5 $"; + /* *************************** I/O-Interface functions ************************************* */ /* cs->readisac, macro rByteAMD */ -static BYTE +BYTE ReadByteAmd7930(struct IsdnCardState *cs, BYTE offset) { /* direktes Register */ @@ -95,7 +96,7 @@ } /* cs->writeisac, macro wByteAMD */ -static void +void WriteByteAmd7930(struct IsdnCardState *cs, BYTE offset, BYTE value) { /* direktes Register */ @@ -110,14 +111,8 @@ } -static struct dc_hw_ops amd7930_ops = { - .read_reg = ReadByteAmd7930, - .write_reg = WriteByteAmd7930, -}; - -static void -enpci_setIrqMask(struct IsdnCardState *cs, BYTE val) -{ +void +enpci_setIrqMask(struct IsdnCardState *cs, BYTE val) { if (!val) OutByte(cs->hw.njet.base+NETJET_IRQMASK1, 0x00); else @@ -125,6 +120,17 @@ } +static BYTE dummyrr(struct IsdnCardState *cs, int chan, BYTE off) +{ + return(5); +} + +static void dummywr(struct IsdnCardState *cs, int chan, BYTE off, BYTE value) +{ + +} + + /* ******************************************************************************** */ @@ -137,15 +143,12 @@ /* Reset on, (also for AMD) */ cs->hw.njet.ctrl_reg = 0x07; OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - /* 80 ms delay */ - schedule_timeout((80*HZ)/1000); + mdelay(20); /* Reset off */ - cs->hw.njet.ctrl_reg = 0x70; + cs->hw.njet.ctrl_reg = 0x30; OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - /* 80ms delay */ - schedule_timeout((80*HZ)/1000); + /* 20ms delay */ + mdelay(20); cs->hw.njet.auxd = 0; // LED-status cs->hw.njet.dmactrl = 0; OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ); @@ -153,96 +156,124 @@ OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd); // LED off } -static void -enpci_bc_activate(struct IsdnCardState *cs, int chan) -{ - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "enter:now PCI: assign phys. BC %d in AMD LMR1", chan); - - cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 | (chan + 1)), "MDL_BC_ASSIGN"); - /* at least one b-channel in use, LED 2 on */ - cs->hw.njet.auxd |= TJ_AMD_IRQ << 2; - OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); -} -static void -enpci_bc_deactivate(struct IsdnCardState *cs, int chan) +static int +enpci_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "enter:now PCI: release phys. BC %d in Amd LMR1", chan); - - cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 & ~(chan + 1)), "MDL_BC_RELEASE"); - /* no b-channel active -> LED2 off */ - if (!(cs->dc.amd7930.lmr1 & 3)) { - cs->hw.njet.auxd &= ~(TJ_AMD_IRQ << 2); - OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); - } -} + u_long flags; + BYTE *chan; -static void -enpci_led_handler(struct IsdnCardState *cs) -{ - if (cs->status & 0x0001) { - /* TEI assigned, LED1 on */ - cs->hw.njet.auxd = TJ_AMD_IRQ << 1; - OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); - } else { - /* TEI removed, LEDs off */ - cs->hw.njet.auxd = 0; - OutByte(cs->hw.njet.base + NETJET_AUXDATA, 0x00); - } -} + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "enter:now PCI: card_msg: 0x%04X", mt); -static void -enpci_init(struct IsdnCardState *cs) -{ - inittiger(cs); - Amd7930_init(cs); -} + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_enpci(cs); + Amd7930_init(cs); + spin_unlock_irqrestore(&cs->lock, flags); + break; + case CARD_RELEASE: + release_io_netjet(cs); + break; + case CARD_INIT: + reset_enpci(cs); + inittiger(cs); + /* irq must be on here */ + Amd7930_init(cs); + break; + case CARD_TEST: + break; + case MDL_ASSIGN: + /* TEI assigned, LED1 on */ + cs->hw.njet.auxd = TJ_AMD_IRQ << 1; + OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); + break; + case MDL_REMOVE: + /* TEI removed, LEDs off */ + cs->hw.njet.auxd = 0; + OutByte(cs->hw.njet.base + NETJET_AUXDATA, 0x00); + break; + case MDL_BC_ASSIGN: + /* activate B-channel */ + chan = (BYTE *)arg; + + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "enter:now PCI: assign phys. BC %d in AMD LMR1", *chan); + + cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 | (*chan + 1)), "MDL_BC_ASSIGN"); + /* at least one b-channel in use, LED 2 on */ + cs->hw.njet.auxd |= TJ_AMD_IRQ << 2; + OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); + break; + case MDL_BC_RELEASE: + /* deactivate B-channel */ + chan = (BYTE *)arg; + + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "enter:now PCI: release phys. BC %d in Amd LMR1", *chan); + + cs->dc.amd7930.ph_command(cs, (cs->dc.amd7930.lmr1 & ~(*chan + 1)), "MDL_BC_RELEASE"); + /* no b-channel active -> LED2 off */ + if (!(cs->dc.amd7930.lmr1 & 3)) { + cs->hw.njet.auxd &= ~(TJ_AMD_IRQ << 2); + OutByte(cs->hw.njet.base + NETJET_AUXDATA, cs->hw.njet.auxd); + } + break; + default: + break; -static int -enpci_reset(struct IsdnCardState *cs) -{ - reset_enpci(cs); - Amd7930_init(cs); - return 0; + } + return(0); } static irqreturn_t enpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - BYTE sval, ir; - - spin_lock(&cs->lock); + BYTE s0val, s1val, ir; + u_long flags; - sval = InByte(cs->hw.njet.base + NETJET_IRQSTAT1); + spin_lock_irqsave(&cs->lock, flags); + s1val = InByte(cs->hw.njet.base + NETJET_IRQSTAT1); /* AMD threw an interrupt */ - if (!(sval & TJ_AMD_IRQ)) { + if (!(s1val & TJ_AMD_IRQ)) { /* read and clear interrupt-register */ ir = ReadByteAmd7930(cs, 0x00); Amd7930_interrupt(cs, ir); - } + s1val = 1; + } else + s1val = 0; + s0val = InByte(cs->hw.njet.base + NETJET_IRQSTAT0); + if ((s0val | s1val)==0) { // shared IRQ + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_NONE; + } + if (s0val) + OutByte(cs->hw.njet.base + NETJET_IRQSTAT0, s0val); /* DMA-Interrupt: B-channel-stuff */ /* set bits in sval to indicate which page is free */ - - /* set bits in sval to indicate which page is free */ if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) < inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ)) /* the 2nd write page is free */ - sval = 0x08; + s0val = 0x08; else /* the 1st write page is free */ - sval = 0x04; + s0val = 0x04; if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) < inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ)) /* the 2nd read page is free */ - sval = sval | 0x02; + s0val = s0val | 0x02; else /* the 1st read page is free */ - sval = sval | 0x01; - if (sval != cs->hw.njet.last_is0) { /* we have a DMA interrupt */ - cs->hw.njet.irqstat0 = sval; + s0val = s0val | 0x01; + if (s0val != cs->hw.njet.last_is0) /* we have a DMA interrupt */ + { + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; + } + cs->hw.njet.irqstat0 = s0val; if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != (cs->hw.njet.last_is0 & NETJET_IRQM0_READ)) /* we have a read dma int */ @@ -251,71 +282,12 @@ (cs->hw.njet.last_is0 & NETJET_IRQM0_WRITE)) /* we have a write dma int */ write_tiger(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } - spin_unlock(&cs->lock); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } -static struct card_ops enpci_ops = { - .init = enpci_init, - .reset = enpci_reset, - .release = netjet_release, - .led_handler = enpci_led_handler, - .irq_func = enpci_interrupt, -}; - -static int __init -enpci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - if (pci_enable_device(pdev)) - goto err; - - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.njet.base = pci_resource_start(pdev, 0); - if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "Fn_ISDN")) - goto err; - - cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; - cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD - - /* Reset an */ - cs->hw.njet.ctrl_reg = 0x07; // geändert von 0xff - OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - /* 50 ms Pause */ - schedule_timeout((50*HZ)/1000); - - cs->hw.njet.ctrl_reg = 0x30; /* Reset Off and status read clear */ - OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.auxd = 0x00; // war 0xc0 - cs->hw.njet.dmactrl = 0; - - OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ); - OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ); - OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd); - - printk(KERN_INFO - "enter:now PCI: PCI card configured at 0x%lx IRQ %d\n", - cs->hw.njet.base, cs->irq); - reset_enpci(cs); - cs->hw.njet.last_is0 = 0; - cs->hw.njet.bc_activate = enpci_bc_activate; - cs->hw.njet.bc_deactivate = enpci_bc_deactivate; - amd7930_setup(cs, &amd7930_ops, &enpci_setIrqMask); - - cs->card_ops = &enpci_ops; - - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} static struct pci_dev *dev_netjet __initdata = NULL; @@ -323,30 +295,105 @@ int __init setup_enternow_pci(struct IsdnCard *card) { + int bytecnt; + struct IsdnCardState *cs = card->cs; char tmp[64]; +#if CONFIG_PCI #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif strcpy(tmp, enternow_pci_rev); printk(KERN_INFO "HiSax: Formula-n Europe AG enter:now ISDN PCI driver Rev. %s\n", HiSax_getrev(tmp)); - - dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, - PCI_DEVICE_ID_TIGERJET_300, dev_netjet); - if (dev_netjet) { - if (dev_netjet->subsystem_vendor != 0x55 || - dev_netjet->subsystem_device != 0x02) { - printk(KERN_WARNING "enter:now: You tried to load " - "this driver with an incompatible " - "TigerJet-card\n"); - printk(KERN_WARNING "Use type=20 for Traverse " - "NetJet PCI Card.\n"); - return 0; + if (cs->typ != ISDN_CTYPE_ENTERNOW) + return(0); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + + for ( ;; ) + { + if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, + PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { + if (pci_enable_device(dev_netjet)) + return(0); + cs->irq = dev_netjet->irq; + if (!cs->irq) { + printk(KERN_WARNING "enter:now PCI: No IRQ for PCI card found\n"); + return(0); + } + cs->hw.njet.base = pci_resource_start(dev_netjet, 0); + if (!cs->hw.njet.base) { + printk(KERN_WARNING "enter:now PCI: No IO-Adr for PCI card found\n"); + return(0); + } + /* checks Sub-Vendor ID because system crashes with Traverse-Card */ + if ((dev_netjet->subsystem_vendor != 0x55) || + (dev_netjet->subsystem_device != 0x02)) { + printk(KERN_WARNING "enter:now: You tried to load this driver with an incompatible TigerJet-card\n"); + printk(KERN_WARNING "Use type=20 for Traverse NetJet PCI Card.\n"); + return(0); + } + } else { + printk(KERN_WARNING "enter:now PCI: No PCI card found\n"); + return(0); } - if (enpci_probe(card->cs, dev_netjet)) - return 1; - return 0; + + cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; + cs->hw.njet.isac = cs->hw.njet.base + 0xC0; // Fenster zum AMD + + /* Reset an */ + cs->hw.njet.ctrl_reg = 0x07; // geändert von 0xff + OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + /* 20 ms Pause */ + mdelay(20); + + cs->hw.njet.ctrl_reg = 0x30; /* Reset Off and status read clear */ + OutByte(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + mdelay(10); + + cs->hw.njet.auxd = 0x00; // war 0xc0 + cs->hw.njet.dmactrl = 0; + + OutByte(cs->hw.njet.base + NETJET_AUXCTRL, ~TJ_AMD_IRQ); + OutByte(cs->hw.njet.base + NETJET_IRQMASK1, TJ_AMD_IRQ); + OutByte(cs->hw.njet.auxa, cs->hw.njet.auxd); + + break; + } +#else + + printk(KERN_WARNING "enter:now PCI: NO_PCI_BIOS\n"); + printk(KERN_WARNING "enter:now PCI: unable to config Formula-n enter:now ISDN PCI ab\n"); + return (0); + +#endif /* CONFIG_PCI */ + + bytecnt = 256; + + printk(KERN_INFO + "enter:now PCI: PCI card configured at 0x%lx IRQ %d\n", + cs->hw.njet.base, cs->irq); + if (!request_region(cs->hw.njet.base, bytecnt, "Fn_ISDN")) { + printk(KERN_WARNING + "HiSax: %s config port %lx-%lx already in use\n", + CardType[card->typ], + cs->hw.njet.base, + cs->hw.njet.base + bytecnt); + return (0); } - printk(KERN_WARNING "enter:now PCI: No PCI card found\n"); - return 0; + setup_Amd7930(cs); + cs->hw.njet.last_is0 = 0; + /* macro rByteAMD */ + cs->readisac = &ReadByteAmd7930; + /* macro wByteAMD */ + cs->writeisac = &WriteByteAmd7930; + cs->dc.amd7930.setIrqMask = &enpci_setIrqMask; + + cs->BC_Read_Reg = &dummyrr; + cs->BC_Write_Reg = &dummywr; + cs->BC_Send_Data = &netjet_fill_dma; + cs->cardmsg = &enpci_card_msg; + cs->irq_func = &enpci_interrupt; + cs->irq_flags |= SA_SHIRQ; + + return (1); } diff -Nru a/drivers/isdn/hisax/gazel.c b/drivers/isdn/hisax/gazel.c --- a/drivers/isdn/hisax/gazel.c Thu Feb 19 23:44:25 2004 +++ b/drivers/isdn/hisax/gazel.c Thu Feb 19 23:44:25 2004 @@ -1,4 +1,4 @@ -/* $Id: gazel.c,v 2.11.6.7 2001/09/23 22:24:47 kai Exp $ +/* $Id: gazel.c,v 2.19.2.4 2004/01/14 16:04:48 keil Exp $ * * low level stuff for Gazel isdn cards * @@ -21,8 +21,7 @@ #include extern const char *CardType[]; -const char *gazel_revision = "$Revision: 2.11.6.7 $"; -static spinlock_t gazel_lock = SPIN_LOCK_UNLOCKED; +const char *gazel_revision = "$Revision: 2.19.2.4 $"; #define R647 1 #define R685 2 @@ -44,492 +43,642 @@ #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static inline u8 +static inline u_char readreg(unsigned int adr, u_short off) { return bytein(adr + off); } static inline void -writereg(unsigned int adr, u_short off, u8 data) +writereg(unsigned int adr, u_short off, u_char data) { byteout(adr + off, data); } static inline void -read_fifo(unsigned int adr, u8 * data, int size) +read_fifo(unsigned int adr, u_char * data, int size) { insb(adr, data, size); } static void -write_fifo(unsigned int adr, u8 * data, int size) +write_fifo(unsigned int adr, u_char * data, int size) { outsb(adr, data, size); } -static u8 -r685_isac_read(struct IsdnCardState *cs, u8 off) +static inline u_char +readreg_ipac(unsigned int adr, u_short off) { - return readreg(cs->hw.gazel.isac, off); -} + register u_char ret; -static u8 -r647_isac_read(struct IsdnCardState *cs, u8 off) -{ - return readreg(cs->hw.gazel.isac, (off << 8 & 0xf000) | (off & 0xf)); + byteout(adr, off); + ret = bytein(adr + 4); + return ret; } -static void -r685_isac_write(struct IsdnCardState *cs, u8 off, u8 value) +static inline void +writereg_ipac(unsigned int adr, u_short off, u_char data) { - writereg(cs->hw.gazel.isac, off, value); + byteout(adr, off); + byteout(adr + 4, data); } -static void -r647_isac_write(struct IsdnCardState *cs, u8 off, u8 value) -{ - writereg(cs->hw.gazel.isac, (off << 8 & 0xf000) | (off & 0xf), value); -} -static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +static inline void +read_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size) { - read_fifo(cs->hw.gazel.isacfifo, data, size); + byteout(adr, off); + insb(adr + 4, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +write_fifo_ipac(unsigned int adr, u_short off, u_char * data, int size) { - write_fifo(cs->hw.gazel.isacfifo, data, size); + byteout(adr, off); + outsb(adr + 4, data, size); } -static struct dc_hw_ops r685_isac_ops = { - .read_reg = r685_isac_read, - .write_reg = r685_isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; +/* Interface functions */ -static struct dc_hw_ops r647_isac_ops = { - .read_reg = r647_isac_read, - .write_reg = r647_isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -r685_hscx_read(struct IsdnCardState *cs, int hscx, u8 off) +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs->hw.gazel.hscx[hscx], off); + u_short off2 = offset; + + switch (cs->subtyp) { + case R647: + off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); + case R685: + return (readreg(cs->hw.gazel.isac, off2)); + case R753: + case R742: + return (readreg_ipac(cs->hw.gazel.ipac, 0x80 + off2)); + } + return 0; } -static u8 -r647_hscx_read(struct IsdnCardState *cs, int hscx, u8 off) +static void +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - return readreg(cs->hw.gazel.hscx[hscx], - (off << 8 & 0xf000) | (off & 0xf)); + u_short off2 = offset; + + switch (cs->subtyp) { + case R647: + off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); + case R685: + writereg(cs->hw.gazel.isac, off2, value); + break; + case R753: + case R742: + writereg_ipac(cs->hw.gazel.ipac, 0x80 + off2, value); + break; + } } static void -r685_hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 value) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - writereg(cs->hw.gazel.hscx[hscx], off, value); + switch (cs->subtyp) { + case R647: + case R685: + read_fifo(cs->hw.gazel.isacfifo, data, size); + break; + case R753: + case R742: + read_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size); + break; + } } static void -r647_hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 value) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - writereg(cs->hw.gazel.hscx[hscx], - (off << 8 & 0xf000) | (off & 0xf), value); + switch (cs->subtyp) { + case R647: + case R685: + write_fifo(cs->hw.gazel.isacfifo, data, size); + break; + case R753: + case R742: + write_fifo_ipac(cs->hw.gazel.ipac, 0x80, data, size); + break; + } } static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size) +ReadHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size) { - read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); + switch (cs->subtyp) { + case R647: + case R685: + read_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); + break; + case R753: + case R742: + read_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size); + break; + } } static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size) +WriteHSCXfifo(struct IsdnCardState *cs, int hscx, u_char * data, int size) { - write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); + switch (cs->subtyp) { + case R647: + case R685: + write_fifo(cs->hw.gazel.hscxfifo[hscx], data, size); + break; + case R753: + case R742: + write_fifo_ipac(cs->hw.gazel.ipac, hscx * 0x40, data, size); + break; + } } -static struct bc_hw_ops r685_hscx_ops = { - .read_reg = r685_hscx_read, - .write_reg = r685_hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static struct bc_hw_ops r647_hscx_ops = { - .read_reg = r647_hscx_read, - .write_reg = r647_hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static inline u8 -ipac_read(struct IsdnCardState *cs, u_short off) -{ - register u8 ret; - unsigned long flags; - - spin_lock_irqsave(&gazel_lock, flags); - byteout(cs->hw.gazel.ipac, off); - ret = bytein(cs->hw.gazel.ipac + 4); - spin_unlock_irqrestore(&gazel_lock, flags); - return ret; +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) +{ + u_short off2 = offset; + + switch (cs->subtyp) { + case R647: + off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); + case R685: + return (readreg(cs->hw.gazel.hscx[hscx], off2)); + case R753: + case R742: + return (readreg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2)); + } + return 0; } -static inline void -ipac_write(struct IsdnCardState *cs, u_short off, u8 data) +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - unsigned long flags; + u_short off2 = offset; - spin_lock_irqsave(&gazel_lock, flags); - byteout(cs->hw.gazel.ipac, off); - byteout(cs->hw.gazel.ipac + 4, data); - spin_unlock_irqrestore(&gazel_lock, flags); + switch (cs->subtyp) { + case R647: + off2 = ((off2 << 8 & 0xf000) | (off2 & 0xf)); + case R685: + writereg(cs->hw.gazel.hscx[hscx], off2, value); + break; + case R753: + case R742: + writereg_ipac(cs->hw.gazel.ipac, hscx * 0x40 + off2, value); + break; + } } +/* + * fast interrupt HSCX stuff goes here + */ -static inline void -ipac_readfifo(struct IsdnCardState *cs, u8 off, u8 * data, int size) -{ - byteout(cs->hw.gazel.ipac, off); - insb(cs->hw.gazel.ipac + 4, data, size); +#define READHSCX(cs, nr, reg) ReadHSCX(cs, nr, reg) +#define WRITEHSCX(cs, nr, reg, data) WriteHSCX(cs, nr, reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) ReadHSCXfifo(cs, nr, ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) WriteHSCXfifo(cs, nr, ptr, cnt) + +#include "hscx_irq.c" + +static irqreturn_t +gazel_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ +#define MAXCOUNT 5 + struct IsdnCardState *cs = dev_id; + u_char valisac, valhscx; + int count = 0; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + do { + valhscx = ReadHSCX(cs, 1, HSCX_ISTA); + if (valhscx) + hscx_int_main(cs, valhscx); + valisac = ReadISAC(cs, ISAC_ISTA); + if (valisac) + isac_interrupt(cs, valisac); + count++; + } while ((valhscx || valisac) && (count < MAXCOUNT)); + + WriteHSCX(cs, 0, HSCX_MASK, 0xFF); + WriteHSCX(cs, 1, HSCX_MASK, 0xFF); + WriteISAC(cs, ISAC_MASK, 0xFF); + WriteISAC(cs, ISAC_MASK, 0x0); + WriteHSCX(cs, 0, HSCX_MASK, 0x0); + WriteHSCX(cs, 1, HSCX_MASK, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; } -static inline void -ipac_writefifo(struct IsdnCardState *cs, u8 off, u8 * data, int size) -{ - byteout(cs->hw.gazel.ipac, off); - outsb(cs->hw.gazel.ipac + 4, data, size); -} -/* This will generate ipac_dc_ops and ipac_bc_ops using the functions - * above */ +static irqreturn_t +gazel_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char ista, val; + int count = 0; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + ista = ReadISAC(cs, IPAC_ISTA - 0x80); + do { + if (ista & 0x0f) { + val = ReadHSCX(cs, 1, HSCX_ISTA); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) { + hscx_int_main(cs, val); + } + } + if (ista & 0x20) { + val = 0xfe & ReadISAC(cs, ISAC_ISTA); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = ReadISAC(cs, IPAC_ISTA - 0x80); + count++; + } + while ((ista & 0x3f) && (count < MAXCOUNT)); -BUILD_IPAC_OPS(ipac); + WriteISAC(cs, IPAC_MASK - 0x80, 0xFF); + WriteISAC(cs, IPAC_MASK - 0x80, 0xC0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} +void +release_io_gazel(struct IsdnCardState *cs) +{ + unsigned int i; + + switch (cs->subtyp) { + case R647: + for (i = 0x0000; i < 0xC000; i += 0x1000) + release_region(i + cs->hw.gazel.hscx[0], 16); + release_region(0xC000 + cs->hw.gazel.hscx[0], 1); + break; -static int -r647_reset(struct IsdnCardState *cs) -{ - writereg(cs->hw.gazel.cfg_reg, 0, 0); - HZDELAY(10); - writereg(cs->hw.gazel.cfg_reg, 0, 1); - HZDELAY(2); - return 0; + case R685: + release_region(cs->hw.gazel.hscx[0], 0x100); + release_region(cs->hw.gazel.cfg_reg, 0x80); + break; + + case R753: + release_region(cs->hw.gazel.ipac, 0x8); + release_region(cs->hw.gazel.cfg_reg, 0x80); + break; + + case R742: + release_region(cs->hw.gazel.ipac, 8); + break; + } } static int -r685_reset(struct IsdnCardState *cs) +reset_gazel(struct IsdnCardState *cs) { unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg; - plxcntrl = inl(addr + PLX_CNTRL); - plxcntrl |= (RESET_9050 + RESET_GAZEL); - outl(plxcntrl, addr + PLX_CNTRL); - plxcntrl &= ~(RESET_9050 + RESET_GAZEL); - HZDELAY(4); - outl(plxcntrl, addr + PLX_CNTRL); - HZDELAY(10); - outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR); - return 0; + switch (cs->subtyp) { + case R647: + writereg(addr, 0, 0); + HZDELAY(10); + writereg(addr, 0, 1); + HZDELAY(2); + break; + case R685: + plxcntrl = inl(addr + PLX_CNTRL); + plxcntrl |= (RESET_9050 + RESET_GAZEL); + outl(plxcntrl, addr + PLX_CNTRL); + plxcntrl &= ~(RESET_9050 + RESET_GAZEL); + HZDELAY(4); + outl(plxcntrl, addr + PLX_CNTRL); + HZDELAY(10); + outb(INT_ISAC_EN + INT_HSCX_EN + INT_PCI_EN, addr + PLX_INCSR); + break; + case R753: + plxcntrl = inl(addr + PLX_CNTRL); + plxcntrl |= (RESET_9050 + RESET_GAZEL); + outl(plxcntrl, addr + PLX_CNTRL); + plxcntrl &= ~(RESET_9050 + RESET_GAZEL); + WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20); + HZDELAY(4); + outl(plxcntrl, addr + PLX_CNTRL); + HZDELAY(10); + WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00); + WriteISAC(cs, IPAC_ACFG - 0x80, 0xff); + WriteISAC(cs, IPAC_AOE - 0x80, 0x0); + WriteISAC(cs, IPAC_MASK - 0x80, 0xff); + WriteISAC(cs, IPAC_CONF - 0x80, 0x1); + outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR); + WriteISAC(cs, IPAC_MASK - 0x80, 0xc0); + break; + case R742: + WriteISAC(cs, IPAC_POTA2 - 0x80, 0x20); + HZDELAY(4); + WriteISAC(cs, IPAC_POTA2 - 0x80, 0x00); + WriteISAC(cs, IPAC_ACFG - 0x80, 0xff); + WriteISAC(cs, IPAC_AOE - 0x80, 0x0); + WriteISAC(cs, IPAC_MASK - 0x80, 0xff); + WriteISAC(cs, IPAC_CONF - 0x80, 0x1); + WriteISAC(cs, IPAC_MASK - 0x80, 0xc0); + break; + } + return (0); } static int -r753_reset(struct IsdnCardState *cs) +Gazel_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - unsigned long plxcntrl, addr = cs->hw.gazel.cfg_reg; + u_long flags; - if (test_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags)) - /* we can't read, assume the default */ - plxcntrl = 0x18784db6; - else - plxcntrl = inl(addr + PLX_CNTRL); - plxcntrl |= (RESET_9050 + RESET_GAZEL); - outl(plxcntrl, addr + PLX_CNTRL); - ipac_write(cs, IPAC_POTA2, 0x20); - HZDELAY(4); - plxcntrl &= ~(RESET_9050 + RESET_GAZEL); - outl(plxcntrl, addr + PLX_CNTRL); - HZDELAY(10); - ipac_write(cs, IPAC_POTA2, 0x00); - ipac_write(cs, IPAC_ACFG, 0xff); - ipac_write(cs, IPAC_AOE, 0x0); - ipac_write(cs, IPAC_MASK, 0xff); - ipac_write(cs, IPAC_CONF, 0x1); - outb(INT_IPAC_EN + INT_PCI_EN, addr + PLX_INCSR); - ipac_write(cs, IPAC_MASK, 0xc0); - return 0; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_gazel(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_RELEASE: + release_io_gazel(cs); + return (0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithscxisac(cs, 1); + if ((cs->subtyp==R647)||(cs->subtyp==R685)) { + int i; + for (i=0;i<(2+MAX_WAITING_CALLS);i++) { + cs->bcs[i].hw.hscx.tsaxr0 = 0x1f; + cs->bcs[i].hw.hscx.tsaxr1 = 0x23; + } + } + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_TEST: + return (0); + } + return (0); } static int -r742_reset(struct IsdnCardState *cs) +reserve_regions(struct IsdnCard *card, struct IsdnCardState *cs) { - ipac_write(cs, IPAC_POTA2, 0x20); - HZDELAY(4); - ipac_write(cs, IPAC_POTA2, 0x00); - ipac_write(cs, IPAC_ACFG, 0xff); - ipac_write(cs, IPAC_AOE, 0x0); - ipac_write(cs, IPAC_MASK, 0xff); - ipac_write(cs, IPAC_CONF, 0x1); - ipac_write(cs, IPAC_MASK, 0xc0); - return 0; -} + unsigned int i, j, base = 0, adr = 0, len = 0; -static void -gazel_init(struct IsdnCardState *cs) -{ - int i; + switch (cs->subtyp) { + case R647: + base = cs->hw.gazel.hscx[0]; + if (!request_region(adr = (0xC000 + base), len = 1, "gazel")) + goto error; + for (i = 0x0000; i < 0xC000; i += 0x1000) { + if (!request_region(adr = (i + base), len = 16, "gazel")) + goto error; + } + if (i != 0xC000) { + for (j = 0; j < i; j+= 0x1000) + release_region(j + base, 16); + release_region(0xC000 + base, 1); + goto error; + } + break; + + case R685: + if (!request_region(adr = cs->hw.gazel.hscx[0], len = 0x100, "gazel")) + goto error; + if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) { + release_region(cs->hw.gazel.hscx[0],0x100); + goto error; + } + break; - for (i = 0; i < 2; i++) { - cs->bcs[i].hw.hscx.tsaxr0 = 0x1f; - cs->bcs[i].hw.hscx.tsaxr1 = 0x23; - } - inithscxisac(cs); -} - -static struct card_ops r647_ops = { - .init = gazel_init, - .reset = r647_reset, - .release = hisax_release_resources, - .irq_func = hscxisac_irq, -}; - -static struct card_ops r685_ops = { - .init = gazel_init, - .reset = r685_reset, - .release = hisax_release_resources, - .irq_func = hscxisac_irq, -}; - -static struct card_ops r742_ops = { - .init = ipac_init, - .reset = r742_reset, - .release = hisax_release_resources, - .irq_func = ipac_irq, -}; - -static struct card_ops r753_ops = { - .init = ipac_init, - .reset = r753_reset, - .release = hisax_release_resources, - .irq_func = ipac_irq, -}; + case R753: + if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel")) + goto error; + if (!request_region(adr = cs->hw.gazel.cfg_reg, len = 0x80, "gazel")) { + release_region(cs->hw.gazel.ipac, 8); + goto error; + } + break; + + case R742: + if (!request_region(adr = cs->hw.gazel.ipac, len = 0x8, "gazel")) + goto error; + break; + } + + return 0; + + error: + printk(KERN_WARNING "Gazel: %s io ports 0x%x-0x%x already in use\n", + CardType[cs->typ], adr, adr + len); + return 1; +} static int __init -gazel647_probe(struct IsdnCardState *cs, struct IsdnCard *card) +setup_gazelisa(struct IsdnCard *card, struct IsdnCardState *cs) { - int i, base; + printk(KERN_INFO "Gazel: ISA PnP card automatic recognition\n"); + // we got an irq parameter, assume it is an ISA card + // R742 decodes address even in not started... + // R647 returns FF if not present or not started + // eventually needs improvment + if (readreg_ipac(card->para[1], IPAC_ID) == 1) + cs->subtyp = R742; + else + cs->subtyp = R647; - cs->subtyp = R647; - cs->irq = card->para[0]; + setup_isac(cs); cs->hw.gazel.cfg_reg = card->para[1] + 0xC000; - - printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n"); - cs->dc.isac.adf2 = 0x87; - printk(KERN_INFO "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", - cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); - printk(KERN_INFO - "Gazel: hscx A:0x%X hscx B:0x%X\n", - cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); - + cs->hw.gazel.ipac = card->para[1]; cs->hw.gazel.isac = card->para[1] + 0x8000; cs->hw.gazel.hscx[0] = card->para[1]; cs->hw.gazel.hscx[1] = card->para[1] + 0x4000; + cs->irq = card->para[0]; cs->hw.gazel.isacfifo = cs->hw.gazel.isac; cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0]; cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; - base = cs->hw.gazel.hscx[0]; - for (i = 0; i < 0xc000; i += 0x1000) { - if (!request_io(&cs->rs, base + i, 16, "gazel")) - goto err; - } - if (!request_io(&cs->rs, 0xc000 + base, 1, "gazel")) - goto err; - - cs->card_ops = &r647_ops; - if (hscxisac_setup(cs, &r647_isac_ops, &r647_hscx_ops)) - goto err; - - cs->card_ops->reset(cs); - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -gazel742_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->subtyp = R742; - cs->irq = card->para[0]; - cs->hw.gazel.cfg_reg = card->para[1] + 0xC000; + switch (cs->subtyp) { + case R647: + printk(KERN_INFO "Gazel: Card ISA R647/R648 found\n"); + cs->dc.isac.adf2 = 0x87; + printk(KERN_INFO + "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); + printk(KERN_INFO + "Gazel: hscx A:0x%X hscx B:0x%X\n", + cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); - printk(KERN_INFO "Gazel: Card ISA R742 found\n"); - printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X\n", - cs->irq, cs->hw.gazel.ipac); - - if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel")) - goto err; - - cs->card_ops = &r742_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; + break; + case R742: + printk(KERN_INFO "Gazel: Card ISA R742 found\n"); + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + printk(KERN_INFO + "Gazel: config irq:%d ipac:0x%X\n", + cs->irq, cs->hw.gazel.ipac); + break; + } - cs->card_ops->reset(cs); - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + return (0); } +static struct pci_dev *dev_tel __initdata = NULL; + static int __init -gazel685_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +setup_gazelpci(struct IsdnCardState *cs) { - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = R685; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.gazel.cfg_reg = pci_resource_start(pdev, 1); - cs->hw.gazel.isac = pci_resource_start(pdev, 2) + 0x80; - cs->hw.gazel.hscx[0] = pci_resource_start(pdev, 2); - cs->hw.gazel.hscx[1] = pci_resource_start(pdev, 2) + 0x40; - cs->hw.gazel.isacfifo = cs->hw.gazel.isac; + u_int pci_ioaddr0 = 0, pci_ioaddr1 = 0; + u_char pci_irq = 0, found; + u_int nbseek, seekcard; + + printk(KERN_WARNING "Gazel: PCI card automatic recognition\n"); + + found = 0; + seekcard = PCI_DEVICE_ID_PLX_R685; + for (nbseek = 0; nbseek < 3; nbseek++) { + if ((dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, seekcard, dev_tel))) { + if (pci_enable_device(dev_tel)) + return 1; + pci_irq = dev_tel->irq; + pci_ioaddr0 = pci_resource_start(dev_tel, 1); + pci_ioaddr1 = pci_resource_start(dev_tel, 2); + found = 1; + } + if (found) + break; + else { + switch (seekcard) { + case PCI_DEVICE_ID_PLX_R685: + seekcard = PCI_DEVICE_ID_PLX_R753; + break; + case PCI_DEVICE_ID_PLX_R753: + seekcard = PCI_DEVICE_ID_PLX_DJINN_ITOO; + break; + } + } + } + if (!found) { + printk(KERN_WARNING "Gazel: No PCI card found\n"); + return (1); + } + if (!pci_irq) { + printk(KERN_WARNING "Gazel: No IRQ for PCI card found\n"); + return 1; + } + cs->hw.gazel.pciaddr[0] = pci_ioaddr0; + cs->hw.gazel.pciaddr[1] = pci_ioaddr1; + setup_isac(cs); + pci_ioaddr1 &= 0xfffe; + cs->hw.gazel.cfg_reg = pci_ioaddr0 & 0xfffe; + cs->hw.gazel.ipac = pci_ioaddr1; + cs->hw.gazel.isac = pci_ioaddr1 + 0x80; + cs->hw.gazel.hscx[0] = pci_ioaddr1; + cs->hw.gazel.hscx[1] = pci_ioaddr1 + 0x40; + cs->hw.gazel.isacfifo = cs->hw.gazel.isac; cs->hw.gazel.hscxfifo[0] = cs->hw.gazel.hscx[0]; cs->hw.gazel.hscxfifo[1] = cs->hw.gazel.hscx[1]; - cs->dc.isac.adf2 = 0x87; - - if (!request_io(&cs->rs, cs->hw.gazel.hscx[0], 0x100, "gazel")) - goto err; - if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel")) - goto err; - - printk(KERN_INFO "Gazel: Card PCI R685 found\n"); - printk(KERN_INFO "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", - cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); - printk(KERN_INFO "Gazel: hscx A:0x%X hscx B:0x%X\n", - cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); - - cs->card_ops = &r685_ops; - if (hscxisac_setup(cs, &r685_isac_ops, &r685_hscx_ops)) - goto err; + cs->irq = pci_irq; + cs->irq_flags |= SA_SHIRQ; - cs->card_ops->reset(cs); - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -gazel753_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - u8 pci_rev; - - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = R753; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.gazel.cfg_reg = pci_resource_start(pdev, 1); - cs->hw.gazel.ipac = pci_resource_start(pdev, 2); - - if (!request_io(&cs->rs, cs->hw.gazel.ipac, 0x8, "gazel")) - goto err; - if (!request_io(&cs->rs, cs->hw.gazel.cfg_reg, 0x80, "gazel")) - goto err; - - printk(KERN_INFO "Gazel: Card PCI R753 found\n"); - printk(KERN_INFO "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n", - cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg); - /* - * Erratum for PLX9050, revision 1: - * If bit 7 of BAR 0/1 is set, local config registers - * can not be read (write is okay) - */ - if (cs->hw.gazel.cfg_reg & 0x80) { - pci_read_config_byte(pdev, PCI_REVISION_ID, &pci_rev); - if (pci_rev == 1) { - printk(KERN_INFO "Gazel: PLX9050 rev1 workaround " - "activated\n"); - __set_bit(FLG_BUGGY_PLX9050, &cs->HW_Flags); - } + switch (seekcard) { + case PCI_DEVICE_ID_PLX_R685: + printk(KERN_INFO "Gazel: Card PCI R685 found\n"); + cs->subtyp = R685; + cs->dc.isac.adf2 = 0x87; + printk(KERN_INFO + "Gazel: config irq:%d isac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.isac, cs->hw.gazel.cfg_reg); + printk(KERN_INFO + "Gazel: hscx A:0x%X hscx B:0x%X\n", + cs->hw.gazel.hscx[0], cs->hw.gazel.hscx[1]); + break; + case PCI_DEVICE_ID_PLX_R753: + case PCI_DEVICE_ID_PLX_DJINN_ITOO: + printk(KERN_INFO "Gazel: Card PCI R753 found\n"); + cs->subtyp = R753; + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + printk(KERN_INFO + "Gazel: config irq:%d ipac:0x%X cfg:0x%X\n", + cs->irq, cs->hw.gazel.ipac, cs->hw.gazel.cfg_reg); + break; } - cs->card_ops = &r753_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - goto err; - cs->card_ops->reset(cs); - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + return (0); } -static struct pci_dev *dev_tel __initdata = NULL; -static u16 __initdata dev_id = PCI_DEVICE_ID_PLX_R685; - int __init setup_gazel(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; char tmp[64]; + u_char val; strcpy(tmp, gazel_revision); printk(KERN_INFO "Gazel: Driver Revision %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_GAZEL) + return (0); + if (card->para[0]) { - printk(KERN_INFO "Gazel: ISA card automatic recognition\n"); - // we got an irq parameter, assume it is an ISA card - // R742 decodes address even in not started... - // R647 returns FF if not present or not started - // eventually needs improvment - card->cs->hw.gazel.ipac = card->para[1]; - if (ipac_read(card->cs, IPAC_ID) == 1) { - if (gazel742_probe(card->cs, card)) - return 0; - } else { - if (gazel647_probe(card->cs, card)) - return 0; - } - return 1; + if (setup_gazelisa(card, cs)) + return (0); + } else { + +#if CONFIG_PCI + if (setup_gazelpci(cs)) + return (0); +#else + printk(KERN_WARNING "Gazel: Card PCI requested and NO_PCI_BIOS, unable to config\n"); + return (0); +#endif /* CONFIG_PCI */ } - for (;;) { - dev_tel = pci_find_device(PCI_VENDOR_ID_PLX, dev_id, dev_tel); - if (dev_tel) { - switch (dev_id) { - case PCI_DEVICE_ID_PLX_R685: - if (gazel685_probe(card->cs, dev_tel)) - return 0; - return 1; - case PCI_DEVICE_ID_PLX_R753: - case PCI_DEVICE_ID_PLX_DJINN_ITOO: - if (gazel753_probe(card->cs, dev_tel)) - return 0; - return 1; + if (reserve_regions(card, cs)) { + return (0); + } + if (reset_gazel(cs)) { + printk(KERN_WARNING "Gazel: wrong IRQ\n"); + release_io_gazel(cs); + return (0); + } + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &Gazel_card_msg; + + switch (cs->subtyp) { + case R647: + case R685: + cs->irq_func = &gazel_interrupt; + ISACVersion(cs, "Gazel:"); + if (HscxVersion(cs, "Gazel:")) { + printk(KERN_WARNING + "Gazel: wrong HSCX versions check IO address\n"); + release_io_gazel(cs); + return (0); } - } - switch (dev_id) { - case PCI_DEVICE_ID_PLX_R685: - dev_id = PCI_DEVICE_ID_PLX_R753; - case PCI_DEVICE_ID_PLX_R753: - dev_id = PCI_DEVICE_ID_PLX_DJINN_ITOO; - default: break; - } + case R742: + case R753: + cs->irq_func = &gazel_interrupt_ipac; + val = ReadISAC(cs, IPAC_ID - 0x80); + printk(KERN_INFO "Gazel: IPAC version %x\n", val); + break; } - printk(KERN_WARNING "Gazel: No PCI card found\n"); - return 0; -} - + return (1); +} diff -Nru a/drivers/isdn/hisax/hfc_2bds0.c b/drivers/isdn/hisax/hfc_2bds0.c --- a/drivers/isdn/hisax/hfc_2bds0.c Thu Feb 19 23:44:22 2004 +++ b/drivers/isdn/hisax/hfc_2bds0.c Thu Feb 19 23:44:22 2004 @@ -1,4 +1,4 @@ -/* $Id: hfc_2bds0.c,v 1.15.6.3 2001/09/23 22:24:47 kai Exp $ +/* $Id: hfc_2bds0.c,v 1.18.2.6 2004/02/11 13:21:33 keil Exp $ * * specific routines for CCD's HFC 2BDS0 * @@ -23,10 +23,16 @@ #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static inline u8 -ReadReg(struct IsdnCardState *cs, int data, u8 reg) +static void +dummyf(struct IsdnCardState *cs, u_char * data, int size) +{ + printk(KERN_WARNING "HiSax: hfcd dummy fifo called\n"); +} + +static inline u_char +ReadReg(struct IsdnCardState *cs, int data, u_char reg) { - register u8 ret; + register u_char ret; if (data) { if (cs->hw.hfcD.cip != reg) { @@ -44,7 +50,7 @@ } static inline void -WriteReg(struct IsdnCardState *cs, int data, u8 reg, u8 value) +WriteReg(struct IsdnCardState *cs, int data, u_char reg, u_char value) { if (cs->hw.hfcD.cip != reg) { cs->hw.hfcD.cip = reg; @@ -58,31 +64,20 @@ #endif } -static struct bc_hw_ops hfcs_bc_ops = { - .read_reg = ReadReg, - .write_reg = WriteReg, -}; - /* Interface functions */ -static inline u8 -hfcs_read_reg(struct IsdnCardState *cs, u8 offset) +static u_char +readreghfcd(struct IsdnCardState *cs, u_char offset) { - return ReadReg(cs, HFCD_DATA, offset); + return(ReadReg(cs, HFCD_DATA, offset)); } -static inline void -hfcs_write_reg(struct IsdnCardState *cs, u8 offset, u8 value) +static void +writereghfcd(struct IsdnCardState *cs, u_char offset, u_char value) { WriteReg(cs, HFCD_DATA, offset, value); } -void -set_cs_func(struct IsdnCardState *cs) -{ - cs->bc_hw_ops = &hfcs_bc_ops; -} - static inline int WaitForBusy(struct IsdnCardState *cs) { @@ -112,13 +107,12 @@ } static int -SelFiFo(struct IsdnCardState *cs, u8 FiFo) +SelFiFo(struct IsdnCardState *cs, u_char FiFo) { - u8 cip; + u_char cip; if (cs->hw.hfcD.fifo == FiFo) return(1); - switch(FiFo) { case 0: cip = HFCB_FIFO | HFCB_Z1 | HFCB_SEND | HFCB_B1; break; @@ -138,10 +132,11 @@ } cs->hw.hfcD.fifo = FiFo; WaitNoBusy(cs); - WriteReg(cs, HFCD_DATA, cip, 0); + cs->BC_Write_Reg(cs, HFCD_DATA, cip, 0); WaitForBusy(cs); return(2); } + static int GetFreeFifoBytes_B(struct BCState *bcs) { @@ -171,7 +166,7 @@ } static int -ReadZReg(struct IsdnCardState *cs, u8 reg) +ReadZReg(struct IsdnCardState *cs, u_char reg) { int val; @@ -185,12 +180,12 @@ static struct sk_buff *hfc_empty_fifo(struct BCState *bcs, int count) { - u8 *ptr; + u_char *ptr; struct sk_buff *skb; struct IsdnCardState *cs = bcs->cs; int idx; int chksum; - u8 stat, cip; + u_char stat, cip; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hfc_empty_fifo"); @@ -264,10 +259,9 @@ hfc_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - u_int idx; - int fcnt; - u_int count; - u8 cip; + int idx, fcnt; + int count; + u_char cip; if (!bcs->tx_skb) return; @@ -320,7 +314,16 @@ printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel); } else { bcs->tx_cnt -= bcs->tx_skb->len; - xmit_complete_b(bcs); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->tx_skb->len; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; } WaitForBusy(cs); WaitNoBusy(cs); @@ -330,17 +333,33 @@ return; } +static void +hfc_send_data(struct BCState *bcs) +{ + struct IsdnCardState *cs = bcs->cs; + + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs,"send_data %d blocked", bcs->channel); +} + void main_rec_2bds0(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; int z1, z2, rcnt; - u8 f1, f2, cip; + u_char f1, f2, cip; int receive, count = 5; struct sk_buff *skb; Begin: count--; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs,"rec_data %d blocked", bcs->channel); + return; + } SelFiFo(cs, HFCB_REC | HFCB_CHANNEL(bcs->channel)); cip = HFCB_FIFO | HFCB_F1 | HFCB_REC | HFCB_CHANNEL(bcs->channel); WaitNoBusy(cs); @@ -363,7 +382,7 @@ bcs->channel, z1, z2, rcnt); if ((skb = hfc_empty_fifo(bcs, rcnt))) { skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + schedule_event(bcs, B_RCVBUFREADY); } rcnt = f1 -f2; if (rcnt<0) @@ -374,6 +393,7 @@ receive = 0; } else receive = 0; + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); if (count && receive) goto Begin; return; @@ -430,31 +450,57 @@ static void hfc_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; +// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); + } else { +// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - mode_2bs0(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + mode_2bs0(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - mode_2bs0(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + mode_2bs0(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -495,7 +541,7 @@ if (open_hfcstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = hfc_l2l1; + st->l2.l2l1 = hfc_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); @@ -503,11 +549,8 @@ } static void -hfcd_bh(void *data) +hfcd_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; -/* struct PStack *stptr; -*/ if (!cs) return; if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { @@ -543,18 +586,22 @@ struct sk_buff *skb; int idx; int rcnt, z1, z2; - u8 stat, cip, f1, f2; + u_char stat, cip, f1, f2; int chksum; int count=5; - u8 *ptr; + u_char *ptr; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "rec_dmsg blocked"); + return(1); + } SelFiFo(cs, 4 | HFCD_REC); cip = HFCD_FIFO | HFCD_F1 | HFCD_REC; WaitNoBusy(cs); - f1 = hfcs_read_reg(cs, cip) & 0xf; + f1 = cs->readisac(cs, cip) & 0xf; cip = HFCD_FIFO | HFCD_F2 | HFCD_REC; WaitNoBusy(cs); - f2 = hfcs_read_reg(cs, cip) & 0xf; + f2 = cs->readisac(cs, cip) & 0xf; while ((f1 != f2) && count--) { z1 = ReadZReg(cs, HFCD_FIFO | HFCD_Z1 | HFCD_REC); z2 = ReadZReg(cs, HFCD_FIFO | HFCD_Z2 | HFCD_REC); @@ -617,7 +664,7 @@ #endif } else { skb_queue_tail(&cs->rq, skb); - sched_d_event(cs, D_RCVBUFREADY); + schedule_event(cs, D_RCVBUFREADY); } } } else @@ -629,17 +676,18 @@ WaitForBusy(cs); cip = HFCD_FIFO | HFCD_F2 | HFCD_REC; WaitNoBusy(cs); - f2 = hfcs_read_reg(cs, cip) & 0xf; + f2 = cs->readisac(cs, cip) & 0xf; } + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); return(1); } static void hfc_fill_dfifo(struct IsdnCardState *cs) { - int fcnt; - u_int idx, count; - u8 cip; + int idx, fcnt; + int count; + u_char cip; if (!cs->tx_skb) return; @@ -711,26 +759,31 @@ } void -hfc2bds0_interrupt(struct IsdnCardState *cs, u8 val) +hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val) { - u8 exval; + u_char exval; struct BCState *bcs; int count=15; if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "HFCD irq %x", val); - + debugl1(cs, "HFCD irq %x %s", val, + test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ? + "locked" : "unlocked"); val &= cs->hw.hfcD.int_m1; if (val & 0x40) { /* TE state machine irq */ - exval = hfcs_read_reg(cs, HFCD_STATES) & 0xf; + exval = cs->readisac(cs, HFCD_STATES) & 0xf; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcd.ph_state, exval); cs->dc.hfcd.ph_state = exval; - sched_d_event(cs, D_L1STATECHANGE); + schedule_event(cs, D_L1STATECHANGE); val &= ~0x40; } while (val) { + if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + cs->hw.hfcD.int_s1 |= val; + return; + } if (cs->hw.hfcD.int_s1 & 0x18) { exval = val; val = cs->hw.hfcD.int_s1; @@ -755,7 +808,23 @@ if (cs->debug) debugl1(cs, "hfcd spurious 0x01 IRQ"); } else { - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs,"fill_data %d blocked", bcs->channel); + } else { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs,"fill_data %d blocked", bcs->channel); + } else { + schedule_event(bcs, B_XMTBUFREADY); + } + } } } if (val & 0x02) { @@ -763,15 +832,60 @@ if (cs->debug) debugl1(cs, "hfcd spurious 0x02 IRQ"); } else { - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs,"fill_data %d blocked", bcs->channel); + } else { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs,"fill_data %d blocked", bcs->channel); + } else { + schedule_event(bcs, B_XMTBUFREADY); + } + } } } if (val & 0x20) { /* receive dframe */ receive_dmsg(cs); } if (val & 0x04) { /* dframe transmitted */ - xmit_xpr_d(cs); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else { + debugl1(cs, "hfc_fill_dfifo irq blocked"); + } + goto afterXPR; + } else { + dev_kfree_skb_irq(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else { + debugl1(cs, "hfc_fill_dfifo irq blocked"); + } + } else + schedule_event(cs, D_XMTBUFREADY); } + afterXPR: if (cs->hw.hfcD.int_s1 && count--) { val = cs->hw.hfcD.int_s1; cs->hw.hfcD.int_s1 = 0; @@ -787,36 +901,101 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_d(cs, skb); + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "hfc_fill_dfifo blocked"); + + } + spin_unlock_irqrestore(&cs->lock, flags); break; - case (PH_PULL |INDICATION): - xmit_pull_ind_d(cs, skb); + case (PH_PULL | INDICATION): + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + spin_unlock_irqrestore(&cs->lock, flags); + break; + } + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfc_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "hfc_fill_dfifo blocked"); + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_d(st); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (HW_RESET | REQUEST): - hfcs_write_reg(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */ + spin_lock_irqsave(&cs->lock, flags); + cs->writeisac(cs, HFCD_STATES, HFCD_LOAD_STATE | 3); /* HFC ST 3 */ udelay(6); - hfcs_write_reg(cs, HFCD_STATES, 3); /* HFC ST 2 */ + cs->writeisac(cs, HFCD_STATES, 3); /* HFC ST 2 */ cs->hw.hfcD.mst_m |= HFCD_MASTER; - hfcs_write_reg(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); - hfcs_write_reg(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION); + cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); + cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION); + spin_unlock_irqrestore(&cs->lock, flags); l1_msg(cs, HW_POWERUP | CONFIRM, NULL); break; case (HW_ENABLE | REQUEST): - hfcs_write_reg(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION); + spin_lock_irqsave(&cs->lock, flags); + cs->writeisac(cs, HFCD_STATES, HFCD_ACTIVATE | HFCD_DO_ACTION); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_DEACTIVATE | REQUEST): + spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcD.mst_m &= ~HFCD_MASTER; - hfcs_write_reg(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); + cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_INFO3 | REQUEST): + spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcD.mst_m |= HFCD_MASTER; - hfcs_write_reg(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); + cs->writeisac(cs, HFCD_MST_MODE, cs->hw.hfcD.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); break; default: if (cs->debug & L1_DEB_WARN) @@ -825,11 +1004,10 @@ } } -static int +void setstack_hfcd(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = HFCD_l1hw; - return 0; } static void @@ -852,30 +1030,21 @@ return(send); } -static struct bc_l1_ops hfcd_bc_l1_ops = { - .fill_fifo = hfc_fill_fifo, - .open = setstack_2b, - .close = close_2bs0, -}; - -static struct dc_l1_ops hfcd_dc_l1_ops = { - .fill_fifo = hfc_fill_dfifo, - .open = setstack_hfcd, - .bh_func = hfcd_bh, - .dbusy_func = hfc_dbusy_timer, -}; - void __init init2bds0(struct IsdnCardState *cs) { - dc_l1_init(cs, &hfcd_dc_l1_ops); - cs->bc_l1_ops = &hfcd_bc_l1_ops; + cs->setstack_d = setstack_hfcd; if (!cs->hw.hfcD.send) cs->hw.hfcD.send = init_send_hfcd(16); if (!cs->bcs[0].hw.hfc.send) cs->bcs[0].hw.hfc.send = init_send_hfcd(32); if (!cs->bcs[1].hw.hfc.send) cs->bcs[1].hw.hfc.send = init_send_hfcd(32); + cs->BC_Send_Data = &hfc_send_data; + cs->bcs[0].BC_SetStack = setstack_2b; + cs->bcs[1].BC_SetStack = setstack_2b; + cs->bcs[0].BC_Close = close_2bs0; + cs->bcs[1].BC_Close = close_2bs0; mode_2bs0(cs->bcs, 0, 0); mode_2bs0(cs->bcs + 1, 0, 1); } @@ -895,4 +1064,19 @@ kfree(cs->hw.hfcD.send); cs->hw.hfcD.send = NULL; } +} + +void +set_cs_func(struct IsdnCardState *cs) +{ + cs->readisac = &readreghfcd; + cs->writeisac = &writereghfcd; + cs->readisacfifo = &dummyf; + cs->writeisacfifo = &dummyf; + cs->BC_Read_Reg = &ReadReg; + cs->BC_Write_Reg = &WriteReg; + cs->dbusytimer.function = (void *) hfc_dbusy_timer; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); + INIT_WORK(&cs->tqueue, (void *)(void *) hfcd_bh, cs); } diff -Nru a/drivers/isdn/hisax/hfc_2bds0.h b/drivers/isdn/hisax/hfc_2bds0.h --- a/drivers/isdn/hisax/hfc_2bds0.h Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/hisax/hfc_2bds0.h Thu Feb 19 23:44:27 2004 @@ -1,4 +1,4 @@ -/* $Id: hfc_2bds0.h,v 1.4.6.2 2001/09/23 22:24:47 kai Exp $ +/* $Id: hfc_2bds0.h,v 1.6.2.2 2004/01/12 22:52:26 keil Exp $ * * specific defines for CCD's HFC 2BDS0 * @@ -124,5 +124,5 @@ extern void main_irq_2bds0(struct BCState *bcs); extern void init2bds0(struct IsdnCardState *cs); extern void release2bds0(struct IsdnCardState *cs); -extern void hfc2bds0_interrupt(struct IsdnCardState *cs, u8 val); +extern void hfc2bds0_interrupt(struct IsdnCardState *cs, u_char val); extern void set_cs_func(struct IsdnCardState *cs); diff -Nru a/drivers/isdn/hisax/hfc_2bs0.c b/drivers/isdn/hisax/hfc_2bs0.c --- a/drivers/isdn/hisax/hfc_2bs0.c Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/hfc_2bs0.c Thu Feb 19 23:44:23 2004 @@ -1,4 +1,4 @@ -/* $Id: hfc_2bs0.c,v 1.17.6.3 2001/09/23 22:24:47 kai Exp $ +/* $Id: hfc_2bs0.c,v 1.20.2.6 2004/02/11 13:21:33 keil Exp $ * * specific routines for CCD's HFC 2BS0 * @@ -17,26 +17,14 @@ #include "isdnl1.h" #include -static inline u8 -hfc_read_reg(struct IsdnCardState *cs, int data, u8 reg) -{ - return cs->bc_hw_ops->read_reg(cs, data, reg); -} - -static inline void -hfc_write_reg(struct IsdnCardState *cs, int data, u8 reg, u8 val) -{ - cs->bc_hw_ops->write_reg(cs, data, reg, val); -} - static inline int WaitForBusy(struct IsdnCardState *cs) { int to = 130; - u8 val; + u_char val; - while (!(hfc_read_reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) { - val = hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2 | + while (!(cs->BC_Read_Reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) { + val = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2 | (cs->hw.hfc.cip & 3)); udelay(1); to--; @@ -53,7 +41,7 @@ { int to = 125; - while ((hfc_read_reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) { + while ((cs->BC_Read_Reg(cs, HFC_STATUS, 0) & HFC_BUSY) && to) { udelay(1); to--; } @@ -79,14 +67,14 @@ } int -ReadZReg(struct BCState *bcs, u8 reg) +ReadZReg(struct BCState *bcs, u_char reg) { int val; WaitNoBusy(bcs->cs); - val = 256 * hfc_read_reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_HIGH); + val = 256 * bcs->cs->BC_Read_Reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_HIGH); WaitNoBusy(bcs->cs); - val += hfc_read_reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_LOW); + val += bcs->cs->BC_Read_Reg(bcs->cs, HFC_DATA, reg | HFC_CIP | HFC_Z_LOW); return (val); } @@ -96,21 +84,20 @@ struct IsdnCardState *cs = bcs->cs; int idx, cnt; int rcnt, z1, z2; - u8 cip, f1, f2; + u_char cip, f1, f2; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hfc_clear_fifo"); - cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel); if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) { - hfc_write_reg(cs, HFC_STATUS, cip, cip); + cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip); WaitForBusy(cs); } WaitNoBusy(cs); - f1 = hfc_read_reg(cs, HFC_DATA, cip); + f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip); cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel); WaitNoBusy(cs); - f2 = hfc_read_reg(cs, HFC_DATA, cip); + f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip); z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel)); z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel)); cnt = 32; @@ -129,21 +116,21 @@ cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel); idx = 0; while ((idx < rcnt) && WaitNoBusy(cs)) { - hfc_read_reg(cs, HFC_DATA_NODEB, cip); + cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip); idx++; } if (f1 != f2) { WaitNoBusy(cs); - hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | + cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | HFC_CHANNEL(bcs->channel)); WaitForBusy(cs); } cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel); WaitNoBusy(cs); - f1 = hfc_read_reg(cs, HFC_DATA, cip); + f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip); cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel); WaitNoBusy(cs); - f2 = hfc_read_reg(cs, HFC_DATA, cip); + f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip); z1 = ReadZReg(bcs, HFC_Z1 | HFC_REC | HFC_CHANNEL(bcs->channel)); z2 = ReadZReg(bcs, HFC_Z2 | HFC_REC | HFC_CHANNEL(bcs->channel)); } @@ -155,12 +142,12 @@ * hfc_empty_fifo(struct BCState *bcs, int count) { - u8 *ptr; + u_char *ptr; struct sk_buff *skb; struct IsdnCardState *cs = bcs->cs; int idx; int chksum; - u8 stat, cip; + u_char stat, cip; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hfc_empty_fifo"); @@ -170,9 +157,9 @@ debugl1(cs, "hfc_empty_fifo: incoming packet too large"); cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel); while ((idx++ < count) && WaitNoBusy(cs)) - hfc_read_reg(cs, HFC_DATA_NODEB, cip); + cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip); WaitNoBusy(cs); - stat = hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | + stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | HFC_CHANNEL(bcs->channel)); WaitForBusy(cs); return (NULL); @@ -182,9 +169,9 @@ debugl1(cs, "hfc_empty_fifo: incoming packet too small"); cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel); while ((idx++ < count) && WaitNoBusy(cs)) - hfc_read_reg(cs, HFC_DATA_NODEB, cip); + cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip); WaitNoBusy(cs); - stat = hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | + stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | HFC_CHANNEL(bcs->channel)); WaitForBusy(cs); #ifdef ERROR_STATISTIC @@ -203,7 +190,7 @@ idx = 0; cip = HFC_CIP | HFC_FIFO_OUT | HFC_REC | HFC_CHANNEL(bcs->channel); while ((idx < count) && WaitNoBusy(cs)) { - *ptr++ = hfc_read_reg(cs, HFC_DATA_NODEB, cip); + *ptr++ = cs->BC_Read_Reg(cs, HFC_DATA_NODEB, cip); idx++; } if (idx != count) { @@ -212,7 +199,7 @@ dev_kfree_skb_any(skb); if (bcs->mode != L1_MODE_TRANS) { WaitNoBusy(cs); - stat = hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | + stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | HFC_CHANNEL(bcs->channel)); WaitForBusy(cs); } @@ -220,11 +207,11 @@ } if (bcs->mode != L1_MODE_TRANS) { WaitNoBusy(cs); - chksum = (hfc_read_reg(cs, HFC_DATA, cip) << 8); + chksum = (cs->BC_Read_Reg(cs, HFC_DATA, cip) << 8); WaitNoBusy(cs); - chksum += hfc_read_reg(cs, HFC_DATA, cip); + chksum += cs->BC_Read_Reg(cs, HFC_DATA, cip); WaitNoBusy(cs); - stat = hfc_read_reg(cs, HFC_DATA, cip); + stat = cs->BC_Read_Reg(cs, HFC_DATA, cip); if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc_empty_fifo %d chksum %x stat %x", bcs->channel, chksum, stat); @@ -237,7 +224,7 @@ #endif } WaitNoBusy(cs); - stat = hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | + stat = cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F2_INC | HFC_REC | HFC_CHANNEL(bcs->channel)); WaitForBusy(cs); } @@ -249,10 +236,10 @@ hfc_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - int fcnt; - u_int idx, count; + int idx, fcnt; + int count; int z1, z2; - u8 cip; + u_char cip; if (!bcs->tx_skb) return; @@ -261,15 +248,15 @@ cip = HFC_CIP | HFC_F1 | HFC_SEND | HFC_CHANNEL(bcs->channel); if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) { - hfc_write_reg(cs, HFC_STATUS, cip, cip); + cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip); WaitForBusy(cs); } WaitNoBusy(cs); if (bcs->mode != L1_MODE_TRANS) { - bcs->hw.hfc.f1 = hfc_read_reg(cs, HFC_DATA, cip); + bcs->hw.hfc.f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip); cip = HFC_CIP | HFC_F2 | HFC_SEND | HFC_CHANNEL(bcs->channel); WaitNoBusy(cs); - bcs->hw.hfc.f2 = hfc_read_reg(cs, HFC_DATA, cip); + bcs->hw.hfc.f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip); bcs->hw.hfc.send[bcs->hw.hfc.f1] = ReadZReg(bcs, HFC_Z1 | HFC_SEND | HFC_CHANNEL(bcs->channel)); if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc_fill_fifo %d f1(%d) f2(%d) z1(%x)", @@ -305,7 +292,7 @@ cip = HFC_CIP | HFC_FIFO_IN | HFC_SEND | HFC_CHANNEL(bcs->channel); idx = 0; while ((idx < bcs->tx_skb->len) && WaitNoBusy(cs)) - hfc_write_reg(cs, HFC_DATA_NODEB, cip, bcs->tx_skb->data[idx++]); + cs->BC_Write_Reg(cs, HFC_DATA_NODEB, cip, bcs->tx_skb->data[idx++]); if (idx != bcs->tx_skb->len) { debugl1(cs, "FIFO Send BUSY error"); printk(KERN_WARNING "HFC S FIFO channel %d BUSY Error\n", bcs->channel); @@ -314,12 +301,20 @@ bcs->tx_cnt -= count; if (PACKET_NOACK == bcs->tx_skb->pkt_type) count = -1; - - xmit_complete_b(bcs); + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; if (bcs->mode != L1_MODE_TRANS) { WaitForBusy(cs); WaitNoBusy(cs); - hfc_read_reg(cs, HFC_DATA, HFC_CIP | HFC_F1_INC | HFC_SEND | HFC_CHANNEL(bcs->channel)); + cs->BC_Read_Reg(cs, HFC_DATA, HFC_CIP | HFC_F1_INC | HFC_SEND | HFC_CHANNEL(bcs->channel)); + } + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (count >= 0)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); } test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } @@ -331,7 +326,7 @@ { struct IsdnCardState *cs = bcs->cs; int z1, z2, rcnt; - u8 f1, f2, cip; + u_char f1, f2, cip; int receive, transmit, count = 5; struct sk_buff *skb; @@ -339,16 +334,16 @@ count--; cip = HFC_CIP | HFC_F1 | HFC_REC | HFC_CHANNEL(bcs->channel); if ((cip & 0xc3) != (cs->hw.hfc.cip & 0xc3)) { - hfc_write_reg(cs, HFC_STATUS, cip, cip); + cs->BC_Write_Reg(cs, HFC_STATUS, cip, cip); WaitForBusy(cs); } WaitNoBusy(cs); receive = 0; if (bcs->mode == L1_MODE_HDLC) { - f1 = hfc_read_reg(cs, HFC_DATA, cip); + f1 = cs->BC_Read_Reg(cs, HFC_DATA, cip); cip = HFC_CIP | HFC_F2 | HFC_REC | HFC_CHANNEL(bcs->channel); WaitNoBusy(cs); - f2 = hfc_read_reg(cs, HFC_DATA, cip); + f2 = cs->BC_Read_Reg(cs, HFC_DATA, cip); if (f1 != f2) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc rec %d f1(%d) f2(%d)", @@ -368,14 +363,14 @@ if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfc rec %d z1(%x) z2(%x) cnt(%d)", bcs->channel, z1, z2, rcnt); + /* sti(); */ if ((skb = hfc_empty_fifo(bcs, rcnt))) { skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + schedule_event(bcs, B_RCVBUFREADY); } } receive = 1; } - udelay(1); if (bcs->tx_skb) { transmit = 1; test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); @@ -391,7 +386,7 @@ transmit = 0; } else { transmit = 0; - sched_b_event(bcs, B_XMTBUFREADY); + schedule_event(bcs, B_XMTBUFREADY); } } if ((receive || transmit) && count) @@ -423,7 +418,7 @@ break; case (L1_MODE_TRANS): cs->hw.hfc.ctmt &= ~(1 << bc); /* set HDLC mode */ - hfc_write_reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt); + cs->BC_Write_Reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt); hfc_clear_fifo(bcs); /* complete fifo clear */ if (bc) { cs->hw.hfc.ctmt |= 1; @@ -447,8 +442,8 @@ } break; } - hfc_write_reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt); - cs->dc_hw_ops->write_reg(cs, ISAC_SPCR, cs->hw.hfc.isac_spcr); + cs->BC_Write_Reg(cs, HFC_STATUS, cs->hw.hfc.ctmt, cs->hw.hfc.ctmt); + cs->writeisac(cs, ISAC_SPCR, cs->hw.hfc.isac_spcr); if (mode == L1_MODE_HDLC) hfc_clear_fifo(bcs); } @@ -456,31 +451,57 @@ static void hfc_l2l1(struct PStack *st, int pr, void *arg) { - struct sk_buff *skb = arg; + struct BCState *bcs = st->l1.bcs; + struct sk_buff *skb = arg; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); + } else { + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - mode_hfc(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + mode_hfc(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - mode_hfc(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + mode_hfc(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -523,7 +544,7 @@ if (open_hfcstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = hfc_l2l1; + st->l2.l2l1 = hfc_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); @@ -544,18 +565,16 @@ bcs->hw.hfc.send[i] = 0x1fff; } -static struct bc_l1_ops hfc_l1_ops = { - .fill_fifo = hfc_fill_fifo, - .open = setstack_hfc, - .close = close_hfcstate, -}; - void __init inithfc(struct IsdnCardState *cs) { init_send(&cs->bcs[0]); init_send(&cs->bcs[1]); - cs->bc_l1_ops = &hfc_l1_ops; + cs->BC_Send_Data = &hfc_fill_fifo; + cs->bcs[0].BC_SetStack = setstack_hfc; + cs->bcs[1].BC_SetStack = setstack_hfc; + cs->bcs[0].BC_Close = close_hfcstate; + cs->bcs[1].BC_Close = close_hfcstate; mode_hfc(cs->bcs, 0, 0); mode_hfc(cs->bcs + 1, 0, 0); } @@ -571,11 +590,4 @@ kfree(cs->bcs[1].hw.hfc.send); cs->bcs[1].hw.hfc.send = NULL; } -} - -int -hfc_setup(struct IsdnCardState *cs, struct bc_hw_ops *hfc_ops) -{ - cs->bc_hw_ops = hfc_ops; - return 0; } diff -Nru a/drivers/isdn/hisax/hfc_2bs0.h b/drivers/isdn/hisax/hfc_2bs0.h --- a/drivers/isdn/hisax/hfc_2bs0.h Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/hfc_2bs0.h Thu Feb 19 23:44:23 2004 @@ -1,4 +1,4 @@ -/* $Id: hfc_2bs0.h,v 1.3.6.2 2001/09/23 22:24:47 kai Exp $ +/* $Id: hfc_2bs0.h,v 1.5.2.2 2004/01/12 22:52:26 keil Exp $ * * specific defines for CCD's HFC 2BS0 * @@ -58,4 +58,3 @@ extern void main_irq_hfc(struct BCState *bcs); extern void inithfc(struct IsdnCardState *cs); extern void releasehfc(struct IsdnCardState *cs); -extern int hfc_setup(struct IsdnCardState *cs, struct bc_hw_ops *hfc_ops); diff -Nru a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c --- a/drivers/isdn/hisax/hfc_pci.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hisax/hfc_pci.c Thu Feb 19 23:44:24 2004 @@ -1,4 +1,4 @@ -/* $Id: hfc_pci.c,v 1.34.6.8 2001/09/23 22:24:47 kai Exp $ +/* $Id: hfc_pci.c,v 1.48.2.4 2004/02/11 13:21:33 keil Exp $ * * low level driver for CCD´s hfc-pci based cards * @@ -25,7 +25,7 @@ extern const char *CardType[]; -static const char *hfcpci_revision = "$Revision: 1.34.6.8 $"; +static const char *hfcpci_revision = "$Revision: 1.48.2.4 $"; /* table entry in the PCI devices list */ typedef struct { @@ -65,45 +65,47 @@ }; +#if CONFIG_PCI + /******************************************/ /* free hardware resources used by driver */ /******************************************/ -static void -hfcpci_release(struct IsdnCardState *cs) +void +release_io_hfcpci(struct IsdnCardState *cs) { printk(KERN_INFO "HiSax: release hfcpci at %p\n", cs->hw.hfcpci.pci_io); - cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */ + cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */ Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); - Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ - Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */ - pci_disable_device(cs->hw.hfcpci.pdev); + Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */ + mdelay(10); + Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */ + mdelay(10); + Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); + pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, 0); /* disable memory mapped ports + busmaster */ del_timer(&cs->hw.hfcpci.timer); - pci_free_consistent(cs->hw.hfcpci.pdev, 32768, cs->hw.hfcpci.fifos, cs->hw.hfcpci.fifos_dma); - hisax_release_resources(cs); + kfree(cs->hw.hfcpci.share_start); + cs->hw.hfcpci.share_start = NULL; + iounmap((void *)cs->hw.hfcpci.pci_io); } /********************************************************************************/ /* function called to reset the HFC PCI chip. A complete software reset of chip */ /* and fifos is done. */ /********************************************************************************/ -static int -hfcpci_reset(struct IsdnCardState *cs) +static void +reset_hfcpci(struct IsdnCardState *cs) { - pci_disable_device(cs->hw.hfcpci.pdev); + pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */ cs->hw.hfcpci.int_m2 = 0; /* interrupt output off ! */ Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); printk(KERN_INFO "HFC_PCI: resetting card\n"); - pci_set_master(cs->hw.hfcpci.pdev); + pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO + PCI_ENA_MASTER); /* enable memory ports + busmaster */ Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET); /* Reset On */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ + mdelay(10); Write_hfc(cs, HFCPCI_CIRM, 0); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */ + mdelay(10); if (Read_hfc(cs, HFCPCI_STATUS) & 2) printk(KERN_WARNING "HFC-PCI init bit busy\n"); @@ -156,9 +158,7 @@ /* Finally enable IRQ output */ cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE; Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); - if (Read_hfc(cs, HFCPCI_INT_S2)); - - return 0; + if (Read_hfc(cs, HFCPCI_INT_S1)); } /***************************************************/ @@ -174,6 +174,27 @@ */ } + +/*********************************/ +/* schedule a new D-channel task */ +/*********************************/ +static void +sched_event_D_pci(struct IsdnCardState *cs, int event) +{ + test_and_set_bit(event, &cs->event); + schedule_work(&cs->tqueue); +} + +/*********************************/ +/* schedule a new b_channel task */ +/*********************************/ +static void +hfcpci_sched_event(struct BCState *bcs, int event) +{ + test_and_set_bit(event, &bcs->event); + schedule_work(&bcs->tqueue); +} + /************************************************/ /* select a b-channel entry matching and active */ /************************************************/ @@ -193,7 +214,7 @@ /* clear the desired B-channel rx fifo */ /***************************************/ static void hfcpci_clear_fifo_rx(struct IsdnCardState *cs, int fifo) -{ u8 fifo_state; +{ u_char fifo_state; bzfifo_type *bzr; if (fifo) { @@ -207,7 +228,7 @@ cs->hw.hfcpci.fifo_en ^= fifo_state; Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); cs->hw.hfcpci.last_bfifo_cnt[fifo] = 0; - bzr->za[MAX_B_FRAMES].z1 = cpu_to_le16(B_FIFO_SIZE + B_SUB_VAL - 1); + bzr->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1; bzr->za[MAX_B_FRAMES].z2 = bzr->za[MAX_B_FRAMES].z1; bzr->f1 = MAX_B_FRAMES; bzr->f2 = bzr->f1; /* init F pointers to remain constant */ @@ -220,7 +241,7 @@ /* clear the desired B-channel tx fifo */ /***************************************/ static void hfcpci_clear_fifo_tx(struct IsdnCardState *cs, int fifo) -{ u8 fifo_state; +{ u_char fifo_state; bzfifo_type *bzt; if (fifo) { @@ -233,7 +254,7 @@ if (fifo_state) cs->hw.hfcpci.fifo_en ^= fifo_state; Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); - bzt->za[MAX_B_FRAMES].z1 = cpu_to_le16(B_FIFO_SIZE + B_SUB_VAL - 1); + bzt->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1; bzt->za[MAX_B_FRAMES].z2 = bzt->za[MAX_B_FRAMES].z1; bzt->f1 = MAX_B_FRAMES; bzt->f2 = bzt->f1; /* init F pointers to remain constant */ @@ -247,9 +268,9 @@ /*********************************************/ static struct sk_buff * -hfcpci_empty_fifo(struct BCState *bcs, bzfifo_type * bz, u8 * bdata, int count) +hfcpci_empty_fifo(struct BCState *bcs, bzfifo_type * bz, u_char * bdata, int count) { - u8 *ptr, *ptr1, new_f2; + u_char *ptr, *ptr1, new_f2; struct sk_buff *skb; struct IsdnCardState *cs = bcs->cs; int total, maxlen, new_z2; @@ -258,18 +279,18 @@ if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "hfcpci_empty_fifo"); zp = &bz->za[bz->f2]; /* point to Z-Regs */ - new_z2 = le16_to_cpu(zp->z2) + count; /* new position in fifo */ + new_z2 = zp->z2 + count; /* new position in fifo */ if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) new_z2 -= B_FIFO_SIZE; /* buffer wrap */ new_f2 = (bz->f2 + 1) & MAX_B_FRAMES; if ((count > HSCX_BUFMAX + 3) || (count < 4) || - (*(bdata + (le16_to_cpu(zp->z1) - B_SUB_VAL)))) { + (*(bdata + (zp->z1 - B_SUB_VAL)))) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfcpci_empty_fifo: incoming packet invalid length %d or crc", count); #ifdef ERROR_STATISTIC bcs->err_inv++; #endif - bz->za[new_f2].z2 = cpu_to_le16(new_z2); + bz->za[new_f2].z2 = new_z2; bz->f2 = new_f2; /* next buffer */ skb = NULL; } else if (!(skb = dev_alloc_skb(count - 3))) @@ -279,12 +300,12 @@ count -= 3; ptr = skb_put(skb, count); - if (le16_to_cpu(zp->z2) + count <= B_FIFO_SIZE + B_SUB_VAL) + if (zp->z2 + count <= B_FIFO_SIZE + B_SUB_VAL) maxlen = count; /* complete transfer */ else - maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(zp->z2); /* maximum */ + maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */ - ptr1 = bdata + (le16_to_cpu(zp->z2) - B_SUB_VAL); /* start of data */ + ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */ memcpy(ptr, ptr1, maxlen); /* copy data */ count -= maxlen; @@ -293,7 +314,7 @@ ptr1 = bdata; /* start of buffer */ memcpy(ptr, ptr1, count); /* rest */ } - bz->za[new_f2].z2 = cpu_to_le16(new_z2); + bz->za[new_f2].z2 = new_z2; bz->f2 = new_f2; /* next buffer */ } @@ -311,41 +332,45 @@ int maxlen; int rcnt, total; int count = 5; - u8 *ptr, *ptr1; + u_char *ptr, *ptr1; dfifo_type *df; z_type *zp; df = &((fifo_area *) (cs->hw.hfcpci.fifos))->d_chan.d_rx; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "rec_dmsg blocked"); + return (1); + } while (((df->f1 & D_FREG_MASK) != (df->f2 & D_FREG_MASK)) && count--) { zp = &df->za[df->f2 & D_FREG_MASK]; - rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2); + rcnt = zp->z1 - zp->z2; if (rcnt < 0) rcnt += D_FIFO_SIZE; rcnt++; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)", - df->f1, df->f2, le16_to_cpu(zp->z1), le16_to_cpu(zp->z2), rcnt); + df->f1, df->f2, zp->z1, zp->z2, rcnt); if ((rcnt > MAX_DFRAME_LEN + 3) || (rcnt < 4) || - (df->data[le16_to_cpu(zp->z1)])) { + (df->data[zp->z1])) { if (cs->debug & L1_DEB_WARN) - debugl1(cs, "empty_fifo hfcpci paket inv. len %d or crc %d", rcnt, df->data[le16_to_cpu(zp->z1)]); + debugl1(cs, "empty_fifo hfcpci paket inv. len %d or crc %d", rcnt, df->data[zp->z1]); #ifdef ERROR_STATISTIC cs->err_rx++; #endif df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1); /* next buffer */ - df->za[df->f2 & D_FREG_MASK].z2 = cpu_to_le16((le16_to_cpu(zp->z2) + rcnt) & (D_FIFO_SIZE - 1)); + df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + rcnt) & (D_FIFO_SIZE - 1); } else if ((skb = dev_alloc_skb(rcnt - 3))) { total = rcnt; rcnt -= 3; ptr = skb_put(skb, rcnt); - if ((le16_to_cpu(zp->z2) + rcnt) <= D_FIFO_SIZE) + if (zp->z2 + rcnt <= D_FIFO_SIZE) maxlen = rcnt; /* complete transfer */ else - maxlen = D_FIFO_SIZE - le16_to_cpu(zp->z2); /* maximum */ + maxlen = D_FIFO_SIZE - zp->z2; /* maximum */ - ptr1 = df->data + le16_to_cpu(zp->z2); /* start of data */ + ptr1 = df->data + zp->z2; /* start of data */ memcpy(ptr, ptr1, maxlen); /* copy data */ rcnt -= maxlen; @@ -355,13 +380,14 @@ memcpy(ptr, ptr1, rcnt); /* rest */ } df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1); /* next buffer */ - df->za[df->f2 & D_FREG_MASK].z2 = cpu_to_le16((le16_to_cpu(zp->z2) + total) & (D_FIFO_SIZE - 1)); + df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + total) & (D_FIFO_SIZE - 1); skb_queue_tail(&cs->rq, skb); - sched_d_event(cs, D_RCVBUFREADY); + sched_event_D_pci(cs, D_RCVBUFREADY); } else printk(KERN_WARNING "HFC-PCI: D receive out of memory\n"); } + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); return (1); } @@ -369,17 +395,17 @@ /* check for transparent receive data and read max one threshold size if avail */ /*******************************************************************************/ int -hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type * bz, u8 * bdata) +hfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type * bz, u_char * bdata) { unsigned short *z1r, *z2r; int new_z2, fcnt, maxlen; struct sk_buff *skb; - u8 *ptr, *ptr1; + u_char *ptr, *ptr1; z1r = &bz->za[MAX_B_FRAMES].z1; /* pointer to z reg */ z2r = z1r + 1; - if (!(fcnt = le16_to_cpu(*z1r) - le16_to_cpu(*z2r))) + if (!(fcnt = *z1r - *z2r)) return (0); /* no data avail */ if (fcnt <= 0) @@ -387,7 +413,7 @@ if (fcnt > HFCPCI_BTRANS_THRESHOLD) fcnt = HFCPCI_BTRANS_THRESHOLD; /* limit size */ - new_z2 = le16_to_cpu(*z2r) + fcnt; /* new position in fifo */ + new_z2 = *z2r + fcnt; /* new position in fifo */ if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) new_z2 -= B_FIFO_SIZE; /* buffer wrap */ @@ -395,12 +421,12 @@ printk(KERN_WARNING "HFCPCI: receive out of memory\n"); else { ptr = skb_put(skb, fcnt); - if (le16_to_cpu(*z2r) + fcnt <= B_FIFO_SIZE + B_SUB_VAL) + if (*z2r + fcnt <= B_FIFO_SIZE + B_SUB_VAL) maxlen = fcnt; /* complete transfer */ else - maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(*z2r); /* maximum */ + maxlen = B_FIFO_SIZE + B_SUB_VAL - *z2r; /* maximum */ - ptr1 = bdata + (le16_to_cpu(*z2r) - B_SUB_VAL); /* start of data */ + ptr1 = bdata + (*z2r - B_SUB_VAL); /* start of data */ memcpy(ptr, ptr1, maxlen); /* copy data */ fcnt -= maxlen; @@ -410,10 +436,10 @@ memcpy(ptr, ptr1, fcnt); /* rest */ } skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + hfcpci_sched_event(bcs, B_RCVBUFREADY); } - *z2r = cpu_to_le16(new_z2); /* new position */ + *z2r = new_z2; /* new position */ return (1); } /* hfcpci_empty_fifo_trans */ @@ -428,9 +454,10 @@ int receive, count = 5; struct sk_buff *skb; bzfifo_type *bz; - u8 *bdata; + u_char *bdata; z_type *zp; + if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) { bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2; bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2; @@ -442,22 +469,26 @@ } Begin: count--; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "rec_data %d blocked", bcs->channel); + return; + } if (bz->f1 != bz->f2) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci rec %d f1(%d) f2(%d)", bcs->channel, bz->f1, bz->f2); zp = &bz->za[bz->f2]; - rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2); + rcnt = zp->z1 - zp->z2; if (rcnt < 0) rcnt += B_FIFO_SIZE; rcnt++; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci rec %d z1(%x) z2(%x) cnt(%d)", - bcs->channel, le16_to_cpu(zp->z1), le16_to_cpu(zp->z2), rcnt); + bcs->channel, zp->z1, zp->z2, rcnt); if ((skb = hfcpci_empty_fifo(bcs, bz, bdata, rcnt))) { skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + hfcpci_sched_event(bcs, B_RCVBUFREADY); } rcnt = bz->f1 - bz->f2; if (rcnt < 0) @@ -475,7 +506,7 @@ receive = hfcpci_empty_fifo_trans(bcs, bz, bdata); else receive = 0; - + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); if (count && receive) goto Begin; return; @@ -487,10 +518,10 @@ static void hfcpci_fill_dfifo(struct IsdnCardState *cs) { - int fcnt, new_z1, maxlen; - u_int count; + int fcnt; + int count, new_z1, maxlen; dfifo_type *df; - u8 *src, *dst, new_f1; + u_char *src, *dst, new_f1; if (!cs->tx_skb) return; @@ -502,7 +533,7 @@ if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci_fill_Dfifo f1(%d) f2(%d) z1(f1)(%x)", df->f1, df->f2, - le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1)); + df->za[df->f1 & D_FREG_MASK].z1); fcnt = df->f1 - df->f2; /* frame count actually buffered */ if (fcnt < 0) fcnt += (MAX_D_FRAMES + 1); /* if wrap around */ @@ -515,7 +546,7 @@ return; } /* now determine free bytes in FIFO buffer */ - count = le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z2) - le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1); + count = df->za[df->f2 & D_FREG_MASK].z2 - df->za[df->f1 & D_FREG_MASK].z1 - 1; if (count <= 0) count += D_FIFO_SIZE; /* count now contains available bytes */ @@ -528,12 +559,12 @@ return; } count = cs->tx_skb->len; /* get frame len */ - new_z1 = (le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1) + count) & (D_FIFO_SIZE - 1); + new_z1 = (df->za[df->f1 & D_FREG_MASK].z1 + count) & (D_FIFO_SIZE - 1); new_f1 = ((df->f1 + 1) & D_FREG_MASK) | (D_FREG_MASK + 1); src = cs->tx_skb->data; /* source pointer */ - dst = df->data + le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1); - maxlen = D_FIFO_SIZE - le16_to_cpu(df->za[df->f1 & D_FREG_MASK].z1); /* end fifo */ - if (maxlen > (int)count) + dst = df->data + df->za[df->f1 & D_FREG_MASK].z1; + maxlen = D_FIFO_SIZE - df->za[df->f1 & D_FREG_MASK].z1; /* end fifo */ + if (maxlen > count) maxlen = count; /* limit size */ memcpy(dst, src, maxlen); /* first copy */ @@ -543,8 +574,8 @@ src += maxlen; /* new position */ memcpy(dst, src, count); } - df->za[new_f1 & D_FREG_MASK].z1 = cpu_to_le16(new_z1); /* for next buffer */ - df->za[df->f1 & D_FREG_MASK].z1 = cpu_to_le16(new_z1); /* new pos actual buffer */ + df->za[new_f1 & D_FREG_MASK].z1 = new_z1; /* for next buffer */ + df->za[df->f1 & D_FREG_MASK].z1 = new_z1; /* new pos actual buffer */ df->f1 = new_f1; /* next frame */ dev_kfree_skb_any(cs->tx_skb); @@ -559,11 +590,11 @@ hfcpci_fill_fifo(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - int maxlen, fcnt, new_z1; - u_int count; + int maxlen, fcnt; + int count, new_z1; bzfifo_type *bz; - u8 *bdata; - u8 new_f1, *src, *dst; + u_char *bdata; + u_char new_f1, *src, *dst; unsigned short *z1t, *z2t; if (!bcs->tx_skb) @@ -584,24 +615,24 @@ z2t = z1t + 1; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci_fill_fifo_trans %d z1(%x) z2(%x)", - bcs->channel, le16_to_cpu(*z1t), le16_to_cpu(*z2t)); - fcnt = le16_to_cpu(*z2t) - le16_to_cpu(*z1t); + bcs->channel, *z1t, *z2t); + fcnt = *z2t - *z1t; if (fcnt <= 0) fcnt += B_FIFO_SIZE; /* fcnt contains available bytes in fifo */ fcnt = B_FIFO_SIZE - fcnt; /* remaining bytes to send */ while ((fcnt < 2 * HFCPCI_BTRANS_THRESHOLD) && (bcs->tx_skb)) { - if ((int)bcs->tx_skb->len < (B_FIFO_SIZE - fcnt)) { + if (bcs->tx_skb->len < B_FIFO_SIZE - fcnt) { /* data is suitable for fifo */ count = bcs->tx_skb->len; - new_z1 = le16_to_cpu(*z1t) + count; /* new buffer Position */ + new_z1 = *z1t + count; /* new buffer Position */ if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL)) new_z1 -= B_FIFO_SIZE; /* buffer wrap */ src = bcs->tx_skb->data; /* source pointer */ - dst = bdata + (le16_to_cpu(*z1t) - B_SUB_VAL); - maxlen = (B_FIFO_SIZE + B_SUB_VAL) - le16_to_cpu(*z1t); /* end of fifo */ - if (maxlen > (int)count) + dst = bdata + (*z1t - B_SUB_VAL); + maxlen = (B_FIFO_SIZE + B_SUB_VAL) - *z1t; /* end of fifo */ + if (maxlen > count) maxlen = count; /* limit size */ memcpy(dst, src, maxlen); /* first copy */ @@ -613,11 +644,20 @@ } bcs->tx_cnt -= bcs->tx_skb->len; fcnt += bcs->tx_skb->len; - *z1t = cpu_to_le16(new_z1); /* now send data */ + *z1t = new_z1; /* now send data */ } else if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded", bcs->channel, bcs->tx_skb->len); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->tx_skb->len; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = skb_dequeue(&bcs->squeue); /* fetch next data */ } @@ -627,7 +667,7 @@ if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hfcpci_fill_fifo_hdlc %d f1(%d) f2(%d) z1(f1)(%x)", bcs->channel, bz->f1, bz->f2, - le16_to_cpu(bz->za[bz->f1].z1)); + bz->za[bz->f1].z1); fcnt = bz->f1 - bz->f2; /* frame count actually buffered */ if (fcnt < 0) @@ -638,7 +678,7 @@ return; } /* now determine free bytes in FIFO buffer */ - count = le16_to_cpu(bz->za[bz->f1].z2) - le16_to_cpu(bz->za[bz->f1].z1); + count = bz->za[bz->f2].z2 - bz->za[bz->f1].z1 - 1; if (count <= 0) count += B_FIFO_SIZE; /* count now contains available bytes */ @@ -653,15 +693,15 @@ return; } count = bcs->tx_skb->len; /* get frame len */ - new_z1 = le16_to_cpu(bz->za[bz->f1].z1) + count; /* new buffer Position */ + new_z1 = bz->za[bz->f1].z1 + count; /* new buffer Position */ if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL)) new_z1 -= B_FIFO_SIZE; /* buffer wrap */ new_f1 = ((bz->f1 + 1) & MAX_B_FRAMES); src = bcs->tx_skb->data; /* source pointer */ - dst = bdata + (le16_to_cpu(bz->za[bz->f1].z1) - B_SUB_VAL); - maxlen = (B_FIFO_SIZE + B_SUB_VAL) - le16_to_cpu(bz->za[bz->f1].z1); /* end fifo */ - if (maxlen > (int)count) + dst = bdata + (bz->za[bz->f1].z1 - B_SUB_VAL); + maxlen = (B_FIFO_SIZE + B_SUB_VAL) - bz->za[bz->f1].z1; /* end fifo */ + if (maxlen > count) maxlen = count; /* limit size */ memcpy(dst, src, maxlen); /* first copy */ @@ -672,11 +712,20 @@ memcpy(dst, src, count); } bcs->tx_cnt -= bcs->tx_skb->len; - xmit_complete_b(bcs); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->tx_skb->len; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } - bz->za[new_f1].z1 = cpu_to_le16(new_z1); /* for next buffer */ + bz->za[new_f1].z1 = new_z1; /* for next buffer */ bz->f1 = new_f1; /* next frame */ + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); return; } @@ -696,7 +745,7 @@ st->l1.l1hw(st, pr, arg); break; case (PH_ACTIVATE | REQUEST): - L1L2(st, PH_ACTIVATE | CONFIRM, NULL); + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); break; case (PH_TESTLOOP | REQUEST): if (1 & (long) arg) @@ -722,10 +771,12 @@ static int hfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic) { - int i = *(unsigned int *) ic->parm.num; + u_long flags; + int i = *(unsigned int *) ic->parm.num; if ((ic->arg == 98) && (!(cs->hw.hfcpci.int_m1 & (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC + HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC)))) { + spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCPCI_CLKDEL, CLKDEL_NT); /* ST-Bit delay for NT-Mode */ Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 0); /* HFC ST G0 */ udelay(10); @@ -738,7 +789,8 @@ cs->dc.hfcpci.ph_state = 1; cs->hw.hfcpci.nt_mode = 1; cs->hw.hfcpci.nt_timer = 0; - cs->stlist->l1.l2l1 = dch_nt_l2l1; + cs->stlist->l2.l2l1 = dch_nt_l2l1; + spin_unlock_irqrestore(&cs->lock, flags); debugl1(cs, "NT mode activated"); return (0); } @@ -746,6 +798,7 @@ (cs->hw.hfcpci.nt_mode) || (ic->arg != 12)) return (-EINVAL); + spin_lock_irqsave(&cs->lock, flags); if (i) { cs->logecho = 1; cs->hw.hfcpci.trm |= 0x20; /* enable echo chan */ @@ -768,6 +821,7 @@ Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm); Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en); Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + spin_unlock_irqrestore(&cs->lock, flags); return (0); } /* hfcpci_auxcmd */ @@ -780,50 +834,54 @@ int rcnt; int receive, count = 5; bzfifo_type *bz; - u8 *bdata; + u_char *bdata; z_type *zp; - u8 *ptr, *ptr1, new_f2; + u_char *ptr, *ptr1, new_f2; int total, maxlen, new_z2; - u8 e_buffer[256]; + u_char e_buffer[256]; bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2; bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2; Begin: count--; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "echo_rec_data blocked"); + return; + } if (bz->f1 != bz->f2) { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci e_rec f1(%d) f2(%d)", bz->f1, bz->f2); zp = &bz->za[bz->f2]; - rcnt = le16_to_cpu(zp->z1) - le16_to_cpu(zp->z2); + rcnt = zp->z1 - zp->z2; if (rcnt < 0) rcnt += B_FIFO_SIZE; rcnt++; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "hfcpci e_rec z1(%x) z2(%x) cnt(%d)", - le16_to_cpu(zp->z1), le16_to_cpu(zp->z2), rcnt); - new_z2 = le16_to_cpu(zp->z2) + rcnt; /* new position in fifo */ + zp->z1, zp->z2, rcnt); + new_z2 = zp->z2 + rcnt; /* new position in fifo */ if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL)) new_z2 -= B_FIFO_SIZE; /* buffer wrap */ new_f2 = (bz->f2 + 1) & MAX_B_FRAMES; if ((rcnt > 256 + 3) || (count < 4) || - (*(bdata + (le16_to_cpu(zp->z1) - B_SUB_VAL)))) { + (*(bdata + (zp->z1 - B_SUB_VAL)))) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt); - bz->za[new_f2].z2 = cpu_to_le16(new_z2); + bz->za[new_f2].z2 = new_z2; bz->f2 = new_f2; /* next buffer */ } else { total = rcnt; rcnt -= 3; ptr = e_buffer; - if (le16_to_cpu(zp->z2) <= (B_FIFO_SIZE + B_SUB_VAL)) + if (zp->z2 <= B_FIFO_SIZE + B_SUB_VAL) maxlen = rcnt; /* complete transfer */ else - maxlen = B_FIFO_SIZE + B_SUB_VAL - le16_to_cpu(zp->z2); /* maximum */ + maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2; /* maximum */ - ptr1 = bdata + (le16_to_cpu(zp->z2) - B_SUB_VAL); /* start of data */ + ptr1 = bdata + (zp->z2 - B_SUB_VAL); /* start of data */ memcpy(ptr, ptr1, maxlen); /* copy data */ rcnt -= maxlen; @@ -832,7 +890,7 @@ ptr1 = bdata; /* start of buffer */ memcpy(ptr, ptr1, rcnt); /* rest */ } - bz->za[new_f2].z2 = cpu_to_le16(new_z2); + bz->za[new_f2].z2 = new_z2; bz->f2 = new_f2; /* next buffer */ if (cs->debug & DEB_DLOG_HEX) { ptr = cs->dlog; @@ -861,6 +919,7 @@ receive = 0; } else receive = 0; + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); if (count && receive) goto Begin; return; @@ -872,28 +931,30 @@ static irqreturn_t hfcpci_interrupt(int intno, void *dev_id, struct pt_regs *regs) { + u_long flags; struct IsdnCardState *cs = dev_id; - u8 exval; + u_char exval; struct BCState *bcs; int count = 15; - u8 val, stat; + u_char val, stat; - if (!cs) { - printk(KERN_WARNING "HFC-PCI: Spurious interrupt!\n"); - return IRQ_NONE; + if (!(cs->hw.hfcpci.int_m2 & 0x08)) { + debugl1(cs, "HFC-PCI: int_m2 %x not initialised", cs->hw.hfcpci.int_m2); + return IRQ_NONE; /* not initialised */ } - if (!(cs->hw.hfcpci.int_m2 & 0x08)) - return IRQ_NONE; /* not initialised */ - + spin_lock_irqsave(&cs->lock, flags); if (HFCPCI_ANYINT & (stat = Read_hfc(cs, HFCPCI_STATUS))) { val = Read_hfc(cs, HFCPCI_INT_S1); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "HFC-PCI: stat(%02x) s1(%02x)", stat, val); - } else + } else { + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_NONE; - + } if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "HFC-PCI irq %x", val); + debugl1(cs, "HFC-PCI irq %x %s", val, + test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ? + "locked" : "unlocked"); val &= cs->hw.hfcpci.int_m1; if (val & 0x40) { /* state machine irq */ exval = Read_hfc(cs, HFCPCI_STATES) & 0xf; @@ -901,18 +962,23 @@ debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcpci.ph_state, exval); cs->dc.hfcpci.ph_state = exval; - sched_d_event(cs, D_L1STATECHANGE); + sched_event_D_pci(cs, D_L1STATECHANGE); val &= ~0x40; } if (val & 0x80) { /* timer irq */ if (cs->hw.hfcpci.nt_mode) { if ((--cs->hw.hfcpci.nt_timer) < 0) - sched_d_event(cs, D_L1STATECHANGE); + sched_event_D_pci(cs, D_L1STATECHANGE); } val &= ~0x80; Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER); } while (val) { + if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + cs->hw.hfcpci.int_s1 |= val; + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; + } if (cs->hw.hfcpci.int_s1 & 0x18) { exval = val; val = cs->hw.hfcpci.int_s1; @@ -939,7 +1005,23 @@ if (cs->debug) debugl1(cs, "hfcpci spurious 0x01 IRQ"); } else { - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + hfcpci_sched_event(bcs, B_XMTBUFREADY); + } + } } } if (val & 0x02) { @@ -947,15 +1029,60 @@ if (cs->debug) debugl1(cs, "hfcpci spurious 0x02 IRQ"); } else { - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + hfcpci_sched_event(bcs, B_XMTBUFREADY); + } + } } } if (val & 0x20) { /* receive dframe */ receive_dmsg(cs); } if (val & 0x04) { /* dframe transmitted */ - xmit_xpr_d(cs); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + sched_event_D_pci(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else { + debugl1(cs, "hfcpci_fill_dfifo irq blocked"); + } + goto afterXPR; + } else { + dev_kfree_skb_irq(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else { + debugl1(cs, "hfcpci_fill_dfifo irq blocked"); + } + } else + sched_event_D_pci(cs, D_XMTBUFREADY); } + afterXPR: if (cs->hw.hfcpci.int_s1 && count--) { val = cs->hw.hfcpci.int_s1; cs->hw.hfcpci.int_s1 = 0; @@ -964,6 +1091,7 @@ } else val = 0; } + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } @@ -981,40 +1109,106 @@ static void HFCPCI_l1hw(struct PStack *st, int pr, void *arg) { + u_long flags; struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_d(cs, skb); + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "hfcpci_fill_dfifo blocked"); + + } + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_d(cs, skb); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + spin_unlock_irqrestore(&cs->lock, flags); + break; + } + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "hfcpci_fill_dfifo blocked"); + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_d(st); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (HW_RESET | REQUEST): + spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 3); /* HFC ST 3 */ udelay(6); Write_hfc(cs, HFCPCI_STATES, 3); /* HFC ST 2 */ cs->hw.hfcpci.mst_m |= HFCPCI_MASTER; Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); Write_hfc(cs, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION); + spin_unlock_irqrestore(&cs->lock, flags); l1_msg(cs, HW_POWERUP | CONFIRM, NULL); break; case (HW_ENABLE | REQUEST): + spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCPCI_STATES, HFCPCI_DO_ACTION); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_DEACTIVATE | REQUEST): + spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcpci.mst_m &= ~HFCPCI_MASTER; Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_INFO3 | REQUEST): + spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcpci.mst_m |= HFCPCI_MASTER; Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_TESTLOOP | REQUEST): + spin_lock_irqsave(&cs->lock, flags); switch ((int) arg) { case (1): Write_hfc(cs, HFCPCI_B1_SSL, 0x80); /* tx slot */ @@ -1031,12 +1225,14 @@ break; default: + spin_unlock_irqrestore(&cs->lock, flags); if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfcpci_l1hw loop invalid %4x", (int) arg); return; } cs->hw.hfcpci.trm |= 0x80; /* enable IOM-loop */ Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm); + spin_unlock_irqrestore(&cs->lock, flags); break; default: if (cs->debug & L1_DEB_WARN) @@ -1048,11 +1244,25 @@ /***********************************************/ /* called during init setting l1 stack pointer */ /***********************************************/ -static int +void setstack_hfcpci(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = HFCPCI_l1hw; - return 0; +} + +/**************************************/ +/* send B-channel data if not blocked */ +/**************************************/ +static void +hfcpci_send_data(struct BCState *bcs) +{ + struct IsdnCardState *cs = bcs->cs; + + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcpci_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "send_data %d blocked", bcs->channel); } /***************************************************************/ @@ -1182,31 +1392,58 @@ static void hfcpci_l2l1(struct PStack *st, int pr, void *arg) { - struct sk_buff *skb = arg; + struct BCState *bcs = st->l1.bcs; + u_long flags; + struct sk_buff *skb = arg; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; +// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + spin_unlock_irqrestore(&bcs->cs->lock, flags); + printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); + break; + } +// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->cs->BC_Send_Data(bcs); + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - mode_hfcpci(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + mode_hfcpci(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - mode_hfcpci(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + mode_hfcpci(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -1256,7 +1493,7 @@ if (open_hfcpcistate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = hfcpci_l2l1; + st->l2.l2l1 = hfcpci_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); @@ -1267,11 +1504,11 @@ /* handle L1 state changes */ /***************************/ static void -hfcpci_bh(void *data) +hfcpci_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; -/* struct PStack *stptr; - */ + u_long flags; +// struct PStack *stptr; + if (!cs) return; if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { @@ -1295,6 +1532,7 @@ default: break; } else { + spin_lock_irqsave(&cs->lock, flags); switch (cs->dc.hfcpci.ph_state) { case (2): if (cs->hw.hfcpci.nt_timer < 0) { @@ -1303,7 +1541,6 @@ Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); /* Clear already pending ints */ if (Read_hfc(cs, HFCPCI_INT_S1)); - Write_hfc(cs, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE); udelay(10); Write_hfc(cs, HFCPCI_STATES, 4); @@ -1329,6 +1566,7 @@ default: break; } + spin_unlock_irqrestore(&cs->lock, flags); } } if (test_and_clear_bit(D_RCVBUFREADY, &cs->event)) @@ -1337,18 +1575,6 @@ DChannel_proc_xmt(cs); } -static struct bc_l1_ops hfcpci_bc_l1_ops = { - .fill_fifo = hfcpci_fill_fifo, - .open = setstack_2b, - .close = close_hfcpci, -}; - -static struct dc_l1_ops hfcpci_dc_l1_ops = { - .fill_fifo = hfcpci_fill_dfifo, - .open = setstack_hfcpci, - .bh_func = hfcpci_bh, - .dbusy_func = hfcpci_dbusy_timer, -}; /********************************/ /* called for card init message */ @@ -1356,116 +1582,167 @@ void __init inithfcpci(struct IsdnCardState *cs) { - dc_l1_init(cs, &hfcpci_dc_l1_ops); - cs->bc_l1_ops = &hfcpci_bc_l1_ops; + cs->bcs[0].BC_SetStack = setstack_2b; + cs->bcs[1].BC_SetStack = setstack_2b; + cs->bcs[0].BC_Close = close_hfcpci; + cs->bcs[1].BC_Close = close_hfcpci; + cs->dbusytimer.function = (void *) hfcpci_dbusy_timer; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); mode_hfcpci(cs->bcs, 0, 0); mode_hfcpci(cs->bcs + 1, 0, 1); } -static void -hfcpci_init(struct IsdnCardState *cs) -{ - inithfcpci(cs); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ - /* now switch timer interrupt off */ - cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; - Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); - /* reinit mode reg */ - Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); -} -static struct card_ops hfcpci_ops = { - .init = hfcpci_init, - .reset = hfcpci_reset, - .release = hfcpci_release, - .irq_func = hfcpci_interrupt, -}; - -static int __init -niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev, int i) +/*******************************************/ +/* handle card messages from control layer */ +/*******************************************/ +static int +hfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - int rc; - - rc = -EBUSY; - if (pci_enable_device(pdev)) - goto err; - - pci_set_master(pdev); - - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.hfcpci.pdev = pdev; - - cs->hw.hfcpci.pci_io = request_mmio(&cs->rs, - pci_resource_start(pdev, 1), 128, - "hfc_pci"); - if (!cs->hw.hfcpci.pci_io) - goto err; - - /* Allocate memory for FIFOS */ - rc = -ENOMEM; - cs->hw.hfcpci.fifos = pci_alloc_consistent(pdev, 32768, - &cs->hw.hfcpci.fifos_dma); - if (!cs->hw.hfcpci.fifos) - goto err; - - pci_write_config_dword(cs->hw.hfcpci.pdev, 0x80, - (u_int)cs->hw.hfcpci.fifos_dma); - printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s name: %s\n", - id_list[i].vendor_name, id_list[i].card_name); - printk(KERN_INFO "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d\n", - (u_int) cs->hw.hfcpci.pci_io, (u_int) cs->hw.hfcpci.fifos, - (u_int) cs->hw.hfcpci.fifos_dma, cs->irq); - printk("ChipID: %x\n", Read_hfc(cs, HFCPCI_CHIP_ID)); - cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */ - cs->hw.hfcpci.int_m1 = 0; - Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); - Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); - /* At this point the needed PCI config is done */ - /* fifos are still not enabled */ + u_long flags; - init_timer(&cs->hw.hfcpci.timer); - cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer; - cs->hw.hfcpci.timer.data = (long) cs; - - hfcpci_reset(cs); - cs->auxcmd = &hfcpci_auxcmd; - cs->card_ops = &hfcpci_ops; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "HFCPCI: card_msg %x", mt); + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_hfcpci(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_RELEASE: + release_io_hfcpci(cs); + return (0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithfcpci(cs); + reset_hfcpci(cs); + spin_unlock_irqrestore(&cs->lock, flags); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ + /* now switch timer interrupt off */ + spin_lock_irqsave(&cs->lock, flags); + cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER; + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + /* reinit mode reg */ + Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_TEST: + return (0); + } + return (0); } + /* this variable is used as card index when more than one cards are present */ static struct pci_dev *dev_hfcpci __initdata = NULL; +#endif /* CONFIG_PCI */ + int __init setup_hfcpci(struct IsdnCard *card) { + u_long flags; struct IsdnCardState *cs = card->cs; char tmp[64]; int i; struct pci_dev *tmp_hfcpci = NULL; +#ifdef __BIG_ENDIAN +#error "not running on big endian machines now" +#endif strcpy(tmp, hfcpci_revision); printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp)); +#if CONFIG_PCI cs->hw.hfcpci.int_s1 = 0; cs->dc.hfcpci.ph_state = 0; cs->hw.hfcpci.fifo = 255; + if (cs->typ == ISDN_CTYPE_HFC_PCI) { + i = 0; + while (id_list[i].vendor_id) { + tmp_hfcpci = pci_find_device(id_list[i].vendor_id, + id_list[i].device_id, + dev_hfcpci); + i++; + if (tmp_hfcpci) { + if (pci_enable_device(tmp_hfcpci)) + continue; + pci_set_master(tmp_hfcpci); + if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[ 0].start & PCI_BASE_ADDRESS_IO_MASK))) + continue; + else + break; + } + } - for (i = 0; id_list[i].vendor_id; i++) { - tmp_hfcpci = pci_find_device(id_list[i].vendor_id, - id_list[i].device_id, - dev_hfcpci); - if (!tmp_hfcpci) - continue; - - if (niccy_pci_probe(card->cs, tmp_hfcpci, i) < 0) + if (tmp_hfcpci) { + i--; + dev_hfcpci = tmp_hfcpci; /* old device */ + cs->hw.hfcpci.dev = dev_hfcpci; + cs->irq = dev_hfcpci->irq; + if (!cs->irq) { + printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n"); + return (0); + } + cs->hw.hfcpci.pci_io = (char *) dev_hfcpci->resource[ 1].start; + printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name); + } else { + printk(KERN_WARNING "HFC-PCI: No PCI card found\n"); + return (0); + } + if (!cs->hw.hfcpci.pci_io) { + printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n"); + return (0); + } + /* Allocate memory for FIFOS */ + /* Because the HFC-PCI needs a 32K physical alignment, we */ + /* need to allocate the double mem and align the address */ + if (!(cs->hw.hfcpci.share_start = kmalloc(65536, GFP_KERNEL))) { + printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n"); return 0; - return 1; - } - return 0; + } + cs->hw.hfcpci.fifos = (void *) + (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000; + pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u_int) virt_to_bus(cs->hw.hfcpci.fifos)); + cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256); + printk(KERN_INFO + "HFC-PCI: defined at mem %#x fifo %#x(%#x) IRQ %d HZ %d\n", + (u_int) cs->hw.hfcpci.pci_io, + (u_int) cs->hw.hfcpci.fifos, + (u_int) virt_to_bus(cs->hw.hfcpci.fifos), + cs->irq, HZ); + spin_lock_irqsave(&cs->lock, flags); + pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO); /* enable memory mapped ports, disable busmaster */ + cs->hw.hfcpci.int_m2 = 0; /* disable alle interrupts */ + cs->hw.hfcpci.int_m1 = 0; + Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1); + Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2); + /* At this point the needed PCI config is done */ + /* fifos are still not enabled */ + INIT_WORK(&cs->tqueue, (void *)(void *) hfcpci_bh, cs); + cs->setstack_d = setstack_hfcpci; + cs->BC_Send_Data = &hfcpci_send_data; + cs->readisac = NULL; + cs->writeisac = NULL; + cs->readisacfifo = NULL; + cs->writeisacfifo = NULL; + cs->BC_Read_Reg = NULL; + cs->BC_Write_Reg = NULL; + cs->irq_func = &hfcpci_interrupt; + cs->irq_flags |= SA_SHIRQ; + cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer; + cs->hw.hfcpci.timer.data = (long) cs; + init_timer(&cs->hw.hfcpci.timer); + cs->cardmsg = &hfcpci_card_msg; + cs->auxcmd = &hfcpci_auxcmd; + spin_unlock_irqrestore(&cs->lock, flags); + return (1); + } else + return (0); /* no valid card type */ +#else + printk(KERN_WARNING "HFC-PCI: NO_PCI_BIOS\n"); + return (0); +#endif /* CONFIG_PCI */ } diff -Nru a/drivers/isdn/hisax/hfc_pci.h b/drivers/isdn/hisax/hfc_pci.h --- a/drivers/isdn/hisax/hfc_pci.h Thu Feb 19 23:44:25 2004 +++ b/drivers/isdn/hisax/hfc_pci.h Thu Feb 19 23:44:25 2004 @@ -1,4 +1,4 @@ -/* $Id: hfc_pci.h,v 1.8.6.2 2001/09/23 22:24:48 kai Exp $ +/* $Id: hfc_pci.h,v 1.10.2.2 2004/01/12 22:52:26 keil Exp $ * * specific defines for CCD's HFC 2BDS0 PCI chips * @@ -185,53 +185,51 @@ typedef struct { unsigned short z1; /* Z1 pointer 16 Bit */ unsigned short z2; /* Z2 pointer 16 Bit */ - } __attribute__((packed)) z_type; + } z_type; typedef struct { - u8 data[D_FIFO_SIZE]; /* FIFO data space */ - u8 fill1[0x20A0-D_FIFO_SIZE]; /* reserved, do not use */ - u8 f1,f2; /* f pointers */ - u8 fill2[0x20C0-0x20A2]; /* reserved, do not use */ + u_char data[D_FIFO_SIZE]; /* FIFO data space */ + u_char fill1[0x20A0-D_FIFO_SIZE]; /* reserved, do not use */ + u_char f1,f2; /* f pointers */ + u_char fill2[0x20C0-0x20A2]; /* reserved, do not use */ z_type za[MAX_D_FRAMES+1]; /* mask index with D_FREG_MASK for access */ - u8 fill3[0x4000-0x2100]; /* align 16K */ - } __attribute__((packed)) dfifo_type; + u_char fill3[0x4000-0x2100]; /* align 16K */ + } dfifo_type; typedef struct { z_type za[MAX_B_FRAMES+1]; /* only range 0x0..0x1F allowed */ - u8 f1,f2; /* f pointers */ - u8 fill[0x2100-0x2082]; /* alignment */ - } __attribute__((packed)) bzfifo_type; + u_char f1,f2; /* f pointers */ + u_char fill[0x2100-0x2082]; /* alignment */ + } bzfifo_type; typedef union { struct { dfifo_type d_tx; /* D-send channel */ dfifo_type d_rx; /* D-receive channel */ - } __attribute__((packed)) d_chan; + } d_chan; struct { - u8 fill1[0x200]; - u8 txdat_b1[B_FIFO_SIZE]; + u_char fill1[0x200]; + u_char txdat_b1[B_FIFO_SIZE]; bzfifo_type txbz_b1; bzfifo_type txbz_b2; - u8 txdat_b2[B_FIFO_SIZE]; + u_char txdat_b2[B_FIFO_SIZE]; - u8 fill2[D_FIFO_SIZE]; + u_char fill2[D_FIFO_SIZE]; - u8 rxdat_b1[B_FIFO_SIZE]; + u_char rxdat_b1[B_FIFO_SIZE]; bzfifo_type rxbz_b1; bzfifo_type rxbz_b2; - u8 rxdat_b2[B_FIFO_SIZE]; - } __attribute__((packed)) b_chans; - u8 fill[32768]; - } __attribute__((packed)) fifo_area; + u_char rxdat_b2[B_FIFO_SIZE]; + } b_chans; + u_char fill[32768]; + } fifo_area; -//#define Write_hfc(a,b,c) (*(((u8 *)a->hw.hfcpci.pci_io)+b) = c) -//#define Read_hfc(a,b) (*(((u8 *)a->hw.hfcpci.pci_io)+b)) -#define Write_hfc(a,b,c) writeb(c, ((u8 *)a->hw.hfcpci.pci_io)+b) -#define Read_hfc(a,b) readb(((u8 *)a->hw.hfcpci.pci_io)+b) +#define Write_hfc(a,b,c) (*(((u_char *)a->hw.hfcpci.pci_io)+b) = c) +#define Read_hfc(a,b) (*(((u_char *)a->hw.hfcpci.pci_io)+b)) extern void main_irq_hcpci(struct BCState *bcs); extern void inithfcpci(struct IsdnCardState *cs); diff -Nru a/drivers/isdn/hisax/hfc_sx.c b/drivers/isdn/hisax/hfc_sx.c --- a/drivers/isdn/hisax/hfc_sx.c Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/hfc_sx.c Thu Feb 19 23:44:23 2004 @@ -1,6 +1,6 @@ -/* $Id: hfc_sx.c,v 1.9.6.3 2001/09/23 22:24:48 kai Exp $ +/* $Id: hfc_sx.c,v 1.12.2.5 2004/02/11 13:21:33 keil Exp $ * - * level driver for CCD´s hfc-s+/sp based cards + * level driver for Cologne Chip Designs hfc-s+/sp based cards * * Author Werner Cornelius * based on existing driver for CCD HFC PCI cards @@ -20,7 +20,7 @@ extern const char *CardType[]; -static const char *hfcsx_revision = "$Revision: 1.9.6.3 $"; +static const char *hfcsx_revision = "$Revision: 1.12.2.5 $"; /***************************************/ /* IRQ-table for CCDs demo board */ @@ -43,11 +43,11 @@ #undef CCD_DEMO_BOARD #ifdef CCD_DEMO_BOARD -static u8 ccd_sp_irqtab[16] = { +static u_char ccd_sp_irqtab[16] = { 0,0,0,0,0,2,1,0,0,0,3,4,5,0,0,6 }; #else /* Teles 16.3c */ -static u8 ccd_sp_irqtab[16] = { +static u_char ccd_sp_irqtab[16] = { 0,0,0,7,0,1,0,0,0,2,3,4,5,0,0,6 }; #endif @@ -60,17 +60,16 @@ /* In/Out access to registers */ /******************************/ static inline void -Write_hfc(struct IsdnCardState *cs, u8 regnum, u8 val) +Write_hfc(struct IsdnCardState *cs, u_char regnum, u_char val) { - byteout(cs->hw.hfcsx.base+1, regnum); byteout(cs->hw.hfcsx.base, val); } -static inline u8 -Read_hfc(struct IsdnCardState *cs, u8 regnum) +static inline u_char +Read_hfc(struct IsdnCardState *cs, u_char regnum) { - u8 ret; + u_char ret; byteout(cs->hw.hfcsx.base+1, regnum); ret = bytein(cs->hw.hfcsx.base); @@ -82,7 +81,7 @@ /* select a fifo and remember which one for reuse */ /**************************************************/ static void -fifo_select(struct IsdnCardState *cs, u8 fifo) +fifo_select(struct IsdnCardState *cs, u_char fifo) { if (fifo == cs->hw.hfcsx.last_fifo) return; /* still valid */ @@ -97,10 +96,10 @@ /******************************************/ /* reset the specified fifo to defaults. */ -/* If it's a send fifo init needed markers */ +/* If its a send fifo init needed markers */ /******************************************/ static void -reset_fifo(struct IsdnCardState *cs, u8 fifo) +reset_fifo(struct IsdnCardState *cs, u_char fifo) { fifo_select(cs, fifo); /* first select the fifo */ byteout(cs->hw.hfcsx.base+1, HFCSX_CIRM); @@ -116,10 +115,11 @@ /* the skb is not released in any way. */ /*************************************************************/ static int -write_fifo(struct IsdnCardState *cs, struct sk_buff *skb, u8 fifo, int trans_max) -{ unsigned short *msp; +write_fifo(struct IsdnCardState *cs, struct sk_buff *skb, u_char fifo, int trans_max) +{ + unsigned short *msp; int fifo_size, count, z1, z2; - u8 f_msk, f1, f2, *src; + u_char f_msk, f1, f2, *src; if (skb->len <= 0) return(0); if (fifo & 1) return(0); /* no write fifo */ @@ -145,9 +145,9 @@ count = z2 - z1; if (count <= 0) count += fifo_size; /* free bytes */ - if (count < (int)(skb->len+1)) return(0); /* no room */ + if (count < skb->len+1) return(0); /* no room */ count = fifo_size - count; /* bytes still not send */ - if (count > 2 * trans_max) return(0); /* delay too long */ + if (count > 2 * trans_max) return(0); /* delay to long */ count = skb->len; src = skb->data; while (count--) @@ -182,7 +182,7 @@ if (cs->debug & L1_DEB_ISAC_FIFO) debugl1(cs, "hfcsx_write_fifo %d count(%ld/%d)", fifo, skb->len, count); - if (count < (int)skb->len) { + if (count < skb->len) { if (cs->debug & L1_DEB_ISAC_FIFO) debugl1(cs, "hfcsx_write_fifo %d no fifo mem", fifo); return(0); @@ -205,9 +205,9 @@ /* the skb is not released in any way. */ /***************************************************************/ static struct sk_buff * -read_fifo(struct IsdnCardState *cs, u8 fifo, int trans_max) +read_fifo(struct IsdnCardState *cs, u_char fifo, int trans_max) { int fifo_size, count, z1, z2; - u8 f_msk, f1, f2, *dst; + u_char f_msk, f1, f2, *dst; struct sk_buff *skb; if (!(fifo & 1)) return(NULL); /* no read fifo */ @@ -308,8 +308,8 @@ /******************************************/ /* free hardware resources used by driver */ /******************************************/ -static void -hfcsx_release(struct IsdnCardState *cs) +void +release_io_hfcsx(struct IsdnCardState *cs) { cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */ Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); @@ -318,7 +318,7 @@ schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ Write_hfc(cs, HFCSX_CIRM, 0); /* Reset Off */ del_timer(&cs->hw.hfcsx.timer); - hisax_release_resources(cs); + release_region(cs->hw.hfcsx.base, 2); /* release IO-Block */ kfree(cs->hw.hfcsx.extra); cs->hw.hfcsx.extra = NULL; } @@ -347,8 +347,8 @@ /* function called to reset the HFC SX chip. A complete software reset of chip */ /* and fifos is done. */ /********************************************************************************/ -static int -hfcsx_reset(struct IsdnCardState *cs) +static void +reset_hfcsx(struct IsdnCardState *cs) { cs->hw.hfcsx.int_m2 = 0; /* interrupt output off ! */ Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); @@ -356,11 +356,9 @@ printk(KERN_INFO "HFC_SX: resetting card\n"); while (1) { Write_hfc(cs, HFCSX_CIRM, HFCSX_RESET | cs->hw.hfcsx.cirm ); /* Reset */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30 * HZ) / 1000); /* Timeout 30ms */ + mdelay(30); Write_hfc(cs, HFCSX_CIRM, cs->hw.hfcsx.cirm); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((20 * HZ) / 1000); /* Timeout 20ms */ + mdelay(20); if (Read_hfc(cs, HFCSX_STATUS) & 2) printk(KERN_WARNING "HFC-SX init bit busy\n"); cs->hw.hfcsx.last_fifo = 0xff; /* invalidate */ @@ -415,7 +413,6 @@ cs->hw.hfcsx.int_m2 = HFCSX_IRQ_ENABLE; Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); if (Read_hfc(cs, HFCSX_INT_S2)); - return 0; } /***************************************************/ @@ -431,7 +428,6 @@ */ } - /************************************************/ /* select a b-channel entry matching and active */ /************************************************/ @@ -450,20 +446,27 @@ /*******************************/ /* D-channel receive procedure */ /*******************************/ -static int +static +int receive_dmsg(struct IsdnCardState *cs) { struct sk_buff *skb; int count = 5; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "rec_dmsg blocked"); + return (1); + } + do { skb = read_fifo(cs, HFCSX_SEL_D_RX, 0); if (skb) { skb_queue_tail(&cs->rq, skb); - sched_d_event(cs, D_RCVBUFREADY); + schedule_event(cs, D_RCVBUFREADY); } } while (--count && skb); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); return (1); } @@ -479,6 +482,10 @@ Begin: count--; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "rec_data %d blocked", bcs->channel); + return; + } skb = read_fifo(cs, ((bcs->channel) && (!cs->hw.hfcsx.bswapped)) ? HFCSX_SEL_B2_RX : HFCSX_SEL_B1_RX, (bcs->mode == L1_MODE_TRANS) ? @@ -486,9 +493,10 @@ if (skb) { skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + schedule_event(bcs, B_RCVBUFREADY); } + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); if (count && skb) goto Begin; return; @@ -509,6 +517,7 @@ dev_kfree_skb_any(cs->tx_skb); cs->tx_skb = NULL; } + return; } /**************************/ @@ -530,9 +539,18 @@ (bcs->mode == L1_MODE_TRANS) ? HFCSX_BTRANS_THRESHOLD : 0)) { - bcs->tx_cnt -= bcs->tx_skb->len; - xmit_complete_b(bcs); - test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_cnt -= bcs->tx_skb->len; + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->tx_skb->len; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); } } @@ -551,7 +569,7 @@ st->l1.l1hw(st, pr, arg); break; case (PH_ACTIVATE | REQUEST): - L1L2(st, PH_ACTIVATE | CONFIRM, NULL); + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); break; case (PH_TESTLOOP | REQUEST): if (1 & (long) arg) @@ -577,10 +595,12 @@ static int hfcsx_auxcmd(struct IsdnCardState *cs, isdn_ctrl * ic) { + unsigned long flags; int i = *(unsigned int *) ic->parm.num; if ((ic->arg == 98) && (!(cs->hw.hfcsx.int_m1 & (HFCSX_INTS_B2TRANS + HFCSX_INTS_B2REC + HFCSX_INTS_B1TRANS + HFCSX_INTS_B1REC)))) { + spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 0); /* HFC ST G0 */ udelay(10); cs->hw.hfcsx.sctrl |= SCTRL_MODE_NT; @@ -592,7 +612,8 @@ cs->dc.hfcsx.ph_state = 1; cs->hw.hfcsx.nt_mode = 1; cs->hw.hfcsx.nt_timer = 0; - cs->stlist->l1.l2l1 = dch_nt_l2l1; + spin_unlock_irqrestore(&cs->lock, flags); + cs->stlist->l2.l2l1 = dch_nt_l2l1; debugl1(cs, "NT mode activated"); return (0); } @@ -614,12 +635,14 @@ cs->hw.hfcsx.sctrl &= ~SCTRL_B2_ENA; cs->hw.hfcsx.conn |= 0x10; /* B2-IOM -> B2-ST */ cs->hw.hfcsx.ctmt &= ~2; + spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt); Write_hfc(cs, HFCSX_SCTRL_R, cs->hw.hfcsx.sctrl_r); Write_hfc(cs, HFCSX_SCTRL, cs->hw.hfcsx.sctrl); Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn); Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm); Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); + spin_unlock_irqrestore(&cs->lock, flags); return (0); } /* hfcsx_auxcmd */ @@ -630,9 +653,13 @@ receive_emsg(struct IsdnCardState *cs) { int count = 5; - u8 *ptr; + u_char *ptr; struct sk_buff *skb; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + debugl1(cs, "echo_rec_data blocked"); + return; + } do { skb = read_fifo(cs, HFCSX_SEL_B2_RX, 0); if (skb) { @@ -655,6 +682,9 @@ dev_kfree_skb_any(skb); } } while (--count && skb); + + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + return; } /* receive_emsg */ @@ -665,27 +695,28 @@ hfcsx_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 exval; + u_char exval; struct BCState *bcs; int count = 15; - u8 val, stat; + u_long flags; + u_char val, stat; - if (!cs) { - printk(KERN_WARNING "HFC-SX: Spurious interrupt!\n"); - return IRQ_NONE; - } if (!(cs->hw.hfcsx.int_m2 & 0x08)) return IRQ_NONE; /* not initialised */ + spin_lock_irqsave(&cs->lock, flags); if (HFCSX_ANYINT & (stat = Read_hfc(cs, HFCSX_STATUS))) { val = Read_hfc(cs, HFCSX_INT_S1); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "HFC-SX: stat(%02x) s1(%02x)", stat, val); - } else + } else { + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_NONE; - + } if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "HFC-SX irq %x", val); + debugl1(cs, "HFC-SX irq %x %s", val, + test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ? + "locked" : "unlocked"); val &= cs->hw.hfcsx.int_m1; if (val & 0x40) { /* state machine irq */ exval = Read_hfc(cs, HFCSX_STATES) & 0xf; @@ -693,18 +724,23 @@ debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcsx.ph_state, exval); cs->dc.hfcsx.ph_state = exval; - sched_d_event(cs, D_L1STATECHANGE); + schedule_event(cs, D_L1STATECHANGE); val &= ~0x40; } if (val & 0x80) { /* timer irq */ if (cs->hw.hfcsx.nt_mode) { if ((--cs->hw.hfcsx.nt_timer) < 0) - sched_d_event(cs, D_L1STATECHANGE); + schedule_event(cs, D_L1STATECHANGE); } val &= ~0x80; Write_hfc(cs, HFCSX_CTMT, cs->hw.hfcsx.ctmt | HFCSX_CLTIMER); } while (val) { + if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + cs->hw.hfcsx.int_s1 |= val; + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; + } if (cs->hw.hfcsx.int_s1 & 0x18) { exval = val; val = cs->hw.hfcsx.int_s1; @@ -731,7 +767,23 @@ if (cs->debug) debugl1(cs, "hfcsx spurious 0x01 IRQ"); } else { - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + schedule_event(bcs, B_XMTBUFREADY); + } + } } } if (val & 0x02) { @@ -739,15 +791,60 @@ if (cs->debug) debugl1(cs, "hfcsx spurious 0x02 IRQ"); } else { - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "fill_data %d blocked", bcs->channel); + } else { + schedule_event(bcs, B_XMTBUFREADY); + } + } } } if (val & 0x20) { /* receive dframe */ receive_dmsg(cs); } if (val & 0x04) { /* dframe transmitted */ - xmit_xpr_d(cs); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else { + debugl1(cs, "hfcsx_fill_dfifo irq blocked"); + } + goto afterXPR; + } else { + dev_kfree_skb_irq(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else { + debugl1(cs, "hfcsx_fill_dfifo irq blocked"); + } + } else + schedule_event(cs, D_XMTBUFREADY); } + afterXPR: if (cs->hw.hfcsx.int_s1 && count--) { val = cs->hw.hfcsx.int_s1; cs->hw.hfcsx.int_s1 = 0; @@ -756,6 +853,7 @@ } else val = 0; } + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } @@ -775,38 +873,104 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_d(cs, skb); + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "hfcsx_fill_dfifo blocked"); + + } + spin_unlock_irqrestore(&cs->lock, flags); break; - case (PH_PULL |INDICATION): - xmit_pull_ind_d(cs, skb); + case (PH_PULL | INDICATION): + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + spin_unlock_irqrestore(&cs->lock, flags); + break; + } + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_dfifo(cs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "hfcsx_fill_dfifo blocked"); + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_d(st); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (HW_RESET | REQUEST): + spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCSX_STATES, HFCSX_LOAD_STATE | 3); /* HFC ST 3 */ udelay(6); Write_hfc(cs, HFCSX_STATES, 3); /* HFC ST 2 */ cs->hw.hfcsx.mst_m |= HFCSX_MASTER; Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION); + spin_unlock_irqrestore(&cs->lock, flags); l1_msg(cs, HW_POWERUP | CONFIRM, NULL); break; case (HW_ENABLE | REQUEST): + spin_lock_irqsave(&cs->lock, flags); Write_hfc(cs, HFCSX_STATES, HFCSX_ACTIVATE | HFCSX_DO_ACTION); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_DEACTIVATE | REQUEST): + spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcsx.mst_m &= ~HFCSX_MASTER; Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_INFO3 | REQUEST): + spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcsx.mst_m |= HFCSX_MASTER; Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_TESTLOOP | REQUEST): + spin_lock_irqsave(&cs->lock, flags); switch ((int) arg) { case (1): Write_hfc(cs, HFCSX_B1_SSL, 0x80); /* tx slot */ @@ -814,21 +978,21 @@ cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~7) | 1; Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn); break; - case (2): Write_hfc(cs, HFCSX_B2_SSL, 0x81); /* tx slot */ Write_hfc(cs, HFCSX_B2_RSL, 0x81); /* rx slot */ cs->hw.hfcsx.conn = (cs->hw.hfcsx.conn & ~0x38) | 0x08; Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn); break; - default: + spin_unlock_irqrestore(&cs->lock, flags); if (cs->debug & L1_DEB_WARN) debugl1(cs, "hfcsx_l1hw loop invalid %4x", (int) arg); return; } cs->hw.hfcsx.trm |= 0x80; /* enable IOM-loop */ Write_hfc(cs, HFCSX_TRM, cs->hw.hfcsx.trm); + spin_unlock_irqrestore(&cs->lock, flags); break; default: if (cs->debug & L1_DEB_WARN) @@ -840,11 +1004,25 @@ /***********************************************/ /* called during init setting l1 stack pointer */ /***********************************************/ -static int +void setstack_hfcsx(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = HFCSX_l1hw; - return 0; +} + +/**************************************/ +/* send B-channel data if not blocked */ +/**************************************/ +static void +hfcsx_send_data(struct BCState *bcs) +{ + struct IsdnCardState *cs = bcs->cs; + + if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + hfcsx_fill_fifo(bcs); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + } else + debugl1(cs, "send_data %d blocked", bcs->channel); } /***************************************************************/ @@ -963,31 +1141,57 @@ static void hfcsx_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; +// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n"); + } else { +// test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - mode_hfcsx(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + mode_hfcsx(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - mode_hfcsx(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + mode_hfcsx(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -1037,7 +1241,7 @@ if (open_hfcsxstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = hfcsx_l2l1; + st->l2.l2l1 = hfcsx_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); @@ -1048,10 +1252,12 @@ /* handle L1 state changes */ /***************************/ static void -hfcsx_bh(void *data) +hfcsx_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; + u_long flags; + if (!cs) + return; if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) { if (!cs->hw.hfcsx.nt_mode) switch (cs->dc.hfcsx.ph_state) { @@ -1075,6 +1281,7 @@ } else { switch (cs->dc.hfcsx.ph_state) { case (2): + spin_lock_irqsave(&cs->lock, flags); if (cs->hw.hfcsx.nt_timer < 0) { cs->hw.hfcsx.nt_timer = 0; cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; @@ -1096,13 +1303,16 @@ cs->hw.hfcsx.nt_timer = NT_T1_COUNT; Write_hfc(cs, HFCSX_STATES, 2 | HFCSX_NT_G2_G3); /* allow G2 -> G3 transition */ } + spin_unlock_irqrestore(&cs->lock, flags); break; case (1): case (3): case (4): + spin_lock_irqsave(&cs->lock, flags); cs->hw.hfcsx.nt_timer = 0; cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); + spin_unlock_irqrestore(&cs->lock, flags); break; default: break; @@ -1115,18 +1325,6 @@ DChannel_proc_xmt(cs); } -static struct bc_l1_ops hfcsx_bc_l1_ops = { - .fill_fifo = hfcsx_fill_fifo, - .open = setstack_2b, - .close = close_hfcsx, -}; - -static struct dc_l1_ops hfcsx_dc_l1_ops = { - .fill_fifo = hfcsx_fill_dfifo, - .open = setstack_hfcsx, - .bh_func = hfcsx_bh, - .dbusy_func = hfcsx_dbusy_timer, -}; /********************************/ /* called for card init message */ @@ -1134,98 +1332,55 @@ void __devinit inithfcsx(struct IsdnCardState *cs) { - dc_l1_init(cs, &hfcsx_dc_l1_ops); - cs->bc_l1_ops = &hfcsx_bc_l1_ops; + cs->setstack_d = setstack_hfcsx; + cs->BC_Send_Data = &hfcsx_send_data; + cs->bcs[0].BC_SetStack = setstack_2b; + cs->bcs[1].BC_SetStack = setstack_2b; + cs->bcs[0].BC_Close = close_hfcsx; + cs->bcs[1].BC_Close = close_hfcsx; mode_hfcsx(cs->bcs, 0, 0); mode_hfcsx(cs->bcs + 1, 0, 1); } -static void -hfcsx_init(struct IsdnCardState *cs) -{ - inithfcsx(cs); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ - /* now switch timer interrupt off */ - cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; - Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); - /* reinit mode reg */ - Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); -} -static struct card_ops hfcsx_ops = { - .init = hfcsx_init, - .reset = hfcsx_reset, - .release = hfcsx_release, - .irq_func = hfcsx_interrupt, -}; -static int __init -hfcsx_probe(struct IsdnCardState *cs, struct IsdnCard *card) +/*******************************************/ +/* handle card messages from control layer */ +/*******************************************/ +static int +hfcsx_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - int rc; - char c; + u_long flags; - cs->irq = card->para[0]; - cs->hw.hfcsx.base = card->para[1] & 0xfffe; - - cs->hw.hfcsx.fifo = 255; - cs->hw.hfcsx.int_s1 = 0; - cs->dc.hfcsx.ph_state = 0; - - rc = -EBUSY; - if (!request_io(&cs->rs, cs->hw.hfcsx.base, 2, "HFCSX isdn")) - goto err; - - rc = -ENODEV; - byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF); - byteout(cs->hw.hfcsx.base + 1, ((cs->hw.hfcsx.base >> 8) & 3) | 0x54); - udelay(10); - cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID); - switch (cs->hw.hfcsx.chip >> 4) { - case 1: - c ='+'; - break; - case 9: - c ='P'; - break; - default: - printk(KERN_WARNING "HFC-SX: invalid chip id 0x%x\n", - cs->hw.hfcsx.chip >> 4); - goto err; - } - if (!ccd_sp_irqtab[cs->irq & 0xF]) { - printk(KERN_WARNING "HFC_SX: invalid irq %d specified\n", - cs->irq & 0xF); - goto err; - } - rc = -ENOMEM; - cs->hw.hfcsx.extra = kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC); - if (!cs->hw.hfcsx.extra) { - printk(KERN_WARNING "HFC-SX: unable to allocate memory\n"); - goto err; + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "HFCSX: card_msg %x", mt); + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_hfcsx(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_RELEASE: + release_io_hfcsx(cs); + return (0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithfcsx(cs); + spin_unlock_irqrestore(&cs->lock, flags); + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((80 * HZ) / 1000); /* Timeout 80ms */ + /* now switch timer interrupt off */ + spin_lock_irqsave(&cs->lock, flags); + cs->hw.hfcsx.int_m1 &= ~HFCSX_INTS_TIMER; + Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); + /* reinit mode reg */ + Write_hfc(cs, HFCSX_MST_MODE, cs->hw.hfcsx.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); + return (0); + case CARD_TEST: + return (0); } - printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d\n", - c, (u_int) cs->hw.hfcsx.base, cs->irq); - - cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */ - cs->hw.hfcsx.int_m1 = 0; - Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); - Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); - - init_timer(&cs->hw.hfcsx.timer); - cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer; - cs->hw.hfcsx.timer.data = (long) cs; - cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */ - cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not eval. */ - - hfcsx_reset(cs); - cs->auxcmd = &hfcsx_auxcmd; - cs->card_ops = &hfcsx_ops; - return 0; - err: - hisax_release_resources(cs); - return rc; + return (0); } #ifdef __ISAPNP__ @@ -1236,66 +1391,133 @@ { 0, } }; -static struct isapnp_device_id *hdev = &hfc_ids[0]; +static struct isapnp_device_id *ipid __initdata = &hfc_ids[0]; static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __devinit setup_hfcsx(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, hfcsx_revision); printk(KERN_INFO "HiSax: HFC-SX driver Rev. %s\n", HiSax_getrev(tmp)); #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; + struct pnp_dev *pnp_d; + while(ipid->card_vendor) { + if ((pnp_c = pnp_find_card(ipid->card_vendor, + ipid->card_device, pnp_c))) { + pnp_d = NULL; + if ((pnp_d = pnp_find_dev(pnp_c, + ipid->vendor, ipid->function, pnp_d))) { + int err; - while(hdev->card_vendor) { - if ((pb = pnp_find_card(hdev->card_vendor, - hdev->card_device, - pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - hdev->vendor, - hdev->function, - pd))) { printk(KERN_INFO "HiSax: %s detected\n", - (char *)hdev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "HFC PnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "HFC PnP: activate failed\n"); - pnp_device_detach(pd); - return 0; + (char *)ipid->driver_data); + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[0] = pnp_irq(pnp_d, 0); + if (!card->para[0] || !card->para[1]) { printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); + card->para[0], card->para[1]); + pnp_disable_dev(pnp_d); return(0); } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); break; } else { printk(KERN_ERR "HFC PnP: PnP error card found, no device\n"); } } - hdev++; - pnp_c=NULL; + ipid++; + pnp_c = NULL; } - if (!hdev->card_vendor) { + if (!ipid->card_vendor) { printk(KERN_INFO "HFC PnP: no ISAPnP card found\n"); return(0); } } #endif - if (hfcsx_probe(card->cs, card) < 0) - return 0; - return 1; + cs->hw.hfcsx.base = card->para[1] & 0xfffe; + cs->irq = card->para[0]; + cs->hw.hfcsx.int_s1 = 0; + cs->dc.hfcsx.ph_state = 0; + cs->hw.hfcsx.fifo = 255; + if ((cs->typ == ISDN_CTYPE_HFC_SX) || + (cs->typ == ISDN_CTYPE_HFC_SP_PCMCIA)) { + if ((!cs->hw.hfcsx.base) || !request_region(cs->hw.hfcsx.base, 2, "HFCSX isdn")) { + printk(KERN_WARNING + "HiSax: HFC-SX io-base %#lx already in use\n", + cs->hw.hfcsx.base); + return(0); + } + byteout(cs->hw.hfcsx.base, cs->hw.hfcsx.base & 0xFF); + byteout(cs->hw.hfcsx.base + 1, + ((cs->hw.hfcsx.base >> 8) & 3) | 0x54); + udelay(10); + cs->hw.hfcsx.chip = Read_hfc(cs,HFCSX_CHIP_ID); + switch (cs->hw.hfcsx.chip >> 4) { + case 1: + tmp[0] ='+'; + break; + case 9: + tmp[0] ='P'; + break; + default: + printk(KERN_WARNING + "HFC-SX: invalid chip id 0x%x\n", + cs->hw.hfcsx.chip >> 4); + release_region(cs->hw.hfcsx.base, 2); + return(0); + } + if (!ccd_sp_irqtab[cs->irq & 0xF]) { + printk(KERN_WARNING + "HFC_SX: invalid irq %d specified\n",cs->irq & 0xF); + release_region(cs->hw.hfcsx.base, 2); + return(0); + } + if (!(cs->hw.hfcsx.extra = (void *) + kmalloc(sizeof(struct hfcsx_extra), GFP_ATOMIC))) { + release_region(cs->hw.hfcsx.base, 2); + printk(KERN_WARNING "HFC-SX: unable to allocate memory\n"); + return(0); + } + printk(KERN_INFO "HFC-S%c chip detected at base 0x%x IRQ %d HZ %d\n", + tmp[0], (u_int) cs->hw.hfcsx.base, cs->irq, HZ); + cs->hw.hfcsx.int_m2 = 0; /* disable alle interrupts */ + cs->hw.hfcsx.int_m1 = 0; + Write_hfc(cs, HFCSX_INT_M1, cs->hw.hfcsx.int_m1); + Write_hfc(cs, HFCSX_INT_M2, cs->hw.hfcsx.int_m2); + } else + return (0); /* no valid card type */ + + cs->dbusytimer.function = (void *) hfcsx_dbusy_timer; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); + INIT_WORK(&cs->tqueue, (void *)(void *) hfcsx_bh, cs); + cs->readisac = NULL; + cs->writeisac = NULL; + cs->readisacfifo = NULL; + cs->writeisacfifo = NULL; + cs->BC_Read_Reg = NULL; + cs->BC_Write_Reg = NULL; + cs->irq_func = &hfcsx_interrupt; + + cs->hw.hfcsx.timer.function = (void *) hfcsx_Timer; + cs->hw.hfcsx.timer.data = (long) cs; + cs->hw.hfcsx.b_fifo_size = 0; /* fifo size still unknown */ + cs->hw.hfcsx.cirm = ccd_sp_irqtab[cs->irq & 0xF]; /* RAM not evaluated */ + init_timer(&cs->hw.hfcsx.timer); + + reset_hfcsx(cs); + cs->cardmsg = &hfcsx_card_msg; + cs->auxcmd = &hfcsx_auxcmd; + return (1); } diff -Nru a/drivers/isdn/hisax/hfc_usb.c b/drivers/isdn/hisax/hfc_usb.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/isdn/hisax/hfc_usb.c Thu Feb 19 23:44:29 2004 @@ -0,0 +1,1667 @@ +/* + * hfc_usb.c + * + * modular HiSax ISDN driver for Colognechip HFC-USB chip + * + * Authors : Peter Sprenger (sprenger@moving-byters.de) + * Martin Bachem (info@colognechip.com) + * based on the first hfc_usb driver of Werner Cornelius (werner@isdn-development.de) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * +*/ + + +#include +#include +#include +#include +#include +#include "hisax.h" +#include +#include +#include +#include +#include +#include +#include "hisax_if.h" + +static const char *hfcusb_revision = "4.0"; + +/* + to enable much mire debug messages in this driver, define + VERBOSE_USB_DEBUG and VERBOSE_ISDN_DEBUG + below +*/ + +#define VERBOSE_USB_DEBUG +#define VERBOSE_ISDN_DEBUG + +#define INCLUDE_INLINE_FUNCS + +#define TRUE 1 +#define FALSE 0 + + +/***********/ +/* defines */ +/***********/ +#define HFC_CTRL_TIMEOUT 20 //(HZ * USB_CTRL_GET_TIMEOUT) +/* 5ms timeout writing/reading regs */ +#define HFC_TIMER_T3 8000 /* timeout for l1 activation timer */ +#define HFC_TIMER_T4 500 /* time for state change interval */ + +#define HFCUSB_L1_STATECHANGE 0 /* L1 state changed */ +#define HFCUSB_L1_DRX 1 /* D-frame received */ +#define HFCUSB_L1_ERX 2 /* E-frame received */ +#define HFCUSB_L1_DTX 4 /* D-frames completed */ + +#define MAX_BCH_SIZE 2048 /* allowed B-channel packet size */ + +#define HFCUSB_RX_THRESHOLD 64 /* threshold for fifo report bit rx */ +#define HFCUSB_TX_THRESHOLD 64 /* threshold for fifo report bit tx */ + +#define HFCUSB_CHIP_ID 0x16 /* Chip ID register index */ +#define HFCUSB_CIRM 0x00 /* cirm register index */ +#define HFCUSB_USB_SIZE 0x07 /* int length register */ +#define HFCUSB_USB_SIZE_I 0x06 /* iso length register */ +#define HFCUSB_F_CROSS 0x0b /* bit order register */ +#define HFCUSB_CLKDEL 0x37 /* bit delay register */ +#define HFCUSB_CON_HDLC 0xfa /* channel connect register */ +#define HFCUSB_HDLC_PAR 0xfb +#define HFCUSB_SCTRL 0x31 /* S-bus control register (tx) */ +#define HFCUSB_SCTRL_E 0x32 /* same for E and special funcs */ +#define HFCUSB_SCTRL_R 0x33 /* S-bus control register (rx) */ +#define HFCUSB_F_THRES 0x0c /* threshold register */ +#define HFCUSB_FIFO 0x0f /* fifo select register */ +#define HFCUSB_F_USAGE 0x1a /* fifo usage register */ +#define HFCUSB_MST_MODE0 0x14 +#define HFCUSB_MST_MODE1 0x15 +#define HFCUSB_P_DATA 0x1f +#define HFCUSB_INC_RES_F 0x0e +#define HFCUSB_STATES 0x30 + +#define HFCUSB_CHIPID 0x40 /* ID value of HFC-USB */ + +/******************/ +/* fifo registers */ +/******************/ +#define HFCUSB_NUM_FIFOS 8 /* maximum number of fifos */ +#define HFCUSB_B1_TX 0 /* index for B1 transmit bulk/int */ +#define HFCUSB_B1_RX 1 /* index for B1 receive bulk/int */ +#define HFCUSB_B2_TX 2 +#define HFCUSB_B2_RX 3 +#define HFCUSB_D_TX 4 +#define HFCUSB_D_RX 5 +#define HFCUSB_PCM_TX 6 +#define HFCUSB_PCM_RX 7 + +/* +* used to switch snd_transfer_mode for different TA modes e.g. the Billion USB TA just +* supports ISO out, while the Cologne Chip EVAL TA just supports BULK out +*/ +#define USB_INT 0 +#define USB_BULK 1 +#define USB_ISOC 2 + +#define ISOC_PACKETS_D 8 +#define ISOC_PACKETS_B 8 +#define ISO_BUFFER_SIZE 128 + +// ISO send definitions +#define SINK_MAX 68 +#define SINK_MIN 48 +#define SINK_DMIN 12 +#define SINK_DMAX 18 +#define BITLINE_INF (-64*8) + + + + +/**********/ +/* macros */ +/**********/ +#define write_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_out_pipe,0,0x40,(c),(b),0,0,HFC_CTRL_TIMEOUT) +#define read_usb(a,b,c) usb_control_msg((a)->dev,(a)->ctrl_in_pipe,1,0xC0,0,(b),(c),1,HFC_CTRL_TIMEOUT) + +/*************************************************/ +/* entry and size of output/input control buffer */ +/*************************************************/ +#define HFC_CTRL_BUFSIZE 32 +typedef struct +{ + __u8 hfc_reg; /* register number */ + __u8 reg_val; /* value to be written (or read) */ + int action; /* data for action handler */ + +} ctrl_buft; + +typedef struct +{ + int vendor; // vendor id + int prod_id; // product id + char *vend_name; // vendor string + __u8 led_scheme; // led display scheme + __u8 led_invert; // invert led aux port settings + __u8 led_bits[8]; // array of 8 possible LED bitmask settings + +} vendor_data; + +/***************************************************************/ +/* structure defining input+output fifos (interrupt/bulk mode) */ +/***************************************************************/ + +struct usb_fifo; /* forward definition */ +typedef struct iso_urb_struct +{ + struct urb *purb; + __u8 buffer[ISO_BUFFER_SIZE]; /* buffer incoming/outgoing data */ + struct usb_fifo *owner_fifo; // pointer to owner fifo +} iso_urb_struct; + + +struct hfcusb_data; /* forward definition */ +typedef struct usb_fifo +{ + int fifonum; /* fifo index attached to this structure */ + int active; /* fifo is currently active */ + struct hfcusb_data *hfc; /* pointer to main structure */ + int pipe; /* address of endpoint */ + __u8 usb_packet_maxlen; /* maximum length for usb transfer */ + unsigned int max_size; /* maximum size of receive/send packet */ + __u8 intervall; /* interrupt interval */ + struct sk_buff *skbuff; /* actual used buffer */ + struct urb *urb; /* transfer structure for usb routines */ + __u8 buffer[128]; /* buffer incoming/outgoing data */ + int bit_line; /* how much bits are in the fifo? */ + + volatile __u8 usb_transfer_mode;/* switched between ISO and INT */ + iso_urb_struct iso[2]; /* need two urbs to have one always for pending */ + struct hisax_if *hif; /* hisax interface */ + int delete_flg; /* only delete skbuff once */ + int last_urblen; /* remember length of last packet */ + +} usb_fifo; + + +/*********************************************/ +/* structure holding all data for one device */ +/*********************************************/ +typedef struct hfcusb_data +{ + // HiSax Interface for loadable Layer1 drivers + struct hisax_d_if d_if; /* see hisax_if.h */ + struct hisax_b_if b_if[2]; /* see hisax_if.h */ + int protocol; + + struct usb_device *dev; /* our device */ + int if_used; /* used interface number */ + int alt_used; /* used alternate config */ + int ctrl_paksize; /* control pipe packet size */ + int ctrl_in_pipe, ctrl_out_pipe; /* handles for control pipe */ + int cfg_used; /* configuration index used */ + int vend_idx; // vendor found + + int b_mode[2]; // B-channel mode + + int l1_activated; // layer 1 activated + + int packet_size,iso_packet_size; + + /* control pipe background handling */ + ctrl_buft ctrl_buff[HFC_CTRL_BUFSIZE]; /* buffer holding queued data */ + volatile int ctrl_in_idx, ctrl_out_idx, + ctrl_cnt; /* input/output pointer + count */ + struct urb *ctrl_urb; /* transfer structure for control channel */ + + struct usb_ctrlrequest ctrl_write; /* buffer for control write request */ + struct usb_ctrlrequest ctrl_read; /* same for read request */ + + __u8 led_state,led_new_data,led_b_active; + + volatile __u8 threshold_mask; /* threshold actually reported */ + volatile __u8 bch_enables; /* or mask for sctrl_r and sctrl register values */ + + usb_fifo fifos[HFCUSB_NUM_FIFOS]; /* structure holding all fifo data */ + + volatile __u8 l1_state; /* actual l1 state */ + struct timer_list t3_timer; /* timer 3 for activation/deactivation */ + struct timer_list t4_timer; /* timer 4 for activation/deactivation */ + struct timer_list led_timer; /* timer flashing leds */ + +} hfcusb_data; + + +static void collect_rx_frame(usb_fifo *fifo,__u8 *data,int len,int finish); + + + +/******************************************************/ +/* start next background transfer for control channel */ +/******************************************************/ +static void ctrl_start_transfer(hfcusb_data * hfc) +{ + int err; + if(hfc->ctrl_cnt) + { + hfc->ctrl_urb->pipe = hfc->ctrl_out_pipe; + hfc->ctrl_urb->setup_packet = (u_char *) & hfc->ctrl_write; + hfc->ctrl_urb->transfer_buffer = NULL; + hfc->ctrl_urb->transfer_buffer_length = 0; + hfc->ctrl_write.wIndex = hfc->ctrl_buff[hfc->ctrl_out_idx].hfc_reg; + hfc->ctrl_write.wValue = hfc->ctrl_buff[hfc->ctrl_out_idx].reg_val; + err = usb_submit_urb(hfc->ctrl_urb, GFP_KERNEL); /* start transfer */ + printk(KERN_DEBUG "ctrl_start_transfer: submit %d\n", err); + } +} /* ctrl_start_transfer */ + +/************************************/ +/* queue a control transfer request */ +/* return 0 on success. */ +/************************************/ +static int queue_control_request(hfcusb_data * hfc, __u8 reg, __u8 val,int action) +{ + ctrl_buft *buf; + +#ifdef VERBOSE_USB_DEBUG + printk ("HFC_USB: queue_control_request reg: %x, val: %x\n", reg, val); +#endif + + if(hfc->ctrl_cnt >= HFC_CTRL_BUFSIZE) return(1); /* no space left */ + buf = &hfc->ctrl_buff[hfc->ctrl_in_idx]; /* pointer to new index */ + buf->hfc_reg = reg; + buf->reg_val = val; + buf->action=action; + if (++hfc->ctrl_in_idx >= HFC_CTRL_BUFSIZE) + hfc->ctrl_in_idx = 0; /* pointer wrap */ + if (++hfc->ctrl_cnt == 1) + ctrl_start_transfer(hfc); + return(0); +} /* queue_control_request */ + + +static int control_action_handler(hfcusb_data *hfc,int reg,int val,int action) +{ + if(!action) return(1); // no action defined + + return(0); +} + + +/***************************************************************/ +/* control completion routine handling background control cmds */ +/***************************************************************/ +static void ctrl_complete(struct urb *urb, struct pt_regs *regs) +{ + hfcusb_data *hfc = (hfcusb_data *) urb->context; + ctrl_buft *buf; + + printk(KERN_DEBUG "ctrl_complete cnt %d\n", hfc->ctrl_cnt); + urb->dev = hfc->dev; + if(hfc->ctrl_cnt) + { + buf=&hfc->ctrl_buff[hfc->ctrl_out_idx]; + control_action_handler(hfc,buf->hfc_reg,buf->reg_val,buf->action); + + hfc->ctrl_cnt--; /* decrement actual count */ + if(++hfc->ctrl_out_idx >= HFC_CTRL_BUFSIZE) hfc->ctrl_out_idx = 0; /* pointer wrap */ + + ctrl_start_transfer(hfc); /* start next transfer */ + } +} /* ctrl_complete */ + + + +#define LED_OFF 0 // no LED support +#define LED_SCHEME1 1 // LED standard scheme +#define LED_SCHEME2 2 // not used yet... + +#define LED_POWER_ON 1 +#define LED_POWER_OFF 2 +#define LED_S0_ON 3 +#define LED_S0_OFF 4 +#define LED_B1_ON 5 +#define LED_B1_OFF 6 +#define LED_B1_DATA 7 +#define LED_B2_ON 8 +#define LED_B2_OFF 9 +#define LED_B2_DATA 10 + +#define LED_NORMAL 0 // LEDs are normal +#define LED_INVERTED 1 // LEDs are inverted + +// time for LED flashing +#define LED_TIME 250 + +vendor_data vdata[]= +{ + {0x959, 0x2bd0, "ISDN USB TA (Cologne Chip HFC-S USB based)", LED_OFF,LED_NORMAL,{4,0,2,1}}, /* CologneChip Eval TA */ + {0x7b0, 0x0007, "Billion tiny USB ISDN TA 128", LED_SCHEME1, LED_INVERTED, {8,0x40,0x20,0x10}}, /* Billion TA */ + {0x742, 0x2008, "Stollmann USB TA", LED_SCHEME1, LED_NORMAL, {4,0,2,1}}, /* Stollmann TA */ + {0x8e3, 0x0301, "Olitec USB RNIS", LED_SCHEME1, LED_NORMAL, {2,0,1,4}}, /* Olitec TA */ + {0x675, 0x1688, "DrayTec USB ISDN TA", LED_SCHEME1, LED_NORMAL, {4,0,2,1}}, /* Draytec TA */ + {0x7fa, 0x0846, "Bewan Modem RNIS USB", LED_SCHEME1, LED_INVERTED, {8,0x40,0x20,0x10}}, /* Bewan TA */ + {0,0,0} // EOL element +}; + +/***************************************************/ +/* write led data to auxport & invert if necessary */ +/***************************************************/ +static void write_led(hfcusb_data * hfc,__u8 led_state) +{ + if(led_state!=hfc->led_state) + { + hfc->led_state=led_state; + queue_control_request(hfc, HFCUSB_P_DATA,(vdata[hfc->vend_idx].led_invert) ? ~led_state : led_state,1); + } +} + +/******************************************/ +/* invert B-channel LEDs if data is sent */ +/******************************************/ +static void led_timer(hfcusb_data * hfc) +{ + static int cnt=0; + __u8 led_state=hfc->led_state; + + if(cnt) + { + if(hfc->led_b_active&1) led_state|=vdata[hfc->vend_idx].led_bits[2]; + if(hfc->led_b_active&2) led_state|=vdata[hfc->vend_idx].led_bits[3]; + } + else + { + if(!(hfc->led_b_active&1) || hfc->led_new_data&1) led_state&=~vdata[hfc->vend_idx].led_bits[2]; + if(!(hfc->led_b_active&2) || hfc->led_new_data&2) led_state&=~vdata[hfc->vend_idx].led_bits[3]; + } + + write_led(hfc,led_state); + hfc->led_new_data=0; + + cnt=!cnt; + // restart 4 hz timer + hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000; + if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer); +} + +/**************************/ +/* handle LED requests */ +/**************************/ +static void handle_led(hfcusb_data * hfc,int event) +{ + __u8 led_state=hfc->led_state; + + // if no scheme -> no LED action + if(vdata[hfc->vend_idx].led_scheme==LED_OFF) return; + + switch(event) + { + case LED_POWER_ON: + led_state|=vdata[hfc->vend_idx].led_bits[0]; + break; + case LED_POWER_OFF: // no Power off handling + break; + case LED_S0_ON: + led_state|=vdata[hfc->vend_idx].led_bits[1]; + break; + case LED_S0_OFF: + led_state&=~vdata[hfc->vend_idx].led_bits[1]; + break; + case LED_B1_ON: + hfc->led_b_active|=1; + break; + case LED_B1_OFF: + hfc->led_b_active&=~1; + break; + case LED_B1_DATA: + hfc->led_new_data|=1; + break; + case LED_B2_ON: + hfc->led_b_active|=2; + break; + case LED_B2_OFF: + hfc->led_b_active&=~2; + break; + case LED_B2_DATA: + hfc->led_new_data|=2; + break; + } + + write_led(hfc,led_state); +} + +/********************************/ +/* called when timer t3 expires */ +/********************************/ +static void l1_timer_expire_t3(hfcusb_data * hfc) +{ + //printk (KERN_INFO "HFC-USB: l1_timer_expire_t3\n"); + + hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL); +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n"); +#endif + hfc->l1_activated=FALSE; + handle_led(hfc,LED_S0_OFF); +} + +/********************************/ +/* called when timer t4 expires */ +/********************************/ +static void l1_timer_expire_t4(hfcusb_data * hfc) +{ + //printk (KERN_INFO "HFC-USB: l1_timer_expire_t4\n"); + + hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL); +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "PH_DEACTIVATE | INDICATION sent\n"); +#endif + hfc->l1_activated=FALSE; + handle_led(hfc,LED_S0_OFF); +} + +/*****************************/ +/* handle S0 state changes */ +/*****************************/ +static void state_handler(hfcusb_data * hfc,__u8 state) +{ + __u8 old_state; + + old_state=hfc->l1_state; + + // range check + if(state==old_state || state<1 || state>8) return; + +#ifdef VERBOSE_ISDN_DEBUG + printk(KERN_INFO "HFC-USB: new S0 state:%d old_state:%d\n",state,old_state); +#endif + + if(state<4 || state==7 || state==8) + { + if(timer_pending(&hfc->t3_timer)) del_timer(&hfc->t3_timer); + //printk(KERN_INFO "HFC-USB: T3 deactivated\n"); + } + + if(state>=7) + { + if(timer_pending(&hfc->t4_timer)) del_timer(&hfc->t4_timer); + //printk(KERN_INFO "HFC-USB: T4 deactivated\n"); + } + + if(state==7 && !hfc->l1_activated) + { + hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_ACTIVATE | INDICATION,NULL); + //printk(KERN_INFO "HFC-USB: PH_ACTIVATE | INDICATION sent\n"); + hfc->l1_activated=TRUE; + handle_led(hfc,LED_S0_ON); + } + else + if(state<=3 /* && activated*/) + { + if(old_state==7 || old_state==8) + { + //printk(KERN_INFO "HFC-USB: T4 activated\n"); + hfc->t4_timer.expires = jiffies + (HFC_TIMER_T4 * HZ) / 1000; + if(!timer_pending(&hfc->t4_timer)) add_timer(&hfc->t4_timer); + } + else + { + hfc->d_if.ifc.l1l2(&hfc->d_if.ifc,PH_DEACTIVATE | INDICATION,NULL); + //printk(KERN_INFO "HFC-USB: PH_DEACTIVATE | INDICATION sent\n"); + hfc->l1_activated=FALSE; + handle_led(hfc,LED_S0_OFF); + } + } + + hfc->l1_state=state; +} + + +/* prepare iso urb */ +static void fill_isoc_urb(struct urb *urb, struct usb_device *dev, unsigned int pipe, void *buf, + int num_packets, int packet_size, int interval, usb_complete_t complete, void *context) +{ + int k; + + spin_lock_init(&urb->lock); // do we really need spin_lock_init ? + urb->dev = dev; + urb->pipe = pipe; + urb->complete = complete; + urb->number_of_packets = num_packets; + urb->transfer_buffer_length = packet_size * num_packets; + urb->context = context; + urb->transfer_buffer = buf; + urb->transfer_flags = 0; + urb->transfer_flags = URB_ISO_ASAP; + urb->actual_length = 0; + urb->interval = interval; + for (k = 0; k < num_packets; k++) { + urb->iso_frame_desc[k].offset = packet_size * k; + urb->iso_frame_desc[k].length = packet_size; + urb->iso_frame_desc[k].actual_length = 0; + } +} + +/* allocs urbs and start isoc transfer with two pending urbs to avoid gaps in the transfer chain */ +static int start_isoc_chain(usb_fifo * fifo, int num_packets_per_urb,usb_complete_t complete,int packet_size) +{ + int i, k, errcode; + +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: starting ISO-chain for Fifo %i\n", fifo->fifonum); +#endif + + + // allocate Memory for Iso out Urbs + for (i = 0; i < 2; i++) { + if (!(fifo->iso[i].purb)) { + fifo->iso[i].purb = usb_alloc_urb(num_packets_per_urb, GFP_KERNEL); + fifo->iso[i].owner_fifo = (struct usb_fifo *) fifo; + + // Init the first iso + if (ISO_BUFFER_SIZE >= (fifo->usb_packet_maxlen * num_packets_per_urb)) + { + + fill_isoc_urb(fifo->iso[i].purb, fifo->hfc->dev, fifo->pipe, fifo->iso[i].buffer, + num_packets_per_urb, fifo->usb_packet_maxlen, fifo->intervall, + complete, &fifo->iso[i]); + + memset(fifo->iso[i].buffer, 0, sizeof(fifo->iso[i].buffer)); + + // defining packet delimeters in fifo->buffer + for(k = 0; k < num_packets_per_urb; k++) + { + fifo->iso[i].purb->iso_frame_desc[k].offset = k*packet_size; + fifo->iso[i].purb->iso_frame_desc[k].length = packet_size; + } + } + } + + fifo->bit_line = BITLINE_INF; + + errcode = usb_submit_urb(fifo->iso[i].purb, GFP_KERNEL); + fifo->active = (errcode >= 0) ? 1 : 0; + if(errcode < 0) + { + printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i.%i \n", errcode, i); + }; + + } + + // errcode = (usb_submit_urb(fifo->iso[0].purb, GFP_KERNEL)); + return(fifo->active); +} + +/* stops running iso chain and frees their pending urbs */ +static void stop_isoc_chain(usb_fifo * fifo) +{ + int i; + + for(i = 0; i < 2; i++) + { + if(fifo->iso[i].purb) + { +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: Stopping iso chain for fifo %i.%i\n", fifo->fifonum, i); +#endif + usb_unlink_urb(fifo->iso[i].purb); + usb_free_urb(fifo->iso[i].purb); + fifo->iso[i].purb = NULL; + } + } + if (fifo->urb) { + usb_unlink_urb(fifo->urb); + usb_free_urb(fifo->urb); + fifo->urb = NULL; + } + fifo->active = 0; +} + +// defines how much ISO packets are handled in one URB +static int iso_packets[8]={ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B,ISOC_PACKETS_B, + ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D,ISOC_PACKETS_D}; + +/*****************************************************/ +/* transmit completion routine for all ISO tx fifos */ +/*****************************************************/ +static void tx_iso_complete(struct urb *urb, struct pt_regs *regs) +{ + iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context; + usb_fifo *fifo = context_iso_urb->owner_fifo; + hfcusb_data *hfc = fifo->hfc; + int k, tx_offset, num_isoc_packets, sink, len, current_len,errcode,frame_complete,transp_mode,fifon; + __u8 threshbit; + __u8 threshtable[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80}; + + fifon=fifo->fifonum; + tx_offset=0; + // very weird error code when using ohci drivers, for now : ignore this error ... (MB) + if(urb->status == -EOVERFLOW) + { + urb->status = 0; +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN for fifo %i \n",fifon); +#endif + } + + if(fifo->active && !urb->status) + { + transp_mode=0; + if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE; + + threshbit = threshtable[fifon] & hfc->threshold_mask; // is threshold set for our channel? + num_isoc_packets=iso_packets[fifon]; + + if(fifon >= HFCUSB_D_TX) + { + sink = (threshbit) ? SINK_DMIN : SINK_DMAX; // how much bit go to the sink for D-channel? + } + else + { + sink = (threshbit) ? SINK_MIN : SINK_MAX; // how much bit go to the sink for B-channel? + } + + // prepare ISO Urb + fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets, + fifo->usb_packet_maxlen, fifo->intervall, tx_iso_complete, urb->context); + memset(context_iso_urb->buffer, 0, sizeof(context_iso_urb->buffer)); + + frame_complete=FALSE; + + // Generate Iso Packets + for(k = 0; k < num_isoc_packets; ++k) + { + if(fifo->skbuff) + { + len = fifo->skbuff->len; // remaining length + + fifo->bit_line -= sink; // we lower data margin every msec + current_len = (0 - fifo->bit_line) / 8; + if(current_len > 14) current_len = 14; // maximum 15 byte for every ISO packet makes our life easier + current_len = (len <= current_len) ? len : current_len; + fifo->bit_line += current_len * 8; // how much bit do we put on the line? + + context_iso_urb->buffer[tx_offset] = 0; + if(current_len == len) + { + if(!transp_mode) + { + context_iso_urb->buffer[tx_offset] = 1; // here frame completion + fifo->bit_line += 32; // add 2 byte flags and 16bit CRC at end of ISDN frame + } + frame_complete = TRUE; + } + + // copy bytes from buffer into ISO_URB + memcpy(context_iso_urb->buffer+tx_offset+1,fifo->skbuff->data,current_len); + skb_pull(fifo->skbuff,current_len); + + // define packet delimeters within the URB buffer + urb->iso_frame_desc[k].offset = tx_offset; + urb->iso_frame_desc[k].length = current_len + 1; + + tx_offset += (current_len + 1); + // printk(KERN_INFO "HFC-USB: fifonum:%d,%d bytes to send, %d bytes ISO packet,bitline:%d,sink:%d,threshbit:%d,threshmask:%x\n",fifon,len,current_len,fifo->bit_line,sink,threshbit,hfc->threshold_mask); + if(!transp_mode) + { + if(fifon==HFCUSB_B1_TX) handle_led(hfc,LED_B1_DATA); + if(fifon==HFCUSB_B2_TX) handle_led(hfc,LED_B2_DATA); + } + } + else + { + // we have no more data - generate 1 byte ISO packets + urb->iso_frame_desc[k].offset = tx_offset++; + + urb->iso_frame_desc[k].length = 1; + fifo->bit_line -= sink; // we lower data margin every msec + + if(fifo->bit_line < BITLINE_INF) + { + fifo->bit_line = BITLINE_INF; + //printk (KERN_INFO "HFC-USB: BITLINE_INF underrun\n"); + } + } + + if(frame_complete) + { + // delete the buffer only once, here or in hfc_usb_l2l1() in a PH_DATA|REQUEST + fifo->delete_flg=TRUE; + + fifo->hif->l1l2(fifo->hif,PH_DATA|CONFIRM,(void*)fifo->skbuff->truesize); + + if(fifo->skbuff && fifo->delete_flg) + { + dev_kfree_skb_any(fifo->skbuff); + //printk(KERN_INFO "HFC-USB: skbuff=NULL on fifo:%d\n",fifo->fifonum); + fifo->skbuff = NULL; + fifo->delete_flg=FALSE; + } + + frame_complete=FALSE; + } + } + + errcode = usb_submit_urb(urb, GFP_KERNEL); + if(errcode < 0) + { + printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n", errcode); + } + } + else + { + if(urb->status) + { + printk(KERN_INFO "HFC-USB: tx_iso_complete : urb->status %i, fifonum %i\n", urb->status,fifon); + } + } + +} /* tx_iso_complete */ + +/*****************************************************/ +/* receive completion routine for all ISO tx fifos */ +/*****************************************************/ +static void rx_iso_complete(struct urb *urb, struct pt_regs *regs) +{ + iso_urb_struct *context_iso_urb = (iso_urb_struct *) urb->context; + usb_fifo *fifo = context_iso_urb->owner_fifo; + hfcusb_data *hfc = fifo->hfc; + int k, len, errcode, offset, num_isoc_packets,fifon; + __u8 *buf; + + fifon=fifo->fifonum; + // very weird error code when using ohci drivers, for now : ignore this error ... (MB) + if(urb->status == -EOVERFLOW) + { + urb->status = 0; +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: ignoring USB DATAOVERRUN for fifo %i \n",fifon); +#endif + } + + if(fifo->active && !urb->status) + { + num_isoc_packets=iso_packets[fifon]; + + // Generate D-Channel Iso Packets + for(k = 0; k < num_isoc_packets; ++k) + { + len=urb->iso_frame_desc[k].actual_length; + offset=urb->iso_frame_desc[k].offset; + buf=context_iso_urb->buffer+offset; + + if(fifo->last_urblen!=fifo->usb_packet_maxlen) + { + // the threshold mask is in the 2nd status byte + hfc->threshold_mask=buf[1]; + // the S0 state is in the upper half of the 1st status byte + state_handler(hfc,buf[0] >> 4); + // if we have more than the 2 status bytes -> collect data + if(len>2) collect_rx_frame(fifo,buf+2,len-2,buf[0]&1); + } + else collect_rx_frame(fifo,buf,len,0); + + fifo->last_urblen=len; + + } + + // prepare ISO Urb + fill_isoc_urb(urb, fifo->hfc->dev, fifo->pipe,context_iso_urb->buffer, num_isoc_packets, + fifo->usb_packet_maxlen, fifo->intervall, rx_iso_complete, urb->context); + + errcode = usb_submit_urb(urb, GFP_KERNEL); + if(errcode < 0) + { + printk(KERN_INFO "HFC-USB: error submitting ISO URB: %i \n", errcode); + } + } + else + { + if(urb->status) + { + printk(KERN_INFO "HFC-USB: rx_iso_complete : urb->status %i, fifonum %i\n", urb->status,fifon); + } + } +} /* rx_iso_complete */ + + +/*****************************************************/ +/* collect data from interrupt or isochron in */ +/*****************************************************/ +static void collect_rx_frame(usb_fifo *fifo,__u8 *data,int len,int finish) +{ + hfcusb_data *hfc = fifo->hfc; + int transp_mode,fifon; + + fifon=fifo->fifonum; + transp_mode=0; + if(fifon<4 && hfc->b_mode[fifon/2]==L1_MODE_TRANS) transp_mode=TRUE; + + //printk(KERN_INFO "HFC-USB: got %d bytes finish:%d max_size:%d fifo:%d\n",len,finish,fifo->max_size,fifon); + if(!fifo->skbuff) + { + // allocate sk buffer + fifo->skbuff=dev_alloc_skb(fifo->max_size + 3); + if(!fifo->skbuff) + { + printk(KERN_INFO "HFC-USB: cannot allocate buffer (dev_alloc_skb) fifo:%d\n",fifon); + return; + } + + } + + if(len && fifo->skbuff->len+lenmax_size) + { + memcpy(skb_put(fifo->skbuff,len),data,len); + } + else printk(KERN_INFO "HCF-USB: got frame exceeded fifo->max_size:%d\n",fifo->max_size); + + // give transparent data up, when 128 byte are available + if(transp_mode && fifo->skbuff->len>=128) + { + fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff); + fifo->skbuff = NULL; // buffer was freed from upper layer + return; + } + + // we have a complete hdlc packet + if(finish) + { + if(!fifo->skbuff->data[fifo->skbuff->len-1]) + { + skb_trim(fifo->skbuff,fifo->skbuff->len-3); // remove CRC & status + + //printk(KERN_INFO "HFC-USB: got frame %d bytes on fifo:%d\n",fifo->skbuff->len,fifon); + + if(fifon==HFCUSB_PCM_RX) fifo->hif->l1l2(fifo->hif,PH_DATA_E | INDICATION,fifo->skbuff); + else fifo->hif->l1l2(fifo->hif,PH_DATA | INDICATION,fifo->skbuff); + + fifo->skbuff = NULL; // buffer was freed from upper layer + } + else + { + printk(KERN_INFO "HFC-USB: got frame %d bytes but CRC ERROR!!!\n",fifo->skbuff->len); + + skb_trim(fifo->skbuff,0); // clear whole buffer + } + } + + // LED flashing only in HDLC mode + if(!transp_mode) + { + if(fifon==HFCUSB_B1_RX) handle_led(hfc,LED_B1_DATA); + if(fifon==HFCUSB_B2_RX) handle_led(hfc,LED_B2_DATA); + } +} + +/***********************************************/ +/* receive completion routine for all rx fifos */ +/***********************************************/ +static void rx_complete(struct urb *urb, struct pt_regs *regs) +{ + int len; + __u8 *buf; + usb_fifo *fifo = (usb_fifo *) urb->context; /* pointer to our fifo */ + hfcusb_data *hfc = fifo->hfc; + + urb->dev = hfc->dev; /* security init */ + + if((!fifo->active) || (urb->status)) { +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: RX-Fifo %i is going down (%i)\n", fifo->fifonum, urb->status); +#endif + fifo->urb->interval = 0; /* cancel automatic rescheduling */ + if(fifo->skbuff) { + dev_kfree_skb_any(fifo->skbuff); + fifo->skbuff = NULL; + } + return; + } + + len=urb->actual_length; + buf=fifo->buffer; + + if(fifo->last_urblen!=fifo->usb_packet_maxlen) { + // the threshold mask is in the 2nd status byte + hfc->threshold_mask=buf[1]; + // the S0 state is in the upper half of the 1st status byte + state_handler(hfc,buf[0] >> 4); + // if we have more than the 2 status bytes -> collect data + if(len>2) collect_rx_frame(fifo,buf+2,urb->actual_length-2,buf[0]&1); + } else + collect_rx_frame(fifo,buf,urb->actual_length,0); + + fifo->last_urblen=urb->actual_length; + + +} /* rx_complete */ + + + +/***************************************************/ +/* start the interrupt transfer for the given fifo */ +/***************************************************/ +static void start_int_fifo(usb_fifo * fifo) +{ + int errcode; + +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: starting intr IN fifo:%d\n", fifo->fifonum); +#endif + if (!fifo->urb) { + fifo->urb = usb_alloc_urb(0, GFP_KERNEL); + if (!fifo->urb) + return; + } + usb_fill_int_urb(fifo->urb, fifo->hfc->dev, fifo->pipe, fifo->buffer, + fifo->usb_packet_maxlen, rx_complete, fifo, fifo->intervall); + fifo->active = 1; /* must be marked active */ + errcode = usb_submit_urb(fifo->urb, GFP_KERNEL); + + if(errcode) + { + printk(KERN_INFO "HFC-USB: submit URB error(start_int_info): status:%i\n", errcode); + fifo->active = 0; + fifo->skbuff = NULL; + } +} /* start_int_fifo */ + +/*****************************/ +/* set the B-channel mode */ +/*****************************/ +static void set_hfcmode(hfcusb_data *hfc,int channel,int mode) +{ + __u8 val,idx_table[2]={0,2}; + +#ifdef VERBOSE_ISDN_DEBUG + printk (KERN_INFO "HFC-USB: setting channel %d to mode %d\n",channel,mode); +#endif + + hfc->b_mode[channel]=mode; + + // setup CON_HDLC + val=0; + if(mode!=L1_MODE_NULL) val=8; // enable fifo? + if(mode==L1_MODE_TRANS) val|=2; // set transparent bit + + queue_control_request(hfc,HFCUSB_FIFO,idx_table[channel],1); // set FIFO to transmit register + queue_control_request(hfc,HFCUSB_CON_HDLC,val,1); + queue_control_request(hfc,HFCUSB_INC_RES_F,2,1); // reset fifo + + queue_control_request(hfc,HFCUSB_FIFO,idx_table[channel]+1,1); // set FIFO to receive register + queue_control_request(hfc,HFCUSB_CON_HDLC,val,1); + queue_control_request(hfc,HFCUSB_INC_RES_F,2,1); // reset fifo + + val=0x40; + if(hfc->b_mode[0]) val|=1; + if(hfc->b_mode[1]) val|=2; + queue_control_request(hfc,HFCUSB_SCTRL,val,1); + + val=0; + if(hfc->b_mode[0]) val|=1; + if(hfc->b_mode[1]) val|=2; + queue_control_request(hfc,HFCUSB_SCTRL_R,val,1); + + if(mode==L1_MODE_NULL) + { + if(channel) handle_led(hfc,LED_B2_OFF); + else handle_led(hfc,LED_B1_OFF); + } + else + { + if(channel) handle_led(hfc,LED_B2_ON); + else handle_led(hfc,LED_B1_ON); + } +} + +/* + -------------------------------------------------------------------------------------- + from here : hisax_if callback routines : + - void hfc_usb_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg) { + + l1 to l2 routines : + - static void hfc_usb_l1l2(hfcusb_data * hfc) + +*/ + +void hfc_usb_l2l1(struct hisax_if *my_hisax_if, int pr, void *arg) +{ + usb_fifo *fifo = my_hisax_if->priv; + hfcusb_data *hfc = fifo->hfc; + + switch (pr) { + case PH_ACTIVATE | REQUEST: + if(fifo->fifonum==HFCUSB_D_TX) + { +#ifdef VERBOSE_ISDN_DEBUG + printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_ACTIVATE | REQUEST\n"); +#endif + queue_control_request(hfc, HFCUSB_STATES,0x60,1); /* make activation */ + hfc->t3_timer.expires = jiffies + (HFC_TIMER_T3 * HZ) / 1000; + if(!timer_pending(&hfc->t3_timer)) add_timer(&hfc->t3_timer); + } + else + { +#ifdef VERBOSE_ISDN_DEBUG + printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_ACTIVATE | REQUEST\n"); +#endif + set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)arg); + fifo->hif->l1l2(fifo->hif,PH_ACTIVATE | INDICATION, NULL); + } + break; + case PH_DEACTIVATE | REQUEST: + if(fifo->fifonum==HFCUSB_D_TX) + { +#ifdef VERBOSE_ISDN_DEBUG + printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DEACTIVATE | REQUEST\n"); +#endif + printk (KERN_INFO "HFC-USB: ISDN TE device should not deativate...\n"); + } + else + { +#ifdef VERBOSE_ISDN_DEBUG + printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DEACTIVATE | REQUEST\n"); +#endif + set_hfcmode(hfc,(fifo->fifonum==HFCUSB_B1_TX) ? 0 : 1 ,(int)L1_MODE_NULL); + fifo->hif->l1l2(fifo->hif,PH_DEACTIVATE | INDICATION, NULL); + } + break; + case PH_DATA | REQUEST: + if(fifo->skbuff && fifo->delete_flg) + { + dev_kfree_skb_any(fifo->skbuff); + //printk(KERN_INFO "skbuff=NULL on fifo:%d\n",fifo->fifonum); + fifo->skbuff = NULL; + fifo->delete_flg=FALSE; + } + + fifo->skbuff=arg; // we have a new buffer + + //if(fifo->fifonum==HFCUSB_D_TX) printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 D-chan: PH_DATA | REQUEST\n"); + //else printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1 Bx-chan: PH_DATA | REQUEST\n"); + break; + default: + printk (KERN_INFO "HFC_USB: hfc_usb_d_l2l1: unkown state : %#x\n", pr); + break; + } +} + +// valid configurations +#define CNF_4INT3ISO 1 // 4 INT IN, 3 ISO OUT +#define CNF_3INT3ISO 2 // 3 INT IN, 3 ISO OUT +#define CNF_4ISO3ISO 3 // 4 ISO IN, 3 ISO OUT +#define CNF_3ISO3ISO 4 // 3 ISO IN, 3 ISO OUT + + +/* + -------------------------------------------------------------------------------------- + From here on USB initialization and deactivation related routines are implemented : + + - hfc_usb_init : + is the main Entry Point for the USB Subsystem when the device get plugged + in. This function calls usb_register with usb_driver as parameter. + Here, further entry points for probing (hfc_usb_probe) and disconnecting + the device (hfc_usb_disconnect) are published, as the id_table + + - hfc_usb_probe + this function is called by the usb subsystem, and steps through the alternate + settings of the currently plugged in device to detect all Endpoints needed to + run an ISDN TA. + Needed EndPoints are + 3 (+1) IntIn EndPoints (D-in, E-in, B1-in, B2-in, (E-in)) or + 3 (+1) Isochron In Endpoints (D-out, B1-out, B2-out) and 3 IsoOut Endpoints + The currently used transfer mode of on the Out-Endpoints will be stored in + hfc->usb_transfer_mode and is either USB_INT or USB_ISO + When a valid alternate setting could be found, the usb_init (see blow) + function is called + + - usb_init + Here, the HFC_USB Chip itself gets initialized and the USB framework to send/receive + Data to/from the several EndPoints are initialized: + The E- and D-Channel Int-In chain gets started + The IsoChain for the Iso-Out traffic get started + + - hfc_usb_disconnect + this function is called by the usb subsystem and has to free all resources + and stop all usb traffic to allow a proper hotplugging disconnect. + +*/ + +/***************************************************************************/ +/* usb_init is called once when a new matching device is detected to setup */ +/* main parameters. It registers the driver at the main hisax module. */ +/* on success 0 is returned. */ +/***************************************************************************/ +static int usb_init(hfcusb_data * hfc) +{ + usb_fifo *fifo; + int i, err; + u_char b; + struct hisax_b_if *p_b_if[2]; + + /* check the chip id */ + printk(KERN_INFO "HFCUSB_CHIP_ID begin\n"); + if (read_usb(hfc, HFCUSB_CHIP_ID, &b) != 1) { + printk(KERN_INFO "HFC-USB: cannot read chip id\n"); + return(1); + } + printk(KERN_INFO "HFCUSB_CHIP_ID %x\n", b); + if (b != HFCUSB_CHIPID) { + printk(KERN_INFO "HFC-USB: Invalid chip id 0x%02x\n", b); + return(1); + } + + /* first set the needed config, interface and alternate */ + printk(KERN_INFO "usb_init 1\n"); +// usb_set_configuration(hfc->dev, 1); + printk(KERN_INFO "usb_init 2\n"); + err = usb_set_interface(hfc->dev, hfc->if_used, hfc->alt_used); + printk(KERN_INFO "usb_init usb_set_interface return %d\n", err); + /* now we initialize the chip */ + write_usb(hfc, HFCUSB_CIRM, 8); // do reset + write_usb(hfc, HFCUSB_CIRM, 0x10); // aux = output, reset off + + // set USB_SIZE to match the the wMaxPacketSize for INT or BULK transfers + write_usb(hfc, HFCUSB_USB_SIZE,(hfc->packet_size/8) | ((hfc->packet_size/8) << 4)); + + // set USB_SIZE_I to match the the wMaxPacketSize for ISO transfers + write_usb(hfc, HFCUSB_USB_SIZE_I, hfc->iso_packet_size); + + /* enable PCM/GCI master mode */ + write_usb(hfc, HFCUSB_MST_MODE1, 0); /* set default values */ + write_usb(hfc, HFCUSB_MST_MODE0, 1); /* enable master mode */ + + /* init the fifos */ + write_usb(hfc, HFCUSB_F_THRES, (HFCUSB_TX_THRESHOLD/8) |((HFCUSB_RX_THRESHOLD/8) << 4)); + + fifo = hfc->fifos; + for(i = 0; i < HFCUSB_NUM_FIFOS; i++) + { + write_usb(hfc, HFCUSB_FIFO, i); /* select the desired fifo */ + fifo[i].skbuff = NULL; /* init buffer pointer */ + fifo[i].max_size = (i <= HFCUSB_B2_RX) ? MAX_BCH_SIZE : MAX_DFRAME_LEN; + fifo[i].last_urblen=0; + write_usb(hfc, HFCUSB_HDLC_PAR, ((i <= HFCUSB_B2_RX) ? 0 : 2)); // set 2 bit for D- & E-channel + write_usb(hfc, HFCUSB_CON_HDLC, ((i==HFCUSB_D_TX) ? 0x09 : 0x08)); // rx hdlc, enable IFF for D-channel + write_usb(hfc, HFCUSB_INC_RES_F, 2); /* reset the fifo */ + } + + write_usb(hfc, HFCUSB_CLKDEL, 0x0f); /* clock delay value */ + write_usb(hfc, HFCUSB_STATES, 3 | 0x10); /* set deactivated mode */ + write_usb(hfc, HFCUSB_STATES, 3); /* enable state machine */ + + write_usb(hfc, HFCUSB_SCTRL_R, 0); /* disable both B receivers */ + write_usb(hfc, HFCUSB_SCTRL, 0x40); /* disable B transmitters + capacitive mode */ + + // set both B-channel to not connected + hfc->b_mode[0]=L1_MODE_NULL; + hfc->b_mode[1]=L1_MODE_NULL; + + hfc->l1_activated=FALSE; + hfc->led_state=0; + hfc->led_new_data=0; + + /* init the t3 timer */ + init_timer(&hfc->t3_timer); + hfc->t3_timer.data = (long) hfc; + hfc->t3_timer.function = (void *) l1_timer_expire_t3; + /* init the t4 timer */ + init_timer(&hfc->t4_timer); + hfc->t4_timer.data = (long) hfc; + hfc->t4_timer.function = (void *) l1_timer_expire_t4; + /* init the led timer */ + init_timer(&hfc->led_timer); + hfc->led_timer.data = (long) hfc; + hfc->led_timer.function = (void *) led_timer; + // trigger 4 hz led timer + hfc->led_timer.expires = jiffies + (LED_TIME * HZ) / 1000; + if(!timer_pending(&hfc->led_timer)) add_timer(&hfc->led_timer); + + // init the background machinery for control requests + hfc->ctrl_read.bRequestType = 0xc0; + hfc->ctrl_read.bRequest = 1; + hfc->ctrl_read.wLength = 1; + hfc->ctrl_write.bRequestType = 0x40; + hfc->ctrl_write.bRequest = 0; + hfc->ctrl_write.wLength = 0; + usb_fill_control_urb(hfc->ctrl_urb, hfc->dev, hfc->ctrl_out_pipe,(u_char *) & hfc->ctrl_write, NULL, 0, ctrl_complete, hfc); + + /* Init All Fifos */ + for(i = 0; i < HFCUSB_NUM_FIFOS; i++) + { + hfc->fifos[i].iso[0].purb = NULL; + hfc->fifos[i].iso[1].purb = NULL; + hfc->fifos[i].active = 0; + } + + // register like Germaschewski : + hfc->d_if.owner = THIS_MODULE; + hfc->d_if.ifc.priv = &hfc->fifos[HFCUSB_D_TX]; + hfc->d_if.ifc.l2l1 = hfc_usb_l2l1; + + for (i=0; i<2; i++) + { + hfc->b_if[i].ifc.priv = &hfc->fifos[HFCUSB_B1_TX+i*2]; + hfc->b_if[i].ifc.l2l1 = hfc_usb_l2l1; + p_b_if[i] = &hfc->b_if[i]; + } + + hfc->protocol = 2; /* default EURO ISDN, should be a module_param */ + hisax_register(&hfc->d_if, p_b_if, "hfc_usb", hfc->protocol); + + for (i=0; i<4; i++) + hfc->fifos[i].hif=&p_b_if[i/2]->ifc; + for (i=4; i<8; i++) + hfc->fifos[i].hif=&hfc->d_if.ifc; + + // 3 (+1) INT IN + 3 ISO OUT + if(hfc->cfg_used == CNF_3INT3ISO || hfc->cfg_used == CNF_4INT3ISO) + { + start_int_fifo(hfc->fifos + HFCUSB_D_RX); // Int IN D-fifo + if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_int_fifo(hfc->fifos + HFCUSB_PCM_RX); // E-fifo + start_int_fifo(hfc->fifos + HFCUSB_B1_RX); // Int IN B1-fifo + start_int_fifo(hfc->fifos + HFCUSB_B2_RX); // Int IN B2-fifo + } + + // 3 (+1) ISO IN + 3 ISO OUT + if(hfc->cfg_used==CNF_3ISO3ISO || hfc->cfg_used==CNF_4ISO3ISO) + { + start_isoc_chain(hfc->fifos + HFCUSB_D_RX, ISOC_PACKETS_D, rx_iso_complete,16); + if(hfc->fifos[HFCUSB_PCM_RX].pipe) start_isoc_chain(hfc->fifos + HFCUSB_PCM_RX, ISOC_PACKETS_D, rx_iso_complete,16); + start_isoc_chain(hfc->fifos + HFCUSB_B1_RX, ISOC_PACKETS_B, rx_iso_complete,16); + start_isoc_chain(hfc->fifos + HFCUSB_B2_RX, ISOC_PACKETS_B, rx_iso_complete,16); + } + + start_isoc_chain(hfc->fifos + HFCUSB_D_TX, ISOC_PACKETS_D, tx_iso_complete,1); + start_isoc_chain(hfc->fifos + HFCUSB_B1_TX, ISOC_PACKETS_B, tx_iso_complete,1); + start_isoc_chain(hfc->fifos + HFCUSB_B2_TX, ISOC_PACKETS_B, tx_iso_complete,1); + + handle_led(hfc,LED_POWER_ON); + + return(0); +} /* usb_init */ + + +/****************************************/ +/* data defining the devices to be used */ +/****************************************/ +// static __devinitdata const struct usb_device_id hfc_usb_idtab[3] = { +static struct usb_device_id hfc_usb_idtab[] = { + {USB_DEVICE(0x7b0, 0x0007)}, /* Billion USB TA 2 */ + {USB_DEVICE(0x742, 0x2008)}, /* Stollmann USB TA */ + {USB_DEVICE(0x959, 0x2bd0)}, /* Colognechip USB eval TA */ + {USB_DEVICE(0x8e3, 0x0301)}, /* OliTec ISDN USB */ + {USB_DEVICE(0x675, 0x1688)}, /* DrayTec ISDN USB */ + {USB_DEVICE(0x7fa, 0x0846)}, /* Bewan ISDN USB TA */ + {} /* end with an all-zeroes entry */ +}; + +MODULE_AUTHOR("Peter Sprenger (sprenger@moving-byters.de)/Martin Bachem (info@colognechip.com)"); +MODULE_DESCRIPTION("HFC I4L USB driver"); +MODULE_DEVICE_TABLE(usb, hfc_usb_idtab); +MODULE_LICENSE("GPL"); + +#define EP_NUL 1 // Endpoint at this position not allowed +#define EP_NOP 2 // all type of endpoints allowed at this position +#define EP_ISO 3 // Isochron endpoint mandatory at this position +#define EP_BLK 4 // Bulk endpoint mandatory at this position +#define EP_INT 5 // Interrupt endpoint mandatory at this position + +// this array represents all endpoints possible in the HCF-USB +// the last 2 entries are the configuration number and the minimum interval for Interrupt endpoints +int validconf[][18]= +{ + // INT in, ISO out config + {EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NOP,EP_INT,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_4INT3ISO,2}, + {EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_INT,EP_NUL,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_ISO,EP_NUL,EP_NUL,EP_NUL,CNF_3INT3ISO,2}, + // ISO in, ISO out config + {EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NOP,EP_ISO,CNF_4ISO3ISO,2}, + {EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_NUL,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_ISO,EP_NUL,EP_NUL,CNF_3ISO3ISO,2}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} // EOL element +}; + +// string description of chosen config +char *conf_str[]= +{ + "4 Interrupt IN + 3 Isochron OUT", + "3 Interrupt IN + 3 Isochron OUT", + "4 Isochron IN + 3 Isochron OUT", + "3 Isochron IN + 3 Isochron OUT" +}; + + +/*************************************************/ +/* function called to probe a new plugged device */ +/*************************************************/ +static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct usb_device *dev= interface_to_usbdev(intf); + hfcusb_data *context; + struct usb_host_interface *iface = intf->altsetting + intf->act_altsetting; + struct usb_host_endpoint *ep; + int i, idx, probe_alt_setting,vend_idx, cfg_used, *vcf, attr, cfg_found, cidx, ep_addr; + int cmptbl[16],small_match,iso_packet_size,packet_size,alt_used=0; + +// usb_show_device(dev); +// usb_show_device_descriptor(&dev->descriptor); +// usb_show_interface_descriptor(&iface->desc); + vend_idx=0xffff; + for(i=0;vdata[i].vendor;i++) + { + if(dev->descriptor.idVendor==vdata[i].vendor && dev->descriptor.idProduct==vdata[i].prod_id) vend_idx=i; + } + + +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n", + intf->altsetting->desc.bInterfaceNumber, intf->act_altsetting, intf->minor); +#endif + + if (vend_idx != 0xffff) { +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: found vendor idx:%d name:%s\n",vend_idx,vdata[vend_idx].vend_name); +#endif + /* if vendor and product ID is OK, start probing a matching alternate setting ... */ + probe_alt_setting = 0; + small_match=0xffff; + // default settings + iso_packet_size=16; + packet_size=64; + + while(probe_alt_setting < intf->num_altsetting) { + iface = intf->altsetting + probe_alt_setting; + cfg_used=0; + +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: test alt_setting %d\n", probe_alt_setting); +#endif + // check for config EOL element + while (validconf[cfg_used][0]) { + cfg_found=TRUE; + vcf=validconf[cfg_used]; + ep = iface->endpoint; /* first endpoint descriptor */ + +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: (if=%d alt=%d cfg_used=%d)\n", + probe_alt_setting, intf->act_altsetting,cfg_used); +#endif + // copy table + memcpy(cmptbl,vcf,16*sizeof(int)); + + // check for all endpoints in this alternate setting + for (i=0; i < iface->desc.bNumEndpoints; i++) { + ep_addr = ep->desc.bEndpointAddress; + idx = ((ep_addr & 0x7f)-1)*2; /* get endpoint base */ + if (ep_addr & 0x80) + idx++; + attr = ep->desc.bmAttributes; + + if (cmptbl[idx] == EP_NUL) { + printk(KERN_INFO "HFC-USB: cfg_found=FALSE in idx:%d attr:%d cmptbl[%d]:%d\n", + idx, attr, idx, cmptbl[idx]); + cfg_found = FALSE; + } + + if (attr == USB_ENDPOINT_XFER_INT && cmptbl[idx] == EP_INT) + cmptbl[idx] = EP_NUL; + if (attr == USB_ENDPOINT_XFER_BULK && cmptbl[idx] == EP_BLK) + cmptbl[idx] = EP_NUL; + if (attr == USB_ENDPOINT_XFER_ISOC && cmptbl[idx] == EP_ISO) + cmptbl[idx] = EP_NUL; + + // check if all INT endpoints match minimum interval + if (attr == USB_ENDPOINT_XFER_INT && ep->desc.bInterval < vcf[17]) { +#ifdef VERBOSE_USB_DEBUG + if (cfg_found) + printk(KERN_INFO "HFC-USB: Interrupt Endpoint interval < %d found - skipping config\n", + vcf[17]); +#endif + cfg_found = FALSE; + } + + ep++; + } + + for (i = 0; i < 16; i++) { + // printk(KERN_INFO "HFC-USB: cmptbl[%d]:%d\n", i, cmptbl[i]); + + // all entries must be EP_NOP or EP_NUL for a valid config + if (cmptbl[i] != EP_NOP && cmptbl[i] != EP_NUL) + cfg_found = FALSE; + } + + // we check for smallest match, to provide configuration priority + // configurations with smaller index have higher priority + if (cfg_found) { + if (cfg_used < small_match) { + small_match = cfg_used; + alt_used = probe_alt_setting; + } +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: small_match=%x %x\n", small_match, alt_used); +#endif + } + + cfg_used++; + } + + probe_alt_setting++; + } /* (probe_alt_setting < intf->num_altsetting) */ +#ifdef VERBOSE_USB_DEBUG + printk(KERN_INFO "HFC-USB: final small_match=%x alt_used=%x\n",small_match, alt_used); +#endif + // yiipiee, we found a valid config + if (small_match != 0xffff) { + intf->act_altsetting = alt_used; + iface = intf->altsetting + intf->act_altsetting; + + if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL))) + return(-ENOMEM); /* got no mem */ + memset(context, 0, sizeof(hfcusb_data)); /* clear the structure */ + + ep = iface->endpoint; /* first endpoint descriptor */ + vcf = validconf[small_match]; + + for (i = 0; i < iface->desc.bNumEndpoints; i++) { + ep_addr = ep->desc.bEndpointAddress; + idx = ((ep_addr & 0x7f)-1)*2; /* get endpoint base */ + if (ep_addr & 0x80) + idx++; + cidx = idx & 7; + attr = ep->desc.bmAttributes; + + // only initialize used endpoints + if (vcf[idx] != EP_NOP && vcf[idx] != EP_NUL) { + switch (attr) { + case USB_ENDPOINT_XFER_INT: + context->fifos[cidx].pipe = usb_rcvintpipe(dev, ep->desc.bEndpointAddress); + context->fifos[cidx].usb_transfer_mode = USB_INT; + packet_size = ep->desc.wMaxPacketSize; // remember max packet size +#ifdef VERBOSE_USB_DEBUG + printk (KERN_INFO "HFC-USB: Interrupt-In Endpoint found %d ms(idx:%d cidx:%d)!\n", + ep->desc.bInterval, idx, cidx); +#endif + break; + case USB_ENDPOINT_XFER_BULK: + if (ep_addr & 0x80) + context->fifos[cidx].pipe = usb_rcvbulkpipe(dev, ep->desc.bEndpointAddress); + else + context->fifos[cidx].pipe = usb_sndbulkpipe(dev, ep->desc.bEndpointAddress); + context->fifos[cidx].usb_transfer_mode = USB_BULK; + packet_size = ep->desc.wMaxPacketSize; // remember max packet size +#ifdef VERBOSE_USB_DEBUG + printk (KERN_INFO "HFC-USB: Bulk Endpoint found (idx:%d cidx:%d)!\n", + idx, cidx); +#endif + break; + case USB_ENDPOINT_XFER_ISOC: + if (ep_addr & 0x80) + context->fifos[cidx].pipe = usb_rcvisocpipe(dev, ep->desc.bEndpointAddress); + else + context->fifos[cidx].pipe = usb_sndisocpipe(dev, ep->desc.bEndpointAddress); + context->fifos[cidx].usb_transfer_mode = USB_ISOC; + iso_packet_size = ep->desc.wMaxPacketSize; // remember max packet size +#ifdef VERBOSE_USB_DEBUG + printk (KERN_INFO "HFC-USB: ISO Endpoint found (idx:%d cidx:%d)!\n", + idx, cidx); +#endif + break; + default: + context->fifos[cidx].pipe = 0; /* reset data */ + } /* switch attribute */ + + if (context->fifos[cidx].pipe) { + context->fifos[cidx].fifonum = cidx; + context->fifos[cidx].hfc = context; + context->fifos[cidx].usb_packet_maxlen = ep->desc.wMaxPacketSize; + context->fifos[cidx].intervall = ep->desc.bInterval; + context->fifos[cidx].skbuff = NULL; +#ifdef VERBOSE_USB_DEBUG + printk (KERN_INFO "HFC-USB: fifo%d pktlen %d interval %d\n", + context->fifos[cidx].fifonum, + context->fifos[cidx].usb_packet_maxlen, + context->fifos[cidx].intervall); +#endif + } + } + + ep++; + } + + // now share our luck + context->dev = dev; /* save device */ + context->if_used = intf->altsetting->desc.bInterfaceNumber; /* save used interface */ + context->alt_used = intf->act_altsetting; /* and alternate config */ + context->ctrl_paksize = dev->descriptor.bMaxPacketSize0; /* control size */ + context->cfg_used=vcf[16]; // store used config + context->vend_idx=vend_idx; // store found vendor + context->packet_size=packet_size; + context->iso_packet_size=iso_packet_size; + + /* create the control pipes needed for register access */ + context->ctrl_in_pipe = usb_rcvctrlpipe(context->dev, 0); + context->ctrl_out_pipe = usb_sndctrlpipe(context->dev, 0); + context->ctrl_urb = usb_alloc_urb(0, GFP_KERNEL); + + printk(KERN_INFO "HFC-USB: detected \"%s\" configuration: %s (if=%d alt=%d)\n", + vdata[vend_idx].vend_name, conf_str[small_match], context->if_used, context->alt_used); + + /* init the chip and register the driver */ + if (usb_init(context)) + { + if (context->ctrl_urb) { + usb_unlink_urb(context->ctrl_urb); + usb_free_urb(context->ctrl_urb); + context->ctrl_urb = NULL; + } + kfree(context); + return(-EIO); + } + usb_set_intfdata(intf, context); + return(0); + } + } + return(-EIO); +} + +/****************************************************/ +/* function called when an active device is removed */ +/****************************************************/ +static void hfc_usb_disconnect(struct usb_interface *intf) +{ + hfcusb_data *context = usb_get_intfdata(intf); + int i; + + printk(KERN_INFO "HFC-USB: device disconnect\n"); + + usb_set_intfdata(intf, NULL); + if (!context) + return; + if (timer_pending(&context->t3_timer)) + del_timer(&context->t3_timer); + if (timer_pending(&context->t4_timer)) + del_timer(&context->t4_timer); + if (timer_pending(&context->led_timer)) + del_timer(&context->led_timer); + + hisax_unregister(&context->d_if); + + /* tell all fifos to terminate */ + for(i = 0; i < HFCUSB_NUM_FIFOS; i++) { + if(context->fifos[i].usb_transfer_mode == USB_ISOC) { + if(context->fifos[i].active > 0) { + stop_isoc_chain(&context->fifos[i]); +#ifdef VERBOSE_USB_DEBUG + printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: stopping ISOC chain Fifo no %i\n", i); +#endif + } + } else { + if(context->fifos[i].active > 0) { + context->fifos[i].active = 0; +#ifdef VERBOSE_USB_DEBUG + printk (KERN_INFO "HFC-USB: hfc_usb_disconnect: unlinking URB for Fifo no %i\n", i); +#endif + } + if (context->fifos[i].urb) { + usb_unlink_urb(context->fifos[i].urb); + usb_free_urb(context->fifos[i].urb); + context->fifos[i].urb = NULL; + } + } + context->fifos[i].active = 0; + } + if (context->ctrl_urb) { + usb_unlink_urb(context->ctrl_urb); + usb_free_urb(context->ctrl_urb); + context->ctrl_urb = NULL; + } + kfree(context); /* free our structure again */ +} /* hfc_usb_disconnect */ + + +/************************************/ +/* our driver information structure */ +/************************************/ +static struct usb_driver hfc_drv = { + .owner = THIS_MODULE, + .name = "hfc_usb", + .id_table = hfc_usb_idtab, + .probe = hfc_usb_probe, + .disconnect = hfc_usb_disconnect, +}; + +static void __exit hfc_usb_exit(void) +{ +#ifdef VERBOSE_USB_DEBUG + printk ("HFC-USB: calling \"hfc_usb_exit\" ...\n"); +#endif + usb_deregister(&hfc_drv); /* release our driver */ + printk(KERN_INFO "HFC-USB module removed\n"); +} + +static int __init hfc_usb_init(void) +{ + printk ("HFC-USB: driver module revision %s loaded\n", hfcusb_revision); + + if(usb_register(&hfc_drv)) + { + printk(KERN_INFO "HFC-USB: Unable to register HFC-USB module at usb stack\n"); + return(-1); /* unable to register */ + } + return(0); +} + +module_init(hfc_usb_init); +module_exit(hfc_usb_exit); diff -Nru a/drivers/isdn/hisax/hfcscard.c b/drivers/isdn/hisax/hfcscard.c --- a/drivers/isdn/hisax/hfcscard.c Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/hisax/hfcscard.c Thu Feb 19 23:44:28 2004 @@ -1,4 +1,4 @@ -/* $Id: hfcscard.c,v 1.8.6.2 2001/09/23 22:24:48 kai Exp $ +/* $Id: hfcscard.c,v 1.10.2.4 2004/01/14 16:04:48 keil Exp $ * * low level stuff for hfcs based cards (Teles3c, ACER P10) * @@ -18,33 +18,19 @@ extern const char *CardType[]; -static const char *hfcs_revision = "$Revision: 1.8.6.2 $"; - -static inline u8 -hfcs_read_reg(struct IsdnCardState *cs, int data, u8 reg) -{ - return cs->bc_hw_ops->read_reg(cs, data, reg); -} - -static inline void -hfcs_write_reg(struct IsdnCardState *cs, int data, u8 reg, u8 val) -{ - cs->bc_hw_ops->write_reg(cs, data, reg, val); -} +static const char *hfcs_revision = "$Revision: 1.10.2.4 $"; static irqreturn_t hfcs_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val, stat; + u_char val, stat; + u_long flags; - if (!cs) { - printk(KERN_WARNING "HFCS: Spurious interrupt!\n"); - return IRQ_NONE; - } + spin_lock_irqsave(&cs->lock, flags); if ((HFCD_ANYINT | HFCD_BUSY_NBUSY) & - (stat = hfcs_read_reg(cs, HFCD_DATA, HFCD_STAT))) { - val = hfcs_read_reg(cs, HFCD_DATA, HFCD_INT_S1); + (stat = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_STAT))) { + val = cs->BC_Read_Reg(cs, HFCD_DATA, HFCD_INT_S1); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "HFCS: stat(%02x) s1(%02x)", stat, val); hfc2bds0_interrupt(cs, val); @@ -52,6 +38,7 @@ if (cs->debug & L1_DEB_ISAC) debugl1(cs, "HFCS: irq_no_irq stat(%02x)", stat); } + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } @@ -65,117 +52,91 @@ */ } -static void -hfcs_release(struct IsdnCardState *cs) +void +release_io_hfcs(struct IsdnCardState *cs) { release2bds0(cs); del_timer(&cs->hw.hfcD.timer); - hisax_release_resources(cs); + if (cs->hw.hfcD.addr) + release_region(cs->hw.hfcD.addr, 2); } -static int -hfcs_reset(struct IsdnCardState *cs) +static void +reset_hfcs(struct IsdnCardState *cs) { printk(KERN_INFO "HFCS: resetting card\n"); cs->hw.hfcD.cirm = HFCD_RESET; if (cs->typ == ISDN_CTYPE_TELES3C) cs->hw.hfcD.cirm |= HFCD_MEM8K; - hfcs_write_reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset On */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30*HZ)/1000); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset On */ + mdelay(10); cs->hw.hfcD.cirm = 0; if (cs->typ == ISDN_CTYPE_TELES3C) cs->hw.hfcD.cirm |= HFCD_MEM8K; - hfcs_write_reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); /* Reset Off */ + mdelay(10); if (cs->typ == ISDN_CTYPE_TELES3C) cs->hw.hfcD.cirm |= HFCD_INTB; else if (cs->typ == ISDN_CTYPE_ACERP10) cs->hw.hfcD.cirm |= HFCD_INTA; - hfcs_write_reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); - hfcs_write_reg(cs, HFCD_DATA, HFCD_CLKDEL, 0x0e); - hfcs_write_reg(cs, HFCD_DATA, HFCD_TEST, HFCD_AUTO_AWAKE); /* S/T Auto awake */ + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CIRM, cs->hw.hfcD.cirm); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CLKDEL, 0x0e); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_TEST, HFCD_AUTO_AWAKE); /* S/T Auto awake */ cs->hw.hfcD.ctmt = HFCD_TIM25 | HFCD_AUTO_TIMER; - hfcs_write_reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); cs->hw.hfcD.int_m2 = HFCD_IRQ_ENABLE; cs->hw.hfcD.int_m1 = HFCD_INTS_B1TRANS | HFCD_INTS_B2TRANS | HFCD_INTS_DTRANS | HFCD_INTS_B1REC | HFCD_INTS_B2REC | HFCD_INTS_DREC | HFCD_INTS_L1STATE; - hfcs_write_reg(cs, HFCD_DATA, HFCD_INT_M1, cs->hw.hfcD.int_m1); - hfcs_write_reg(cs, HFCD_DATA, HFCD_INT_M2, cs->hw.hfcD.int_m2); - hfcs_write_reg(cs, HFCD_DATA, HFCD_STATES, HFCD_LOAD_STATE | 2); /* HFC ST 2 */ + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M1, cs->hw.hfcD.int_m1); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_INT_M2, cs->hw.hfcD.int_m2); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, HFCD_LOAD_STATE | 2); /* HFC ST 2 */ udelay(10); - hfcs_write_reg(cs, HFCD_DATA, HFCD_STATES, 2); /* HFC ST 2 */ + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_STATES, 2); /* HFC ST 2 */ cs->hw.hfcD.mst_m = HFCD_MASTER; - hfcs_write_reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); /* HFC Master */ + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); /* HFC Master */ cs->hw.hfcD.sctrl = 0; - hfcs_write_reg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl); - return 0; + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_SCTRL, cs->hw.hfcD.sctrl); } -static void -hfcs_init(struct IsdnCardState *cs) -{ - cs->hw.hfcD.timer.expires = jiffies + 75; - add_timer(&cs->hw.hfcD.timer); - init2bds0(cs); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((80*HZ)/1000); - cs->hw.hfcD.ctmt |= HFCD_TIM800; - hfcs_write_reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); - hfcs_write_reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); -} - -static struct card_ops hfcs_ops = { - .init = hfcs_init, - .reset = hfcs_reset, - .release = hfcs_release, - .irq_func = hfcs_interrupt, -}; - -static int __init -hfcs_probe(struct IsdnCardState *cs, struct IsdnCard *card) +static int +hfcs_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - cs->irq = card->para[0]; - cs->hw.hfcD.addr = card->para[1]; + u_long flags; + int delay; - if (!request_io(&cs->rs, cs->hw.hfcD.addr, 2, "HFCS isdn")) - goto err; - - printk(KERN_INFO "HFCS: defined at 0x%x IRQ %d\n", - cs->hw.hfcD.addr, cs->irq); - - cs->hw.hfcD.cip = 0; - cs->hw.hfcD.int_s1 = 0; - cs->hw.hfcD.send = NULL; - cs->bcs[0].hw.hfc.send = NULL; - cs->bcs[1].hw.hfc.send = NULL; - cs->hw.hfcD.dfifosize = 512; - cs->dc.hfcd.ph_state = 0; - cs->hw.hfcD.fifo = 255; - - if (cs->typ == ISDN_CTYPE_TELES3C) { - cs->hw.hfcD.bfifosize = 1024 + 512; - /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */ - outb(0x00, cs->hw.hfcD.addr); - outb(0x56, cs->hw.hfcD.addr | 1); - } else if (cs->typ == ISDN_CTYPE_ACERP10) { - cs->hw.hfcD.bfifosize = 7*1024 + 512; - /* Acer P10 IO ADR is 0x300 */ - outb(0x00, cs->hw.hfcD.addr); - outb(0x57, cs->hw.hfcD.addr | 1); + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "HFCS: card_msg %x", mt); + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_hfcs(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_hfcs(cs); + return(0); + case CARD_INIT: + delay = (75*HZ)/100 +1; + cs->hw.hfcD.timer.expires = jiffies + delay; + add_timer(&cs->hw.hfcD.timer); + spin_lock_irqsave(&cs->lock, flags); + reset_hfcs(cs); + init2bds0(cs); + spin_unlock_irqrestore(&cs->lock, flags); + delay = (80*HZ)/1000 +1; + set_current_state(TASK_UNINTERRUPTIBLE); + schedule_timeout((80*HZ)/1000); + spin_lock_irqsave(&cs->lock, flags); + cs->hw.hfcD.ctmt |= HFCD_TIM800; + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcD.ctmt); + cs->BC_Write_Reg(cs, HFCD_DATA, HFCD_MST_MODE, cs->hw.hfcD.mst_m); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); } - set_cs_func(cs); - init_timer(&cs->hw.hfcD.timer); - cs->hw.hfcD.timer.function = (void *) hfcs_Timer; - cs->hw.hfcD.timer.data = (long) cs; - hfcs_reset(cs); - cs->card_ops = &hfcs_ops; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + return(0); } #ifdef __ISAPNP__ @@ -204,13 +165,14 @@ { 0, } }; -static struct isapnp_device_id *hdev = &hfc_ids[0]; +static struct isapnp_device_id *ipid __initdata = &hfc_ids[0]; static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __init setup_hfcs(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, hfcs_revision); @@ -218,54 +180,88 @@ #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; + struct pnp_dev *pnp_d; + while(ipid->card_vendor) { + if ((pnp_c = pnp_find_card(ipid->card_vendor, + ipid->card_device, pnp_c))) { + pnp_d = NULL; + if ((pnp_d = pnp_find_dev(pnp_c, + ipid->vendor, ipid->function, pnp_d))) { + int err; - while(hdev->card_vendor) { - if ((pb = pnp_find_card(hdev->card_vendor, - hdev->card_device, - pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - hdev->vendor, - hdev->function, - pd))) { printk(KERN_INFO "HiSax: %s detected\n", - (char *)hdev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "HFC PnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "HFC PnP: activate failed\n"); - pnp_device_detach(pd); - return 0; + (char *)ipid->driver_data); + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[0] = pnp_irq(pnp_d, 0); + if (!card->para[0] || !card->para[1]) { printk(KERN_ERR "HFC PnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); + card->para[0], card->para[1]); + pnp_disable_dev(pnp_d); return(0); } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); break; } else { printk(KERN_ERR "HFC PnP: PnP error card found, no device\n"); } } - hdev++; - pnp_c=NULL; + ipid++; + pnp_c = NULL; } - if (!hdev->card_vendor) { + if (!ipid->card_vendor) { printk(KERN_INFO "HFC PnP: no ISAPnP card found\n"); return(0); } } #endif - if (hfcs_probe(card->cs, card) < 0) - return 0; - return 1; - + cs->hw.hfcD.addr = card->para[1] & 0xfffe; + cs->irq = card->para[0]; + cs->hw.hfcD.cip = 0; + cs->hw.hfcD.int_s1 = 0; + cs->hw.hfcD.send = NULL; + cs->bcs[0].hw.hfc.send = NULL; + cs->bcs[1].hw.hfc.send = NULL; + cs->hw.hfcD.dfifosize = 512; + cs->dc.hfcd.ph_state = 0; + cs->hw.hfcD.fifo = 255; + if (cs->typ == ISDN_CTYPE_TELES3C) { + cs->hw.hfcD.bfifosize = 1024 + 512; + } else if (cs->typ == ISDN_CTYPE_ACERP10) { + cs->hw.hfcD.bfifosize = 7*1024 + 512; + } else + return (0); + if (!request_region(cs->hw.hfcD.addr, 2, "HFCS isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.hfcD.addr, + cs->hw.hfcD.addr + 2); + return (0); + } + printk(KERN_INFO + "HFCS: defined at 0x%x IRQ %d HZ %d\n", + cs->hw.hfcD.addr, + cs->irq, HZ); + if (cs->typ == ISDN_CTYPE_TELES3C) { + /* Teles 16.3c IO ADR is 0x200 | YY0U (YY Bit 15/14 address) */ + outb(0x00, cs->hw.hfcD.addr); + outb(0x56, cs->hw.hfcD.addr | 1); + } else if (cs->typ == ISDN_CTYPE_ACERP10) { + /* Acer P10 IO ADR is 0x300 */ + outb(0x00, cs->hw.hfcD.addr); + outb(0x57, cs->hw.hfcD.addr | 1); + } + set_cs_func(cs); + cs->hw.hfcD.timer.function = (void *) hfcs_Timer; + cs->hw.hfcD.timer.data = (long) cs; + init_timer(&cs->hw.hfcD.timer); + cs->cardmsg = &hfcs_card_msg; + cs->irq_func = &hfcs_interrupt; + return (1); } diff -Nru a/drivers/isdn/hisax/hisax.h b/drivers/isdn/hisax/hisax.h --- a/drivers/isdn/hisax/hisax.h Thu Feb 19 23:44:26 2004 +++ b/drivers/isdn/hisax/hisax.h Thu Feb 19 23:44:26 2004 @@ -1,4 +1,4 @@ -/* $Id: hisax.h,v 1.1.4.1.2.1 2001/12/09 20:18:40 kai Exp $ +/* $Id: hisax.h,v 2.64.2.4 2004/02/11 13:21:33 keil Exp $ * * Basic declarations, defines and prototypes * @@ -6,14 +6,11 @@ * of the GNU General Public License, incorporated herein by reference. * */ - -#ifndef __HISAX_H__ -#define __HISAX_H__ - #include #include #include #include +#include #include #include #include @@ -28,7 +25,6 @@ #include #include #include -#include #define ERROR_STATISTIC @@ -51,6 +47,11 @@ #define HW_INFO4_P10 0x0048 #define HW_RSYNC 0x0060 #define HW_TESTLOOP 0x0070 +#define CARD_RESET 0x00F0 +#define CARD_INIT 0x00F2 +#define CARD_RELEASE 0x00F3 +#define CARD_TEST 0x00F4 +#define CARD_AUX_IND 0x00F5 #define PH_ACTIVATE 0x0100 #define PH_DEACTIVATE 0x0110 @@ -68,9 +69,14 @@ #define DL_FLUSH 0x0224 #define DL_UNIT_DATA 0x0230 +#define MDL_BC_RELEASE 0x0278 // Formula-n enter:now +#define MDL_BC_ASSIGN 0x027C // Formula-n enter:now #define MDL_ASSIGN 0x0280 #define MDL_REMOVE 0x0284 #define MDL_ERROR 0x0288 +#define MDL_INFO_SETUP 0x02E0 +#define MDL_INFO_CONN 0x02E4 +#define MDL_INFO_REL 0x02E8 #define CC_SETUP 0x0300 #define CC_RESUME 0x0304 @@ -145,35 +151,6 @@ /* #define I4L_IRQ_FLAG SA_INTERRUPT */ #define I4L_IRQ_FLAG 0 -struct res { - struct list_head node; - const char *name; - unsigned long start, end; - unsigned long flags; - union { - void *ioremap_addr; - } r_u; -}; - -struct resources { - struct list_head res_head; -}; - -void -resources_init(struct resources *rs); - -void -resources_release(struct resources *rs); - -unsigned long -request_io(struct resources *rs, unsigned long start, int len, - const char *name); - -void * -request_mmio(struct resources *rs, unsigned long start, int len, - const char *name); - - /* * Statemachine */ @@ -230,9 +207,9 @@ long Flags; struct FsmInst l1m; struct FsmTimer timer; + void (*l1l2) (struct PStack *, int, void *); void (*l1hw) (struct PStack *, int, void *); void (*l1tei) (struct PStack *, int, void *); - void (*l2l1) (struct PStack *, int, void *); int mode, bc; int delay; }; @@ -265,17 +242,18 @@ struct Layer2 { int tei; int sap; - u_int maxlen; - unsigned long flag; - unsigned int vs, va, vr; + int maxlen; + u_long flag; + spinlock_t lock; + u_int vs, va, vr; int rc; unsigned int window; unsigned int sow; struct sk_buff *windowar[MAX_WINDOW]; struct sk_buff_head i_queue; struct sk_buff_head ui_queue; - void (*l3l2) (struct PStack *, int, void *); - void (*l1l2) (struct PStack *, int, void *); + void (*l2l1) (struct PStack *, int, void *); + void (*l2l3) (struct PStack *, int, void *); void (*l2tei) (struct PStack *, int, void *); struct FsmInst l2m; struct FsmTimer t200, t203; @@ -285,10 +263,9 @@ }; struct Layer3 { - void (*l4l3) (struct PStack *, int, void *); - int (*l4l3_proto) (struct PStack *, isdn_ctrl *); + void (*l3l4) (struct PStack *, int, void *); void (*l3ml3) (struct PStack *, int, void *); - void (*l2l3) (struct PStack *, int, void *); + void (*l3l2) (struct PStack *, int, void *); struct FsmInst l3m; struct FsmTimer l3m_timer; struct sk_buff_head squeue; @@ -300,10 +277,14 @@ }; struct LLInterface { - void (*l3l4) (struct PStack *, int, void *); + void (*l4l3) (struct PStack *, int, void *); + int (*l4l3_proto) (struct PStack *, isdn_ctrl *); void *userdata; + u_long flag; }; +#define FLG_LLI_L1WAKEUP 1 +#define FLG_LLI_L2WAKEUP 2 struct Management { int ri; @@ -316,14 +297,14 @@ #define NO_CAUSE 254 struct Param { - u8 cause; - u8 loc; - u8 diag[6]; + u_char cause; + u_char loc; + u_char diag[6]; int bchannel; int chargeinfo; int spv; /* SPV Flag */ setup_parm setup; /* from isdnif.h numbers and Serviceindicator */ - u8 moderate; /* transfer mode and rate (bearer octet 4) */ + u_char moderate; /* transfer mode and rate (bearer octet 4) */ }; @@ -338,7 +319,7 @@ /* protocol specific data fields */ union - { u8 uuuu; /* only as dummy */ + { u_char uuuu; /* only as dummy */ #ifdef CONFIG_HISAX_EURO dss1_stk_priv dss1; /* private dss1 data */ #endif /* CONFIG_HISAX_EURO */ @@ -362,7 +343,7 @@ /* protocol specific data fields */ union - { u8 uuuu; /* only when euro not defined, avoiding empty union */ + { u_char uuuu; /* only when euro not defined, avoiding empty union */ #ifdef CONFIG_HISAX_EURO dss1_proc_priv dss1; /* private dss1 data */ #endif /* CONFIG_HISAX_EURO */ @@ -373,50 +354,58 @@ }; struct hscx_hw { - u8 tsaxr0; - u8 tsaxr1; + int hscx; + int rcvidx; + int count; /* Current skb sent count */ + u_char *rcvbuf; /* B-Channel receive Buffer */ + u_char tsaxr0; + u_char tsaxr1; }; struct w6692B_hw { int bchan; + int rcvidx; + int count; /* Current skb sent count */ + u_char *rcvbuf; /* B-Channel receive Buffer */ }; struct isar_reg { unsigned long Flags; - volatile u8 bstat; - volatile u8 iis; - volatile u8 cmsb; - volatile u8 clsb; - volatile u8 par[8]; + volatile u_char bstat; + volatile u_char iis; + volatile u_char cmsb; + volatile u_char clsb; + volatile u_char par[8]; }; struct isar_hw { int dpath; int rcvidx; + int txcnt; int mml; - u8 state; - u8 cmd; - u8 mod; - u8 newcmd; - u8 newmod; + u_char state; + u_char cmd; + u_char mod; + u_char newcmd; + u_char newmod; char try_mod; struct timer_list ftimer; - u8 *rcvbuf; /* B-Channel receive Buffer */ - u8 conmsg[16]; + u_char *rcvbuf; /* B-Channel receive Buffer */ + u_char conmsg[16]; struct isar_reg *reg; }; struct hdlc_stat_reg { #ifdef __BIG_ENDIAN - u8 fill __attribute__((packed)); - u8 mode __attribute__((packed)); - u8 xml __attribute__((packed)); - u8 cmd __attribute__((packed)); -#else - u8 cmd __attribute__((packed)); - u8 xml __attribute__((packed)); - u8 mode __attribute__((packed)); - u8 fill __attribute__((packed)); + u_char fill __attribute__((packed)); + u_char mode __attribute__((packed)); + u_char xml __attribute__((packed)); + u_char cmd __attribute__((packed)); +#else + u_char cmd __attribute__((packed)); + u_char xml __attribute__((packed)); + u_char mode __attribute__((packed)); + u_char fill __attribute__((packed)); #endif }; @@ -426,6 +415,9 @@ struct hdlc_stat_reg sr; } ctrl; u_int stat; + int rcvidx; + int count; /* Current skb sent count */ + u_char *rcvbuf; /* B-Channel receive Buffer */ }; struct hfcB_hw { @@ -436,36 +428,35 @@ struct tiger_hw { u_int *send; - dma_addr_t send_dma; + u_int *s_irq; u_int *s_end; u_int *sendp; u_int *rec; - dma_addr_t rec_dma; int free; - u8 *rcvbuf; - u8 *sendbuf; - u8 *sp; + u_char *rcvbuf; + u_char *sendbuf; + u_char *sp; int sendcnt; u_int s_tot; u_int r_bitcnt; u_int r_tot; u_int r_err; u_int r_fcs; - u8 r_state; - u8 r_one; - u8 r_val; - u8 s_state; + u_char r_state; + u_char r_one; + u_char r_val; + u_char s_state; }; struct amd7930_hw { - u8 *tx_buff; - u8 *rv_buff; + u_char *tx_buff; + u_char *rv_buff; int rv_buff_in; int rv_buff_out; struct sk_buff *rv_skb; struct hdlc_state *hdlc_state; - struct work_struct rcv_work; - struct work_struct xmt_work; + struct work_struct tq_rcv; + struct work_struct tq_xmt; }; #define BC_FLG_INIT 1 @@ -483,6 +474,8 @@ #define BC_FLG_FTI_RUN 13 #define BC_FLG_LL_OK 14 #define BC_FLG_LL_CONN 15 +#define BC_FLG_FTI_FTS 16 +#define BC_FLG_FRH_WAIT 17 #define L1_MODE_NULL 0 #define L1_MODE_TRANS 1 @@ -496,29 +489,28 @@ struct BCState { int channel; int mode; - long Flag; + u_long Flag; struct IsdnCardState *cs; - int unit; /* first or second unit (e.g. HSCX) */ - int rcvidx; - u8 *rcvbuf; /* B-Channel receive Buffer */ - int tx_cnt; /* B-Channel transmit counter */ - struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ - struct sk_buff_head rqueue; /* B-Channel receive queue */ - struct sk_buff_head squeue; /* B-Channel send queue */ - struct sk_buff_head cmpl_queue; /* B-Channel send complete queue */ + int tx_cnt; /* B-Channel transmit counter */ + struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ + struct sk_buff_head rqueue; /* B-Channel receive Queue */ + struct sk_buff_head squeue; /* B-Channel send Queue */ + int ackcnt; + spinlock_t aclock; struct PStack *st; - u8 *blog; - u8 *conmsg; + u_char *blog; + u_char *conmsg; struct timer_list transbusy; - struct work_struct work; - unsigned long event; + struct work_struct tqueue; + u_long event; + int (*BC_SetStack) (struct PStack *, struct BCState *); + void (*BC_Close) (struct BCState *); #ifdef ERROR_STATISTIC int err_crc; int err_tx; int err_rdo; int err_inv; #endif - int count; union { struct hscx_hw hscx; struct hdlc_hw hdlc; @@ -545,12 +537,12 @@ int data_open; struct l3_process *proc; setup_parm setup; /* from isdnif.h numbers and Serviceindicator */ - long Flags; /* for remembering action done in l4 */ - /* long req'd for set_bit --RR */ + u_long Flags; /* for remembering action done in l4 */ int leased; }; struct elsa_hw { + struct pci_dev *dev; unsigned long base; unsigned int cfg; unsigned int ctrl; @@ -565,17 +557,17 @@ struct timer_list tl; unsigned int MFlag; struct BCState *bcs; - u8 *transbuf; - u8 *rcvbuf; + u_char *transbuf; + u_char *rcvbuf; unsigned int transp; unsigned int rcvp; unsigned int transcnt; unsigned int rcvcnt; - u8 IER; - u8 FCR; - u8 LCR; - u8 MCR; - u8 ctrl_reg; + u_char IER; + u_char FCR; + u_char LCR; + u_char MCR; + u_char ctrl_reg; }; struct teles3_hw { @@ -588,8 +580,8 @@ struct teles0_hw { unsigned int cfg_reg; + unsigned long membase; unsigned long phymem; - void *membase; }; struct avm_hw { @@ -599,6 +591,7 @@ unsigned int isacfifo; unsigned int hscxfifo[2]; unsigned int counter; + struct pci_dev *dev; }; struct ix1_hw { @@ -617,8 +610,10 @@ unsigned int isac; unsigned long hscx_adr; unsigned int hscx; + unsigned int status; struct timer_list tl; - u8 ctrl_reg; + u_char ctrl_reg; + struct pci_dev *dev; }; struct asus_hw { @@ -637,9 +632,9 @@ unsigned char cirm; unsigned char ctmt; unsigned char cip; - u8 isac_spcr; + u_char isac_spcr; struct timer_list timer; -}; +}; struct sedl_hw { unsigned int cfg_reg; @@ -651,6 +646,7 @@ struct isar_reg isar; unsigned int chip; unsigned int bus; + struct pci_dev *dev; }; struct spt_hw { @@ -677,9 +673,7 @@ unsigned char irqmask0; unsigned char irqstat0; unsigned char last_is0; - struct pci_dev *pdev; - void (*bc_activate)(struct IsdnCardState *cs, int bc); - void (*bc_deactivate)(struct IsdnCardState *cs, int bc); + struct pci_dev *dev; }; struct hfcPCI_hw { @@ -700,10 +694,10 @@ unsigned char bswapped; unsigned char nt_mode; int nt_timer; + struct pci_dev *dev; unsigned char *pci_io; /* start of PCI IO memory */ + void *share_start; /* shared memory for Fifos start */ void *fifos; /* FIFO memory */ - dma_addr_t fifos_dma; - struct pci_dev* pdev; int last_bfifo_cnt[2]; /* marker saving last b-fifo frame count */ struct timer_list timer; }; @@ -756,12 +750,14 @@ struct isurf_hw { unsigned int reset; - void *isac; - void *isar; + unsigned long phymem; + unsigned long isac; + unsigned long isar; struct isar_reg isar_r; }; struct saphir_hw { + struct pci_dev *dev; unsigned int cfg_reg; unsigned int ale; unsigned int isac; @@ -770,6 +766,7 @@ }; struct bkm_hw { + struct pci_dev *dev; unsigned long base; /* A4T stuff */ unsigned long isac_adr; @@ -782,7 +779,9 @@ }; struct gazel_hw { + struct pci_dev *dev; unsigned int cfg_reg; + unsigned int pciaddr[2]; signed int ipac; signed int isac; signed int hscx[2]; @@ -793,6 +792,7 @@ }; struct w6692_hw { + struct pci_dev *dev; unsigned int iobase; struct timer_list timer; }; @@ -812,25 +812,25 @@ struct arcofi_msg { struct arcofi_msg *next; - u8 receive; - u8 len; - u8 msg[10]; + u_char receive; + u_char len; + u_char msg[10]; }; struct isac_chip { int ph_state; - u8 *mon_tx; - u8 *mon_rx; + u_char *mon_tx; + u_char *mon_rx; int mon_txp; int mon_txc; int mon_rxp; struct arcofi_msg *arcofi_list; struct timer_list arcofitimer; wait_queue_head_t arcofi_wait; - u8 arcofi_bc; - u8 arcofi_state; - u8 mocr; - u8 adf2; + u_char arcofi_bc; + u_char arcofi_state; + u_char mocr; + u_char adf2; }; struct hfcd_chip { @@ -850,80 +850,30 @@ }; struct amd7930_chip { - u8 lmr1; - u8 ph_state; - u8 old_state; - u8 flg_t3; + u_char lmr1; + u_char ph_state; + u_char old_state; + u_char flg_t3; unsigned int tx_xmtlen; struct timer_list timer3; - void (*ph_command) (struct IsdnCardState *, u8, char *); - void (*setIrqMask) (struct IsdnCardState *, u8); + void (*ph_command) (struct IsdnCardState *, u_char, char *); + void (*setIrqMask) (struct IsdnCardState *, u_char); }; struct icc_chip { int ph_state; - u8 *mon_tx; - u8 *mon_rx; + u_char *mon_tx; + u_char *mon_rx; int mon_txp; int mon_txc; int mon_rxp; struct arcofi_msg *arcofi_list; struct timer_list arcofitimer; wait_queue_head_t arcofi_wait; - u8 arcofi_bc; - u8 arcofi_state; - u8 mocr; - u8 adf2; -}; - -struct IsdnCardState; - -/* Methods provided by driver for a specific card */ - -struct card_ops { - void (*init) (struct IsdnCardState *); - void (*test) (struct IsdnCardState *); - int (*reset) (struct IsdnCardState *); - void (*release) (struct IsdnCardState *); - void (*aux_ind) (struct IsdnCardState *, void *); - void (*led_handler)(struct IsdnCardState *); - irqreturn_t (*irq_func) (int, void *, struct pt_regs *); -}; - -/* Card specific drivers provide methods to access the - * chips to the chip drivers */ - -struct bc_hw_ops { - u8 (*read_reg) (struct IsdnCardState *, int, u8); - void (*write_reg) (struct IsdnCardState *, int, u8, u8); - void (*read_fifo) (struct IsdnCardState *, int, u8 *, int); - void (*write_fifo) (struct IsdnCardState *, int, u8 *, int); -}; - -struct dc_hw_ops { - u8 (*read_reg) (struct IsdnCardState *, u8); - void (*write_reg) (struct IsdnCardState *, u8, u8); - void (*read_fifo) (struct IsdnCardState *, u8 *, int); - void (*write_fifo) (struct IsdnCardState *, u8 *, int); -}; - -/* Methods provided to shared B-channel FIFO handling */ - -struct bc_l1_ops { - void (*fill_fifo) (struct BCState *); - int (*open) (struct PStack *, struct BCState *); - void (*close) (struct BCState *); -}; - -/* Methods provided to shared D-channel FIFO handling */ - -struct dc_l1_ops { - void (*fill_fifo) (struct IsdnCardState *); - int (*open) (struct PStack *, struct IsdnCardState *); - void (*close) (struct IsdnCardState *); - - void (*bh_func) (void *); - void (*dbusy_func) (struct IsdnCardState *); + u_char arcofi_bc; + u_char arcofi_state; + u_char mocr; + u_char adf2; }; #define HW_IOM1 0 @@ -933,25 +883,22 @@ #define FLG_TWO_DCHAN 4 #define FLG_L1_DBUSY 5 #define FLG_DBUSY_TIMER 6 +#define FLG_LOCK_ATOMIC 7 #define FLG_ARCOFI_TIMER 8 #define FLG_ARCOFI_ERROR 9 #define FLG_HW_L1_UINT 10 -#define FLG_BUGGY_PLX9050 11 struct IsdnCardState { - unsigned char typ; - unsigned char subtyp; - spinlock_t lock; - struct card_ops *card_ops; - int protocol; - struct resources rs; - unsigned int irq; - unsigned long irq_flags; - int status; - long HW_Flags; - int *busy_flag; - int chanlimit; /* limited number of B-chans to use */ - int logecho; /* log echo if supported by card */ + spinlock_t lock; + u_char typ; + u_char subtyp; + int protocol; + u_int irq; + u_long irq_flags; + u_long HW_Flags; + int *busy_flag; + int chanlimit; /* limited number of B-chans to use */ + int logecho; /* log echo if supported by card */ union { struct elsa_hw elsa; struct teles0_hw teles0; @@ -979,25 +926,32 @@ struct w6692_hw w6692; struct hisax_d_if *hisax_d_if; } hw; - int myid; - isdn_if iif; - u8 *status_buf; - u8 *status_read; - u8 *status_write; - u8 *status_end; - struct dc_hw_ops *dc_hw_ops; - struct bc_hw_ops *bc_hw_ops; - struct dc_l1_ops *dc_l1_ops; - struct bc_l1_ops *bc_l1_ops; - int (*cardmsg) (struct IsdnCardState *, int, void *); - int (*auxcmd) (struct IsdnCardState *, isdn_ctrl *); - struct Channel channel[2+MAX_WAITING_CALLS]; - struct BCState bcs[2+MAX_WAITING_CALLS]; - struct PStack *stlist; + int myid; + isdn_if iif; + spinlock_t statlock; + u_char *status_buf; + u_char *status_read; + u_char *status_write; + u_char *status_end; + u_char (*readisac) (struct IsdnCardState *, u_char); + void (*writeisac) (struct IsdnCardState *, u_char, u_char); + void (*readisacfifo) (struct IsdnCardState *, u_char *, int); + void (*writeisacfifo) (struct IsdnCardState *, u_char *, int); + u_char (*BC_Read_Reg) (struct IsdnCardState *, int, u_char); + void (*BC_Write_Reg) (struct IsdnCardState *, int, u_char, u_char); + void (*BC_Send_Data) (struct BCState *); + int (*cardmsg) (struct IsdnCardState *, int, void *); + void (*setstack_d) (struct PStack *, struct IsdnCardState *); + void (*DC_Close) (struct IsdnCardState *); + int (*irq_func) (int, void *, struct pt_regs *); + int (*auxcmd) (struct IsdnCardState *, isdn_ctrl *); + struct Channel channel[2+MAX_WAITING_CALLS]; + struct BCState bcs[2+MAX_WAITING_CALLS]; + struct PStack *stlist; struct sk_buff_head rq, sq; /* D-channel queues */ - int cardnr; - char *dlog; - int debug; + int cardnr; + char *dlog; + int debug; union { struct isac_chip isac; struct hfcd_chip hfcd; @@ -1007,83 +961,287 @@ struct amd7930_chip amd7930; struct icc_chip icc; } dc; - u8 *rcvbuf; - int rcvidx; - struct sk_buff *tx_skb; - int tx_cnt; - long event; - struct work_struct work; + u_char *rcvbuf; + int rcvidx; + struct sk_buff *tx_skb; + int tx_cnt; + u_long event; + struct work_struct tqueue; struct timer_list dbusytimer; #ifdef ERROR_STATISTIC - int err_crc; - int err_tx; - int err_rx; + int err_crc; + int err_tx; + int err_rx; #endif }; -void -hisax_release_resources(struct IsdnCardState *cs); + +#define schedule_event(s, ev) do {test_and_set_bit(ev, &s->event);schedule_work(&s->tqueue); } while(0) #define MON0_RX 1 #define MON1_RX 2 #define MON0_TX 4 #define MON1_TX 8 -#define ISDN_CTYPE_16_0 1 -#define ISDN_CTYPE_8_0 2 -#define ISDN_CTYPE_16_3 3 -#define ISDN_CTYPE_PNP 4 -#define ISDN_CTYPE_A1 5 -#define ISDN_CTYPE_ELSA 6 -#define ISDN_CTYPE_ELSA_PNP 7 -#define ISDN_CTYPE_TELESPCMCIA 8 -#define ISDN_CTYPE_IX1MICROR2 9 -#define ISDN_CTYPE_ELSA_PCMCIA 10 -#define ISDN_CTYPE_DIEHLDIVA 11 -#define ISDN_CTYPE_ASUSCOM 12 -#define ISDN_CTYPE_TELEINT 13 -#define ISDN_CTYPE_TELES3C 14 -#define ISDN_CTYPE_SEDLBAUER 15 -#define ISDN_CTYPE_SPORTSTER 16 -#define ISDN_CTYPE_MIC 17 -#define ISDN_CTYPE_ELSA_PCI 18 -#define ISDN_CTYPE_COMPAQ_ISA 19 -#define ISDN_CTYPE_NETJET_S 20 -#define ISDN_CTYPE_TELESPCI 21 -#define ISDN_CTYPE_SEDLBAUER_PCMCIA 22 -#define ISDN_CTYPE_AMD7930 23 -#define ISDN_CTYPE_NICCY 24 -#define ISDN_CTYPE_S0BOX 25 -#define ISDN_CTYPE_A1_PCMCIA 26 -#define ISDN_CTYPE_FRITZPCI 27 -#define ISDN_CTYPE_SEDLBAUER_FAX 28 -#define ISDN_CTYPE_ISURF 29 -#define ISDN_CTYPE_ACERP10 30 -#define ISDN_CTYPE_HSTSAPHIR 31 -#define ISDN_CTYPE_BKM_A4T 32 -#define ISDN_CTYPE_SCT_QUADRO 33 -#define ISDN_CTYPE_GAZEL 34 -#define ISDN_CTYPE_HFC_PCI 35 -#define ISDN_CTYPE_W6692 36 -#define ISDN_CTYPE_HFC_SX 37 -#define ISDN_CTYPE_NETJET_U 38 -#define ISDN_CTYPE_HFC_SP_PCMCIA 39 -#define ISDN_CTYPE_DYNAMIC 40 -#define ISDN_CTYPE_ENTERNOW 41 -#define ISDN_CTYPE_COUNT 41 +#ifdef ISDN_CHIP_ISAC +#undef ISDN_CHIP_ISAC +#endif + +#ifdef CONFIG_HISAX_16_0 +#define CARD_TELES0 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_TELES0 0 +#endif + +#ifdef CONFIG_HISAX_16_3 +#define CARD_TELES3 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_TELES3 0 +#endif + +#ifdef CONFIG_HISAX_TELESPCI +#define CARD_TELESPCI 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_TELESPCI 0 +#endif + +#ifdef CONFIG_HISAX_AVM_A1 +#define CARD_AVM_A1 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_AVM_A1 0 +#endif + +#ifdef CONFIG_HISAX_AVM_A1_PCMCIA +#define CARD_AVM_A1_PCMCIA 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_AVM_A1_PCMCIA 0 +#endif + +#ifdef CONFIG_HISAX_FRITZPCI +#define CARD_FRITZPCI 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_FRITZPCI 0 +#endif + +#ifdef CONFIG_HISAX_ELSA +#define CARD_ELSA 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_ELSA 0 +#endif + +#ifdef CONFIG_HISAX_IX1MICROR2 +#define CARD_IX1MICROR2 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_IX1MICROR2 0 +#endif + +#ifdef CONFIG_HISAX_DIEHLDIVA +#define CARD_DIEHLDIVA 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_DIEHLDIVA 0 +#endif + +#ifdef CONFIG_HISAX_ASUSCOM +#define CARD_ASUSCOM 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_ASUSCOM 0 +#endif + +#ifdef CONFIG_HISAX_TELEINT +#define CARD_TELEINT 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_TELEINT 0 +#endif + +#ifdef CONFIG_HISAX_SEDLBAUER +#define CARD_SEDLBAUER 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_SEDLBAUER 0 +#endif + +#ifdef CONFIG_HISAX_SPORTSTER +#define CARD_SPORTSTER 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_SPORTSTER 0 +#endif + +#ifdef CONFIG_HISAX_MIC +#define CARD_MIC 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_MIC 0 +#endif + +#ifdef CONFIG_HISAX_NETJET +#define CARD_NETJET_S 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_NETJET_S 0 +#endif + +#ifdef CONFIG_HISAX_HFCS +#define CARD_HFCS 1 +#else +#define CARD_HFCS 0 +#endif + +#ifdef CONFIG_HISAX_HFC_PCI +#define CARD_HFC_PCI 1 +#else +#define CARD_HFC_PCI 0 +#endif + +#ifdef CONFIG_HISAX_HFC_SX +#define CARD_HFC_SX 1 +#else +#define CARD_HFC_SX 0 +#endif + +#ifdef CONFIG_HISAX_AMD7930 +#define CARD_AMD7930 1 +#else +#define CARD_AMD7930 0 +#endif + +#ifdef CONFIG_HISAX_NICCY +#define CARD_NICCY 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_NICCY 0 +#endif + +#ifdef CONFIG_HISAX_ISURF +#define CARD_ISURF 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_ISURF 0 +#endif + +#ifdef CONFIG_HISAX_S0BOX +#define CARD_S0BOX 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_S0BOX 0 +#endif + +#ifdef CONFIG_HISAX_HSTSAPHIR +#define CARD_HSTSAPHIR 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_HSTSAPHIR 0 +#endif #ifdef CONFIG_HISAX_TESTEMU +#define CARD_TESTEMU 1 #define ISDN_CTYPE_TESTEMU 99 #undef ISDN_CTYPE_COUNT #define ISDN_CTYPE_COUNT ISDN_CTYPE_TESTEMU +#else +#define CARD_TESTEMU 0 +#endif + +#ifdef CONFIG_HISAX_BKM_A4T +#define CARD_BKM_A4T 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_BKM_A4T 0 +#endif + +#ifdef CONFIG_HISAX_SCT_QUADRO +#define CARD_SCT_QUADRO 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_SCT_QUADRO 0 +#endif + +#ifdef CONFIG_HISAX_GAZEL +#define CARD_GAZEL 1 +#ifndef ISDN_CHIP_ISAC +#define ISDN_CHIP_ISAC 1 +#endif +#else +#define CARD_GAZEL 0 +#endif + +#ifdef CONFIG_HISAX_W6692 +#define CARD_W6692 1 +#ifndef ISDN_CHIP_W6692 +#define ISDN_CHIP_W6692 1 +#endif +#else +#define CARD_W6692 0 #endif #ifdef CONFIG_HISAX_NETJET_U +#define CARD_NETJET_U 1 +#ifndef ISDN_CHIP_ICC +#define ISDN_CHIP_ICC 1 +#endif #ifndef HISAX_UINTERFACE #define HISAX_UINTERFACE 1 #endif #else +#define CARD_NETJET_U 0 +#endif + +#ifdef CONFIG_HISAX_ENTERNOW_PCI +#define CARD_FN_ENTERNOW_PCI 1 #endif #define TEI_PER_CARD 1 @@ -1108,12 +1266,7 @@ extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir); #endif -struct IsdnCard { - int typ; - int protocol; /* EDSS1, 1TR6 or NI1 */ - unsigned long para[4]; - struct IsdnCardState *cs; -}; +#include "hisax_cfg.h" void init_bcstate(struct IsdnCardState *cs, int bc); @@ -1131,13 +1284,14 @@ void releasestack_isdnl2(struct PStack *st); void setstack_transl2(struct PStack *st); void releasestack_transl2(struct PStack *st); +void lli_writewakeup(struct PStack *st, int len); void setstack_l3dc(struct PStack *st, struct Channel *chanp); void setstack_l3bc(struct PStack *st, struct Channel *chanp); void releasestack_isdnl3(struct PStack *st); -u8 *findie(u8 * p, int size, u8 ie, int wanted_set); -int getcallref(u8 * p); +u_char *findie(u_char * p, int size, u_char ie, int wanted_set); +int getcallref(u_char * p); int newcallref(void); int FsmNew(struct Fsm *fsm, struct FsmNode *fnlist, int fncount); @@ -1155,12 +1309,15 @@ int HiSax_command(isdn_ctrl * ic); int HiSax_writebuf_skb(int id, int chan, int ack, struct sk_buff *skb); void HiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, ...); -void VHiSax_putstatus(struct IsdnCardState *cs, char *head, const char *fmt, va_list args); +void VHiSax_putstatus(struct IsdnCardState *cs, char *head, char *fmt, va_list args); void HiSax_reportcard(int cardnr, int sel); -int QuickHex(char *txt, u8 * p, int cnt); -void LogFrame(struct IsdnCardState *cs, u8 * p, int size); +int QuickHex(char *txt, u_char * p, int cnt); +void LogFrame(struct IsdnCardState *cs, u_char * p, int size); void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir); -void iecpy(u8 * dest, u8 * iestart, int ieoffset); +void iecpy(u_char * dest, u_char * iestart, int ieoffset); +#ifdef ISDN_CHIP_ISAC +void setstack_isac(struct PStack *st, struct IsdnCardState *cs); +#endif /* ISDN_CHIP_ISAC */ #endif /* __KERNEL__ */ #define HZDELAY(jiffs) {int tout = jiffs; while (tout--) udelay(1000000/HZ);} @@ -1182,43 +1339,3 @@ char *HiSax_getrev(const char *revision); int TeiNew(void); void TeiFree(void); -int certification_check(int output); - -static inline void -L2L1(struct PStack *st, int pr, void *arg) -{ - st->l1.l2l1(st, pr, arg); -} - -static inline void -L1L2(struct PStack *st, int pr, void *arg) -{ - st->l2.l1l2(st, pr, arg); -} - -static inline void -L3L2(struct PStack *st, int pr, void *arg) -{ - st->l2.l3l2(st, pr, arg); -} - -static inline void -L2L3(struct PStack *st, int pr, void *arg) -{ - st->l3.l2l3(st, pr, arg); -} - -static inline void -L3L4(struct PStack *st, int pr, void *arg) -{ - st->lli.l3l4(st, pr, arg); -} - -static inline void -L4L3(struct PStack *st, int pr, void *arg) -{ - st->l3.l4l3(st, pr, arg); -} - - -#endif diff -Nru a/drivers/isdn/hisax/hisax_cfg.h b/drivers/isdn/hisax/hisax_cfg.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/isdn/hisax/hisax_cfg.h Thu Feb 19 23:44:29 2004 @@ -0,0 +1,64 @@ +/* $Id: hisax_cfg.h,v 1.1.2.1 2004/01/24 20:47:23 keil Exp $ + * define of the basic HiSax configuration structures + * and pcmcia interface + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + */ + +#define ISDN_CTYPE_16_0 1 +#define ISDN_CTYPE_8_0 2 +#define ISDN_CTYPE_16_3 3 +#define ISDN_CTYPE_PNP 4 +#define ISDN_CTYPE_A1 5 +#define ISDN_CTYPE_ELSA 6 +#define ISDN_CTYPE_ELSA_PNP 7 +#define ISDN_CTYPE_TELESPCMCIA 8 +#define ISDN_CTYPE_IX1MICROR2 9 +#define ISDN_CTYPE_ELSA_PCMCIA 10 +#define ISDN_CTYPE_DIEHLDIVA 11 +#define ISDN_CTYPE_ASUSCOM 12 +#define ISDN_CTYPE_TELEINT 13 +#define ISDN_CTYPE_TELES3C 14 +#define ISDN_CTYPE_SEDLBAUER 15 +#define ISDN_CTYPE_SPORTSTER 16 +#define ISDN_CTYPE_MIC 17 +#define ISDN_CTYPE_ELSA_PCI 18 +#define ISDN_CTYPE_COMPAQ_ISA 19 +#define ISDN_CTYPE_NETJET_S 20 +#define ISDN_CTYPE_TELESPCI 21 +#define ISDN_CTYPE_SEDLBAUER_PCMCIA 22 +#define ISDN_CTYPE_AMD7930 23 +#define ISDN_CTYPE_NICCY 24 +#define ISDN_CTYPE_S0BOX 25 +#define ISDN_CTYPE_A1_PCMCIA 26 +#define ISDN_CTYPE_FRITZPCI 27 +#define ISDN_CTYPE_SEDLBAUER_FAX 28 +#define ISDN_CTYPE_ISURF 29 +#define ISDN_CTYPE_ACERP10 30 +#define ISDN_CTYPE_HSTSAPHIR 31 +#define ISDN_CTYPE_BKM_A4T 32 +#define ISDN_CTYPE_SCT_QUADRO 33 +#define ISDN_CTYPE_GAZEL 34 +#define ISDN_CTYPE_HFC_PCI 35 +#define ISDN_CTYPE_W6692 36 +#define ISDN_CTYPE_HFC_SX 37 +#define ISDN_CTYPE_NETJET_U 38 +#define ISDN_CTYPE_HFC_SP_PCMCIA 39 +#define ISDN_CTYPE_DYNAMIC 40 +#define ISDN_CTYPE_ENTERNOW 41 +#define ISDN_CTYPE_COUNT 41 + +typedef struct IsdnCardState IsdnCardState_t; +typedef struct IsdnCard IsdnCard_t; + +struct IsdnCard { + int typ; + int protocol; /* EDSS1, 1TR6 or NI1 */ + unsigned long para[4]; + IsdnCardState_t *cs; +}; + +extern void HiSax_closecard(int); +extern int hisax_init_pcmcia(void *, int *, IsdnCard_t *); diff -Nru a/drivers/isdn/hisax/hisax_debug.h b/drivers/isdn/hisax/hisax_debug.h --- a/drivers/isdn/hisax/hisax_debug.h Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hisax/hisax_debug.h Thu Feb 19 23:44:24 2004 @@ -39,7 +39,7 @@ static void __attribute__((unused)) -dump_packet(const char *name,const u8 *data,int pkt_len) +dump_packet(const char *name,const u_char *data,int pkt_len) { #define DUMP_HDR_SIZE 20 #define DUMP_TLR_SIZE 8 diff -Nru a/drivers/isdn/hisax/hisax_fcclassic.c b/drivers/isdn/hisax/hisax_fcclassic.c --- a/drivers/isdn/hisax/hisax_fcclassic.c Thu Feb 19 23:44:23 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,385 +0,0 @@ -/* - * Driver for AVM Fritz!classic (ISA) ISDN card - * - * Author Kai Germaschewski - * Copyright 2001 by Kai Germaschewski - * 2001 by Karsten Keil - * - * based upon Karsten Keil's original avm_a1.c driver - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hisax_fcclassic.h" - -// debugging cruft -#define __debug_variable debug -#include "hisax_debug.h" - -#ifdef CONFIG_HISAX_DEBUG -static int debug = 0; -MODULE_PARM(debug, "i"); -#endif - -MODULE_AUTHOR("Kai Germaschewski /Karsten Keil "); -MODULE_DESCRIPTION("AVM Fritz!Card classic ISDN driver"); - -static int protocol = 2; /* EURO-ISDN Default */ -MODULE_PARM(protocol, "i"); - -// ---------------------------------------------------------------------- - -#define AVM_A1_STAT_ISAC 0x01 -#define AVM_A1_STAT_HSCX 0x02 -#define AVM_A1_STAT_TIMER 0x04 - -// ---------------------------------------------------------------------- - -static unsigned char -fcclassic_read_isac(struct isac *isac, unsigned char offset) -{ - struct fritz_adapter *adapter = isac->priv; - unsigned char val; - - val = inb(adapter->isac_base + offset); - DBG(0x1000, " port %#x, value %#x", - offset, val); - return val; -} - -static void -fcclassic_write_isac(struct isac *isac, unsigned char offset, - unsigned char value) -{ - struct fritz_adapter *adapter = isac->priv; - - DBG(0x1000, " port %#x, value %#x", - offset, value); - outb(value, adapter->isac_base + offset); -} - -static void -fcclassic_read_isac_fifo(struct isac *isac, unsigned char * data, int size) -{ - struct fritz_adapter *adapter = isac->priv; - - insb(adapter->isac_fifo, data, size); -} - -static void -fcclassic_write_isac_fifo(struct isac *isac, unsigned char * data, int size) -{ - struct fritz_adapter *adapter = isac->priv; - - outsb(adapter->isac_fifo, data, size); -} - -static u8 -fcclassic_read_hscx(struct hscx *hscx, u8 offset) -{ - struct fritz_adapter *adapter = hscx->priv; - - return inb(adapter->hscx_base[hscx->channel] + offset); -} - -static void -fcclassic_write_hscx(struct hscx *hscx, u8 offset, u8 value) -{ - struct fritz_adapter *adapter = hscx->priv; - - outb(value, adapter->hscx_base[hscx->channel] + offset); -} - -static void -fcclassic_read_hscx_fifo(struct hscx *hscx, unsigned char * data, int size) -{ - struct fritz_adapter *adapter = hscx->priv; - - insb(adapter->hscx_fifo[hscx->channel], data, size); -} - -static void -fcclassic_write_hscx_fifo(struct hscx *hscx, unsigned char * data, int size) -{ - struct fritz_adapter *adapter = hscx->priv; - - outsb(adapter->hscx_fifo[hscx->channel], data, size); -} - -// ---------------------------------------------------------------------- - -static irqreturn_t -fcclassic_irq(int intno, void *dev, struct pt_regs *regs) -{ - struct fritz_adapter *adapter = dev; - unsigned char sval; - - DBG(2, ""); - while ((sval = inb(adapter->cfg_reg) & 0xf) != 0x7) { - DBG(2, "sval %#x", sval); - if (!(sval & AVM_A1_STAT_TIMER)) { - outb(0x1e, adapter->cfg_reg); - } - if (!(sval & AVM_A1_STAT_HSCX)) { - hscx_irq(adapter->hscx); - } - if (!(sval & AVM_A1_STAT_ISAC)) { - isac_irq(&adapter->isac); - } - } - return IRQ_HANDLED; -} - -// ---------------------------------------------------------------------- - -static int __init -fcclassic_setup(struct fritz_adapter *adapter) -{ - u32 val = 0; - int i; - int retval; - - DBG(1,""); - - isac_init(&adapter->isac); // FIXME is this okay now - - adapter->cfg_reg = adapter->io + 0x1800; - adapter->isac_base = adapter->io + 0x1400 - 0x20; - adapter->isac_fifo = adapter->io + 0x1000; - adapter->hscx_base[0] = adapter->io + 0x0400 - 0x20; - adapter->hscx_fifo[0] = adapter->io; - adapter->hscx_base[1] = adapter->io + 0x0c00 - 0x20; - adapter->hscx_fifo[1] = adapter->io + 0x0800; - - retval = -EBUSY; - if (!request_region(adapter->cfg_reg , 8, - "fcclassic cfg")) - goto err; - if (!request_region(adapter->isac_base + 0x20 , 32, - "fcclassic isac")) - goto err_cfg_reg; - if (!request_region(adapter->isac_fifo , 1, - "fcclassic isac fifo")) - goto err_isac_base; - if (!request_region(adapter->hscx_base[0] + 0x20, 32, - "fcclassic hscx")) - goto err_isac_fifo; - if (!request_region(adapter->hscx_fifo[0] , 1, - "fcclassic hscx fifo")) - goto err_hscx_base_0; - if (!request_region(adapter->hscx_base[1] + 0x20, 32, - "fcclassic hscx")) - goto err_hscx_fifo_0; - if (!request_region(adapter->hscx_fifo[1] , 1, - "fcclassic hscx fifo")) - goto err_hscx_base_1; - retval = request_irq(adapter->irq, fcclassic_irq, 0, - "fcclassic", adapter); - if (retval) - goto err_hscx_fifo_1; - - // Reset - outb(0x00, adapter->cfg_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(200 * HZ / 1000); // 200 msec - outb(0x01, adapter->cfg_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(200 * HZ / 1000); // 200 msec - outb(0x00, adapter->cfg_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(200 * HZ / 1000); // 200 msec - - val = adapter->irq; - if (val == 9) - val = 2; - outb(val, adapter->cfg_reg + 1); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(200 * HZ / 1000); // 200 msec - outb(0x00, adapter->cfg_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(200 * HZ / 1000); // 200 msec - - val = inb(adapter->cfg_reg); - printk(KERN_INFO "AVM A1: Byte at %x is %x\n", - adapter->cfg_reg, val); - val = inb(adapter->cfg_reg + 3); - printk(KERN_INFO "AVM A1: Byte at %x is %x\n", - adapter->cfg_reg + 3, val); - val = inb(adapter->cfg_reg + 2); - printk(KERN_INFO "AVM A1: Byte at %x is %x\n", - adapter->cfg_reg + 2, val); - val = inb(adapter->cfg_reg); - printk(KERN_INFO "AVM A1: Byte at %x is %x\n", - adapter->cfg_reg, val); - - outb(0x16, adapter->cfg_reg); - outb(0x1e, adapter->cfg_reg); - - adapter->isac.priv = adapter; - adapter->isac.read_isac = &fcclassic_read_isac; - adapter->isac.write_isac = &fcclassic_write_isac; - adapter->isac.read_isac_fifo = &fcclassic_read_isac_fifo; - adapter->isac.write_isac_fifo = &fcclassic_write_isac_fifo; - hisax_isac_setup(&adapter->isac); - for (i = 0; i < 2; i++) { - hscx_init(&adapter->hscx[i]); - adapter->hscx[i].priv = adapter; - adapter->hscx[i].read_hscx = &fcclassic_read_hscx; - adapter->hscx[i].write_hscx = &fcclassic_write_hscx; - adapter->hscx[i].read_hscx_fifo = &fcclassic_read_hscx_fifo; - adapter->hscx[i].write_hscx_fifo = &fcclassic_write_hscx_fifo; - hscx_setup(&adapter->hscx[i]); - } - - return 0; - - err_hscx_fifo_1: - release_region(adapter->hscx_fifo[1] , 1); - err_hscx_base_1: - release_region(adapter->hscx_base[1] + 0x20, 32); - err_hscx_fifo_0: - release_region(adapter->hscx_fifo[0] , 1); - err_hscx_base_0: - release_region(adapter->hscx_base[0] + 0x20, 32); - err_isac_fifo: - release_region(adapter->isac_fifo , 1); - err_isac_base: - release_region(adapter->isac_base + 0x20, 32); - err_cfg_reg: - release_region(adapter->cfg_reg , 8); - err: - return retval; -} - -static void __exit fcclassic_release(struct fritz_adapter *adapter) -{ - DBG(1,""); - -// outb(0, adapter->io + AVM_STATUS0); - free_irq(adapter->irq, adapter); - release_region(adapter->hscx_fifo[1] , 1); - release_region(adapter->hscx_base[1] + 0x20, 32); - release_region(adapter->hscx_fifo[0] , 1); - release_region(adapter->hscx_base[0] + 0x20, 32); - release_region(adapter->isac_fifo , 1); - release_region(adapter->isac_base + 0x20, 32); - release_region(adapter->cfg_reg , 8); -} - -// ---------------------------------------------------------------------- - -static struct fritz_adapter * __init -new_adapter(struct pci_dev *pdev) -{ - struct fritz_adapter *adapter; - struct hisax_b_if *b_if[2]; - int i; - - adapter = kmalloc(sizeof(struct fritz_adapter), GFP_KERNEL); - if (!adapter) - return NULL; - - memset(adapter, 0, sizeof(struct fritz_adapter)); - - adapter->isac.hisax_d_if.owner = THIS_MODULE; - adapter->isac.hisax_d_if.ifc.priv = &adapter->isac; - adapter->isac.hisax_d_if.ifc.l2l1 = isac_d_l2l1; - - for (i = 0; i < 2; i++) { - // adapter->hscx[i].adapter = adapter; - adapter->hscx[i].channel = i; - adapter->hscx[i].b_if.ifc.priv = &adapter->hscx[i]; - adapter->hscx[i].b_if.ifc.l2l1 = hscx_b_l2l1; - } - pci_set_drvdata(pdev, adapter); - - for (i = 0; i < 2; i++) - b_if[i] = &adapter->hscx[i].b_if; - - hisax_register(&adapter->isac.hisax_d_if, b_if, "fcclassic", protocol); - - return adapter; -} - -static void -delete_adapter(struct fritz_adapter *adapter) -{ - hisax_unregister(&adapter->isac.hisax_d_if); - kfree(adapter); -} - -static int __init -fcclassic_probe(struct pci_dev *pdev, const struct isapnp_device_id *ent) -{ - struct fritz_adapter *adapter; - int retval; - - retval = -ENOMEM; - adapter = new_adapter(pdev); - if (!adapter) - goto err; - - adapter->io = pdev->resource[0].start; - adapter->irq = pdev->irq_resource[0].start; - - printk(KERN_INFO "hisax_fcclassic: found Fritz!Card classic at IO %#x irq %d\n", - adapter->io, adapter->irq); - - retval = fcclassic_setup(adapter); - if (retval) - goto err_free; - - return 0; - - err_free: - delete_adapter(adapter); - err: - return retval; -} - -static int __exit -fcclassic_remove(struct pci_dev *pdev) -{ - struct fritz_adapter *adapter = pci_get_drvdata(pdev); - - fcclassic_release(adapter); - delete_adapter(adapter); - - return 0; -} - -static struct pci_dev isa_dev[4]; - -static int __init -hisax_fcclassic_init(void) -{ - printk(KERN_INFO "hisax_fcclassic: Fritz!Card classic ISDN driver v0.0.1\n"); - - isa_dev[0].resource[0].start = 0x300; - isa_dev[0].irq_resource[0].start = 7; - - fcclassic_probe(isa_dev, NULL); - - return 0; -} - -static void __exit -hisax_fcclassic_exit(void) -{ - fcclassic_remove(isa_dev); -} - -module_init(hisax_fcclassic_init); -module_exit(hisax_fcclassic_exit); diff -Nru a/drivers/isdn/hisax/hisax_fcclassic.h b/drivers/isdn/hisax/hisax_fcclassic.h --- a/drivers/isdn/hisax/hisax_fcclassic.h Thu Feb 19 23:44:26 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,18 +0,0 @@ -#include "hisax_if.h" -#include "hisax_isac.h" -#include "hisax_hscx.h" - -#include - -struct fritz_adapter { - unsigned int io; - unsigned int irq; - unsigned int cfg_reg; - unsigned int isac_base; - unsigned int isac_fifo; - unsigned int hscx_base[2]; - unsigned int hscx_fifo[2]; - struct isac isac; - - struct hscx hscx[2]; -}; diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c --- a/drivers/isdn/hisax/hisax_fcpcipnp.c Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c Thu Feb 19 23:44:27 2004 @@ -27,22 +27,26 @@ #include #include #include -#include +#include #include #include #include #include +#include + +#include + #include "hisax_fcpcipnp.h" // debugging cruft #define __debug_variable debug #include "hisax_debug.h" -// #define CONFIG_PNP_CARD 1 - #ifdef CONFIG_HISAX_DEBUG static int debug = 0; +/* static int hdlcfifosize = 32; */ MODULE_PARM(debug, "i"); +/* MODULE_PARM(hdlcfifosize, "i"); */ #endif MODULE_AUTHOR("Kai Germaschewski /Karsten Keil "); @@ -65,6 +69,17 @@ MODULE_DEVICE_TABLE(pci, fcpci_ids); +#ifdef __ISAPNP__ +static struct pnp_device_id fcpnp_ids[] __devinitdata = { + { + .id = "AVM0900", + .driver_data = (unsigned long) "Fritz!Card PnP", + }, +}; + +MODULE_DEVICE_TABLE(isapnp, fcpnp_ids); +#endif + static int protocol = 2; /* EURO-ISDN Default */ MODULE_PARM(protocol, "i"); MODULE_LICENSE("GPL"); @@ -115,12 +130,12 @@ #define HDLC_STAT_RDO 0x10 #define HDLC_STAT_CRCVFRRAB 0x0E #define HDLC_STAT_CRCVFR 0x06 -#define HDLC_STAT_RML_MASK 0x3f00 +#define HDLC_STAT_RML_MASK 0xff00 #define HDLC_CMD_XRS 0x80 #define HDLC_CMD_XME 0x01 #define HDLC_CMD_RRS 0x20 -#define HDLC_CMD_XML_MASK 0x3f00 +#define HDLC_CMD_XML_MASK 0xff00 #define AVM_HDLC_FIFO_1 0x10 #define AVM_HDLC_FIFO_2 0x18 @@ -367,8 +382,7 @@ { struct fritz_adapter *adapter = bcs->adapter; struct sk_buff *skb = bcs->tx_skb; - u_int count; - u_int fifo_size = 32; + int count; unsigned long flags; unsigned char *p; @@ -378,8 +392,8 @@ BUG(); bcs->ctrl.sr.cmd &= ~HDLC_CMD_XME; - if (bcs->tx_skb->len > fifo_size) { - count = fifo_size; + if (bcs->tx_skb->len > bcs->fifo_size) { + count = bcs->fifo_size; } else { count = bcs->tx_skb->len; if (bcs->mode != L1_MODE_TRANS) @@ -389,7 +403,7 @@ p = bcs->tx_skb->data; skb_pull(bcs->tx_skb, count); bcs->tx_cnt += count; - bcs->ctrl.sr.xml = ((count == fifo_size) ? 0 : count); + bcs->ctrl.sr.xml = ((count == bcs->fifo_size) ? 0 : count); switch (adapter->type) { case AVM_FRITZ_PCI: @@ -470,7 +484,7 @@ len = (stat & HDLC_STAT_RML_MASK) >> 8; if (len == 0) - len = 32; + len = bcs->fifo_size; hdlc_empty_fifo(bcs, len); @@ -498,6 +512,7 @@ static inline void hdlc_xdu_irq(struct fritz_bcs *bcs) { struct fritz_adapter *adapter = bcs->adapter; + /* Here we lost an TX interrupt, so * restart transmitting the whole frame. @@ -506,14 +521,17 @@ bcs->ctrl.sr.cmd |= HDLC_CMD_XRS; adapter->write_ctrl(bcs, 1); bcs->ctrl.sr.cmd &= ~HDLC_CMD_XRS; - adapter->write_ctrl(bcs, 1); if (!bcs->tx_skb) { DBG(0x10, "XDU without skb"); + adapter->write_ctrl(bcs, 1); return; } - skb_push(bcs->tx_skb, bcs->tx_cnt); - bcs->tx_cnt = 0; + /* only hdlc restarts the frame, transparent mode must continue */ + if (bcs->mode == L1_MODE_HDLC) { + skb_push(bcs->tx_skb, bcs->tx_cnt); + bcs->tx_cnt = 0; + } } static inline void hdlc_xpr_irq(struct fritz_bcs *bcs) @@ -530,7 +548,8 @@ } bcs->tx_cnt = 0; bcs->tx_skb = NULL; - B_L1L2(bcs, PH_DATA | CONFIRM, skb); + B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize); + dev_kfree_skb_irq(skb); } static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat) @@ -543,6 +562,8 @@ if (stat & HDLC_INT_XDU) { DBG(0x10, "XDU"); hdlc_xdu_irq(bcs); + hdlc_xpr_irq(bcs); + return; } if (stat & HDLC_INT_XPR) { DBG(0x10, "XPR"); @@ -573,6 +594,7 @@ if (bcs->mode == mode) return; + bcs->fifo_size = 32; bcs->ctrl.ctrl = 0; bcs->ctrl.sr.cmd = HDLC_CMD_XRS | HDLC_CMD_RRS; switch (mode) { @@ -585,10 +607,11 @@ bcs->rcvidx = 0; bcs->tx_cnt = 0; bcs->tx_skb = NULL; - if (mode == L1_MODE_TRANS) + if (mode == L1_MODE_TRANS) { bcs->ctrl.sr.mode = HDLC_MODE_TRANS; - else + } else { bcs->ctrl.sr.mode = HDLC_MODE_ITF_FLG; + } adapter->write_ctrl(bcs, 5); bcs->ctrl.sr.cmd = HDLC_CMD_XRS; adapter->write_ctrl(bcs, 1); @@ -631,7 +654,8 @@ // ---------------------------------------------------------------------- -static irqreturn_t fcpci2_irq(int intno, void *dev, struct pt_regs *regs) +static irqreturn_t +fcpci2_irq(int intno, void *dev, struct pt_regs *regs) { struct fritz_adapter *adapter = dev; unsigned char val; @@ -643,13 +667,15 @@ DBG(2, "STATUS0 %#x", val); if (val & AVM_STATUS0_IRQ_ISAC) isacsx_irq(&adapter->isac); - if (val & AVM_STATUS0_IRQ_HDLC) hdlc_irq(adapter); + if (val & AVM_STATUS0_IRQ_ISAC) + isacsx_irq(&adapter->isac); return IRQ_HANDLED; } -static irqreturn_t fcpci_irq(int intno, void *dev, struct pt_regs *regs) +static irqreturn_t +fcpci_irq(int intno, void *dev, struct pt_regs *regs) { struct fritz_adapter *adapter = dev; unsigned char sval; @@ -683,8 +709,7 @@ outb(AVM_STATUS1_ENA_IOM | adapter->irq, adapter->io + AVM_STATUS1); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(50*HZ / 1000); /* Timeout 50ms */ + mdelay(10); } // ---------------------------------------------------------------------- @@ -767,14 +792,11 @@ // Reset outb(0, adapter->io + AVM_STATUS0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(50 * HZ / 1000); // 50 msec + mdelay(10); outb(AVM_STATUS0_RESET, adapter->io + AVM_STATUS0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(50 * HZ / 1000); // 50 msec + mdelay(10); outb(0, adapter->io + AVM_STATUS0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(10 * HZ / 1000); // 10 msec + mdelay(10); switch (adapter->type) { case AVM_FRITZ_PCIV2: @@ -784,7 +806,7 @@ case AVM_FRITZ_PCI: case AVM_FRITZ_PNP: fcpci_init(adapter); - hisax_isac_setup(&adapter->isac); + isac_setup(&adapter->isac); break; } val = adapter->read_hdlc_status(adapter, 0); @@ -817,7 +839,7 @@ // ---------------------------------------------------------------------- static struct fritz_adapter * __devinit -new_adapter(struct pci_dev *pdev) +new_adapter(void) { struct fritz_adapter *adapter; struct hisax_b_if *b_if[2]; @@ -840,8 +862,6 @@ adapter->bcs[i].b_if.ifc.l2l1 = fritz_b_l2l1; } - pci_set_drvdata(pdev, adapter); - for (i = 0; i < 2; i++) b_if[i] = &adapter->bcs[i].b_if; @@ -863,10 +883,12 @@ int retval; retval = -ENOMEM; - adapter = new_adapter(pdev); + adapter = new_adapter(); if (!adapter) goto err; + pci_set_drvdata(pdev, adapter); + if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2) adapter->type = AVM_FRITZ_PCIV2; else @@ -880,7 +902,7 @@ adapter->irq = pdev->irq; printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at %s\n", - (char *) ent->driver_data, pci_name(pdev)); + (char *) ent->driver_data, pdev->slot_name); retval = fcpcipnp_setup(adapter); if (retval) @@ -894,91 +916,87 @@ return retval; } -static void __devexit fcpci_remove(struct pci_dev *pdev) -{ - struct fritz_adapter *adapter = pci_get_drvdata(pdev); - - fcpcipnp_release(adapter); - pci_disable_device(pdev); - delete_adapter(adapter); -} - -static struct pci_driver fcpci_driver = { - .name = "fcpci", - .probe = fcpci_probe, - .remove = __devexit_p(fcpci_remove), - .id_table = fcpci_ids, -}; - -#ifdef CONFIG_PNP_CARD - -static int __devinit fcpnp_probe(struct pnp_card *card, - const struct pnp_card_device_id *card_id) +#ifdef __ISAPNP__ +static int __devinit fcpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id) { struct fritz_adapter *adapter; - struct pnp_dev *pnp_dev; int retval; - retval = -ENODEV; - pnp_dev = pnp_request_card_device(card, card_id->devs[0].id, NULL); - if (!pnp_dev) - goto err; - - if (!pnp_port_valid(pnp_dev, 0) || !pnp_irq_valid(pnp_dev, 0)) - goto err; + if (!pdev) + return(-ENODEV); retval = -ENOMEM; - adapter = new_adapter((struct pci_dev *)pnp_dev); // FIXME + adapter = new_adapter(); if (!adapter) goto err; - + + pnp_set_drvdata(pdev, adapter); + adapter->type = AVM_FRITZ_PNP; - adapter->io = pnp_port_start(pnp_dev, 0); - adapter->irq = pnp_irq(pnp_dev, 0); - + + pnp_disable_dev(pdev); + retval = pnp_activate_dev(pdev); + if (retval < 0) { + printk(KERN_WARNING "%s: pnp_activate_dev(%s) ret(%d)\n", __FUNCTION__, + (char *)dev_id->driver_data, retval); + goto err_free; + } + adapter->io = pnp_port_start(pdev, 0); + adapter->irq = pnp_irq(pdev, 0); + printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at IO %#x irq %d\n", - (char *) card_id->driver_data, adapter->io, adapter->irq); - + (char *) dev_id->driver_data, adapter->io, adapter->irq); + retval = fcpcipnp_setup(adapter); if (retval) - goto err_delete; - + goto err_free; + return 0; - err_delete: + err_free: delete_adapter(adapter); err: return retval; } -static void __devexit fcpnp_remove(struct pnp_card *pcard) +static void __devexit fcpnp_remove(struct pnp_dev *pdev) { - struct fritz_adapter *adapter = pnpc_get_drvdata(pcard); + struct fritz_adapter *adapter = pnp_get_drvdata(pdev); - fcpcipnp_release(adapter); - delete_adapter(adapter); + if (adapter) { + fcpcipnp_release(adapter); + delete_adapter(adapter); + } + pnp_disable_dev(pdev); } -static struct pnp_card_device_id fcpnp_ids[] __devinitdata = { - { .id = "AVM0900", - .driver_data = (unsigned long) "Fritz!Card PnP", - .devs = { { "AVM0900" } }, - }, - {} +static struct pnp_driver fcpnp_driver = { + name: "fcpnp", + probe: fcpnp_probe, + remove: __devexit_p(fcpnp_remove), + id_table: fcpnp_ids, }; +#endif -static struct pnpc_driver fcpnp_driver = { - .name = "fcpnp", - .probe = fcpnp_probe, - .remove = __devexit_p(fcpnp_remove), - .id_table = fcpnp_ids, -}; +static void __devexit fcpci_remove(struct pci_dev *pdev) +{ + struct fritz_adapter *adapter = pci_get_drvdata(pdev); -#endif + fcpcipnp_release(adapter); + pci_disable_device(pdev); + delete_adapter(adapter); +} + +static struct pci_driver fcpci_driver = { + name: "fcpci", + probe: fcpci_probe, + remove: __devexit_p(fcpci_remove), + id_table: fcpci_ids, +}; static int __init hisax_fcpcipnp_init(void) { - int retval = 0, pci_nr_found; + int retval, pci_nr_found; printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n"); @@ -986,25 +1004,26 @@ if (retval < 0) goto out; pci_nr_found = retval; + retval = 0; -#ifdef CONFIG_PNP_CARD - retval = pnpc_register_driver(&fcpnp_driver); -#endif +#ifdef __ISAPNP__ + retval = pnp_register_driver(&fcpnp_driver); if (retval < 0) goto out_unregister_pci; +#endif #if !defined(CONFIG_HOTPLUG) || defined(MODULE) if (pci_nr_found + retval == 0) { retval = -ENODEV; - goto out_unregister_pnp; + goto out_unregister_isapnp; } #endif return 0; #if !defined(CONFIG_HOTPLUG) || defined(MODULE) - out_unregister_pnp: -#ifdef CONFIG_PNP_CARD - pnpc_unregister_driver(&fcpnp_driver); + out_unregister_isapnp: +#ifdef __ISAPNP__ + pnp_unregister_driver(&fcpnp_driver); #endif #endif out_unregister_pci: @@ -1015,8 +1034,8 @@ static void __exit hisax_fcpcipnp_exit(void) { -#ifdef CONFIG_PNP_CARD - pnpc_unregister_driver(&fcpnp_driver); +#ifdef __ISAPNP__ + pnp_unregister_driver(&fcpnp_driver); #endif pci_unregister_driver(&fcpci_driver); } diff -Nru a/drivers/isdn/hisax/hisax_fcpcipnp.h b/drivers/isdn/hisax/hisax_fcpcipnp.h --- a/drivers/isdn/hisax/hisax_fcpcipnp.h Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/hisax/hisax_fcpcipnp.h Thu Feb 19 23:44:28 2004 @@ -12,15 +12,15 @@ struct hdlc_stat_reg { #ifdef __BIG_ENDIAN - u8 fill __attribute__((packed)); - u8 mode __attribute__((packed)); - u8 xml __attribute__((packed)); - u8 cmd __attribute__((packed)); + u_char fill __attribute__((packed)); + u_char mode __attribute__((packed)); + u_char xml __attribute__((packed)); + u_char cmd __attribute__((packed)); #else - u8 cmd __attribute__((packed)); - u8 xml __attribute__((packed)); - u8 mode __attribute__((packed)); - u8 fill __attribute__((packed)); + u_char cmd __attribute__((packed)); + u_char xml __attribute__((packed)); + u_char mode __attribute__((packed)); + u_char fill __attribute__((packed)); #endif }; @@ -36,8 +36,9 @@ } ctrl; u_int stat; int rcvidx; - u8 rcvbuf[HSCX_BUFMAX]; /* B-Channel receive Buffer */ - + int fifo_size; + u_char rcvbuf[HSCX_BUFMAX]; /* B-Channel receive Buffer */ + int tx_cnt; /* B-Channel transmit counter */ struct sk_buff *tx_skb; /* B-Channel transmit Buffer */ }; diff -Nru a/drivers/isdn/hisax/hisax_hfcpci.c b/drivers/isdn/hisax/hisax_hfcpci.c --- a/drivers/isdn/hisax/hisax_hfcpci.c Thu Feb 19 23:44:24 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,1645 +0,0 @@ -/* - * Driver for HFC PCI based cards - * - * Author Kai Germaschewski - * Copyright 2002 by Kai Germaschewski - * 2000 by Karsten Keil - * 2000 by Werner Cornelius - * - * based upon Werner Cornelius's original hfc_pci.c driver - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -// XXX timer3 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hisax_hfcpci.h" - -// debugging cruft -#define __debug_variable debug -#include "hisax_debug.h" - -#ifdef CONFIG_HISAX_DEBUG -static int debug = 0; -MODULE_PARM(debug, "i"); -#endif - -MODULE_AUTHOR("Kai Germaschewski /Werner Cornelius "); -MODULE_DESCRIPTION("HFC PCI ISDN driver"); - -#define ID(ven, dev, name) \ - { .vendor = PCI_VENDOR_ID_##ven, \ - .device = PCI_DEVICE_ID_##dev, \ - .subvendor = PCI_ANY_ID, \ - .subdevice = PCI_ANY_ID, \ - .class = 0, \ - .class_mask = 0, \ - .driver_data = (unsigned long) name } - -static struct pci_device_id hfcpci_ids[] = { - ID(CCD, CCD_2BD0, "CCD/Billion/Asuscom 2BD0"), - ID(CCD, CCD_B000, "Billion B000"), - ID(CCD, CCD_B006, "Billion B006"), - ID(CCD, CCD_B007, "Billion B007"), - ID(CCD, CCD_B008, "Billion B008"), - ID(CCD, CCD_B009, "Billion B009"), - ID(CCD, CCD_B00A, "Billion B00A"), - ID(CCD, CCD_B00B, "Billion B00B"), - ID(CCD, CCD_B00C, "Billion B00C"), - ID(CCD, CCD_B100, "Seyeon"), - ID(ABOCOM, ABOCOM_2BD1, "Abocom/Magitek"), - ID(ASUSTEK, ASUSTEK_0675, "Asuscom/Askey"), - ID(BERKOM, BERKOM_T_CONCEPT, "German Telekom T-Concept"), - ID(BERKOM, BERKOM_A1T, "German Telekom A1T"), - ID(ANIGMA, ANIGMA_MC145575, "Motorola MC145575"), - ID(ZOLTRIX, ZOLTRIX_2BD0, "Zoltrix 2BD0"), - ID(DIGI, DIGI_DF_M_IOM2_E, "Digi DataFire Micro V IOM2 (Europe)"), - ID(DIGI, DIGI_DF_M_E, "Digi DataFire Micro V (Europe)"), - ID(DIGI, DIGI_DF_M_IOM2_A, "Digi DataFire Micro V IOM2 (America)"), - ID(DIGI, DIGI_DF_M_A, "Digi DataFire Micro V (America)"), - { } -}; -MODULE_DEVICE_TABLE(pci, hfcpci_ids); - -#undef ID - -static int protocol = 2; /* EURO-ISDN Default */ -MODULE_PARM(protocol, "i"); - -// ---------------------------------------------------------------------- -// - -#define DBG_WARN 0x0001 -#define DBG_INFO 0x0002 -#define DBG_IRQ 0x0010 -#define DBG_L1M 0x0020 -#define DBG_PR 0x0040 -#define DBG_D_XMIT 0x0100 -#define DBG_D_RECV 0x0200 -#define DBG_B_XMIT 0x1000 -#define DBG_B_RECV 0x2000 - -/* memory window base address offset (in config space) */ - -#define HFCPCI_MWBA 0x80 - -/* GCI/IOM bus monitor registers */ - -#define HCFPCI_C_I 0x08 -#define HFCPCI_TRxR 0x0C -#define HFCPCI_MON1_D 0x28 -#define HFCPCI_MON2_D 0x2C - - -/* GCI/IOM bus timeslot registers */ - -#define HFCPCI_B1_SSL 0x80 -#define HFCPCI_B2_SSL 0x84 -#define HFCPCI_AUX1_SSL 0x88 -#define HFCPCI_AUX2_SSL 0x8C -#define HFCPCI_B1_RSL 0x90 -#define HFCPCI_B2_RSL 0x94 -#define HFCPCI_AUX1_RSL 0x98 -#define HFCPCI_AUX2_RSL 0x9C - -/* GCI/IOM bus data registers */ - -#define HFCPCI_B1_D 0xA0 -#define HFCPCI_B2_D 0xA4 -#define HFCPCI_AUX1_D 0xA8 -#define HFCPCI_AUX2_D 0xAC - -/* GCI/IOM bus configuration registers */ - -#define HFCPCI_MST_EMOD 0xB4 -#define HFCPCI_MST_MODE 0xB8 -#define HFCPCI_CONNECT 0xBC - - -/* Interrupt and status registers */ - -#define HFCPCI_FIFO_EN 0x44 -#define HFCPCI_TRM 0x48 -#define HFCPCI_B_MODE 0x4C -#define HFCPCI_CHIP_ID 0x58 -#define HFCPCI_CIRM 0x60 -#define HFCPCI_CTMT 0x64 -#define HFCPCI_INT_M1 0x68 -#define HFCPCI_INT_M2 0x6C -#define HFCPCI_INT_S1 0x78 -#define HFCPCI_INT_S2 0x7C -#define HFCPCI_STATUS 0x70 - -/* S/T section registers */ - -#define HFCPCI_STATES 0xC0 -#define HFCPCI_SCTRL 0xC4 -#define HFCPCI_SCTRL_E 0xC8 -#define HFCPCI_SCTRL_R 0xCC -#define HFCPCI_SQ 0xD0 -#define HFCPCI_CLKDEL 0xDC -#define HFCPCI_B1_REC 0xF0 -#define HFCPCI_B1_SEND 0xF0 -#define HFCPCI_B2_REC 0xF4 -#define HFCPCI_B2_SEND 0xF4 -#define HFCPCI_D_REC 0xF8 -#define HFCPCI_D_SEND 0xF8 -#define HFCPCI_E_REC 0xFC - - -/* bits in status register (READ) */ -#define HFCPCI_PCI_PROC 0x02 -#define HFCPCI_NBUSY 0x04 -#define HFCPCI_TIMER_ELAP 0x10 -#define HFCPCI_STATINT 0x20 -#define HFCPCI_FRAMEINT 0x40 -#define HFCPCI_ANYINT 0x80 - -/* bits in CTMT (Write) */ -#define HFCPCI_CLTIMER 0x80 -#define HFCPCI_TIM3_125 0x04 -#define HFCPCI_TIM25 0x10 -#define HFCPCI_TIM50 0x14 -#define HFCPCI_TIM400 0x18 -#define HFCPCI_TIM800 0x1C -#define HFCPCI_AUTO_TIMER 0x20 -#define HFCPCI_TRANSB2 0x02 -#define HFCPCI_TRANSB1 0x01 - -/* bits in CIRM (Write) */ -#define HFCPCI_AUX_MSK 0x07 -#define HFCPCI_RESET 0x08 -#define HFCPCI_B1_REV 0x40 -#define HFCPCI_B2_REV 0x80 - -/* bits in INT_M1 and INT_S1 */ -#define HFCPCI_INTS_B1TRANS 0x01 -#define HFCPCI_INTS_B2TRANS 0x02 -#define HFCPCI_INTS_DTRANS 0x04 -#define HFCPCI_INTS_B1REC 0x08 -#define HFCPCI_INTS_B2REC 0x10 -#define HFCPCI_INTS_DREC 0x20 -#define HFCPCI_INTS_L1STATE 0x40 -#define HFCPCI_INTS_TIMER 0x80 - -/* bits in INT_M2 */ -#define HFCPCI_PROC_TRANS 0x01 -#define HFCPCI_GCI_I_CHG 0x02 -#define HFCPCI_GCI_MON_REC 0x04 -#define HFCPCI_IRQ_ENABLE 0x08 -#define HFCPCI_PMESEL 0x80 - -/* bits in STATES */ -#define HFCPCI_STATE_MSK 0x0F -#define HFCPCI_LOAD_STATE 0x10 -#define HFCPCI_ACTIVATE 0x20 -#define HFCPCI_DO_ACTION 0x40 -#define HFCPCI_NT_G2_G3 0x80 - -/* bits in HFCD_MST_MODE */ -#define HFCPCI_MASTER 0x01 -#define HFCPCI_SLAVE 0x00 -/* remaining bits are for codecs control */ - -/* bits in HFCD_SCTRL */ -#define SCTRL_B1_ENA 0x01 -#define SCTRL_B2_ENA 0x02 -#define SCTRL_MODE_TE 0x00 -#define SCTRL_MODE_NT 0x04 -#define SCTRL_LOW_PRIO 0x08 -#define SCTRL_SQ_ENA 0x10 -#define SCTRL_TEST 0x20 -#define SCTRL_NONE_CAP 0x40 -#define SCTRL_PWR_DOWN 0x80 - -/* bits in SCTRL_E */ -#define HFCPCI_AUTO_AWAKE 0x01 -#define HFCPCI_DBIT_1 0x04 -#define HFCPCI_IGNORE_COL 0x08 -#define HFCPCI_CHG_B1_B2 0x80 - -/* bits in FIFO_EN register */ -#define HFCPCI_FIFOEN_B1 0x03 -#define HFCPCI_FIFOEN_B2 0x0C -#define HFCPCI_FIFOEN_DTX 0x10 -#define HFCPCI_FIFOEN_DRX 0x20 -#define HFCPCI_FIFOEN_B1TX 0x01 -#define HFCPCI_FIFOEN_B1RX 0x02 -#define HFCPCI_FIFOEN_B2TX 0x04 -#define HFCPCI_FIFOEN_B2RX 0x08 - -/* - * thresholds for transparent B-channel mode - * change mask and threshold simultaneously - */ -#define HFCPCI_BTRANS_THRESHOLD 128 -#define HFCPCI_BTRANS_THRESMASK 0x00 - -#define CLKDEL_TE 0x0e /* CLKDEL in TE mode */ -#define CLKDEL_NT 0x6c /* CLKDEL in NT mode */ - -#define MAX_D_FRAMES 0x10 -#define MAX_B_FRAMES 0x20 -#define B_FIFO_START 0x0200 -#define B_FIFO_END 0x2000 -#define B_FIFO_SIZE (B_FIFO_END - B_FIFO_START) -#define D_FIFO_START 0x0000 -#define D_FIFO_END 0x0200 -#define D_FIFO_SIZE (D_FIFO_END - D_FIFO_START) - -// ---------------------------------------------------------------------- -// push messages to the upper layers - -static inline void D_L1L2(struct hfcpci_adapter *adapter, int pr, void *arg) -{ - struct hisax_if *ifc = (struct hisax_if *) &adapter->d_if; - - DBG(DBG_PR, "pr %#x", pr); - ifc->l1l2(ifc, pr, arg); -} - -static inline void B_L1L2(struct hfcpci_bcs *bcs, int pr, void *arg) -{ - struct hisax_if *ifc = (struct hisax_if *) &bcs->b_if; - - DBG(DBG_PR, "pr %#x", pr); - ifc->l1l2(ifc, pr, arg); -} - -// ---------------------------------------------------------------------- -// MMIO - -static inline void -hfcpci_writeb(struct hfcpci_adapter *adapter, u8 b, unsigned char offset) -{ - writeb(b, adapter->mmio + offset); -} - -static inline u8 -hfcpci_readb(struct hfcpci_adapter *adapter, unsigned char offset) -{ - return readb(adapter->mmio + offset); -} - -// ---------------------------------------------------------------------- -// magic to define the various F/Z counter accesses - -#define DECL_B_F(r, f) \ -static inline u8 \ -get_b_##r##_##f (struct hfcpci_bcs *bcs) \ -{ \ - u16 off = bcs->channel ? OFF_B2_##r##_##f : OFF_B1_##r##_##f; \ - \ - return *(bcs->adapter->fifo + off); \ -} \ - \ -static inline void \ -set_b_##r##_##f (struct hfcpci_bcs *bcs, u8 f) \ -{ \ - u16 off = bcs->channel ? OFF_B2_##r##_##f : OFF_B1_##r##_##f; \ - \ - *(bcs->adapter->fifo + off) = f; \ -} - -#define OFF_B1_rx_f1 0x6080 -#define OFF_B2_rx_f1 0x6180 -#define OFF_B1_rx_f2 0x6081 -#define OFF_B2_rx_f2 0x6181 - -#define OFF_B1_tx_f1 0x2080 -#define OFF_B2_tx_f1 0x2180 -#define OFF_B1_tx_f2 0x2081 -#define OFF_B2_tx_f2 0x2181 - -DECL_B_F(rx, f1) -DECL_B_F(rx, f2) -DECL_B_F(tx, f1) -DECL_B_F(tx, f2) - -#undef DECL_B_F - -#define DECL_B_Z(r, z) \ -static inline u16 \ -get_b_##r##_##z (struct hfcpci_bcs *bcs, u8 f) \ -{ \ - u16 off = bcs->channel ? OFF_B2_##r##_##z : OFF_B1_##r##_##z; \ - \ - return le16_to_cpu(*((u16 *) (bcs->adapter->fifo + off + f * 4))); \ -} \ - \ -static inline void \ -set_b_##r##_##z(struct hfcpci_bcs *bcs, u8 f, u16 z) \ -{ \ - u16 off = bcs->channel ? OFF_B2_##r##_##z : OFF_B1_##r##_##z; \ - \ - *((u16 *) (bcs->adapter->fifo + off + f * 4)) = cpu_to_le16(z); \ -} - -#define OFF_B1_rx_z1 0x6000 -#define OFF_B2_rx_z1 0x6100 -#define OFF_B1_rx_z2 0x6002 -#define OFF_B2_rx_z2 0x6102 - -#define OFF_B1_tx_z1 0x2000 -#define OFF_B2_tx_z1 0x2100 -#define OFF_B1_tx_z2 0x2002 -#define OFF_B2_tx_z2 0x2102 - -DECL_B_Z(rx, z1) -DECL_B_Z(rx, z2) -DECL_B_Z(tx, z1) -DECL_B_Z(tx, z2) - -#undef DECL_B_Z - -#define DECL_D_F(r, f) \ -static inline u8 \ -get_d_##r##_##f (struct hfcpci_adapter *adapter) \ -{ \ - u16 off = OFF_D_##r##_##f; \ - \ - return *(adapter->fifo + off) & 0xf; \ -} \ - \ -static inline void \ -set_d_##r##_##f (struct hfcpci_adapter *adapter, u8 f) \ -{ \ - u16 off = OFF_D_##r##_##f; \ - \ - *(adapter->fifo + off) = f | 0x10; \ -} - -#define OFF_D_rx_f1 0x60a0 -#define OFF_D_rx_f2 0x60a1 - -#define OFF_D_tx_f1 0x20a0 -#define OFF_D_tx_f2 0x20a1 - -DECL_D_F(rx, f1) -DECL_D_F(rx, f2) -DECL_D_F(tx, f1) -DECL_D_F(tx, f2) - -#undef DECL_D_F - -#define DECL_D_Z(r, z) \ -static inline u16 \ -get_d_##r##_##z (struct hfcpci_adapter *adapter, u8 f) \ -{ \ - u16 off = OFF_D_##r##_##z; \ - \ - return le16_to_cpu(*((u16 *) (adapter->fifo + off + (f | 0x10) * 4)));\ -} \ - \ -static inline void \ -set_d_##r##_##z(struct hfcpci_adapter *adapter, u8 f, u16 z) \ -{ \ - u16 off = OFF_D_##r##_##z; \ - \ - *((u16 *) (adapter->fifo + off + (f | 0x10) * 4)) = cpu_to_le16(z); \ -} - -#define OFF_D_rx_z1 0x6080 -#define OFF_D_rx_z2 0x6082 - -#define OFF_D_tx_z1 0x2080 -#define OFF_D_tx_z2 0x2082 - -DECL_D_Z(rx, z1) -DECL_D_Z(rx, z2) -DECL_D_Z(tx, z1) -DECL_D_Z(tx, z2) - -#undef DECL_B_Z - -// ---------------------------------------------------------------------- -// fill b / d fifos - -static inline void -hfcpci_fill_d_fifo(struct hfcpci_adapter *adapter) -{ - u8 f1, f2; - u16 z1, z2; - int cnt, fcnt; - char *fifo_adr = adapter->fifo; - struct sk_buff *tx_skb = adapter->tx_skb; - - f1 = get_d_tx_f1(adapter); - f2 = get_d_tx_f2(adapter); - DBG(DBG_D_XMIT, "f1 %#x f2 %#x", f1, f2); - - fcnt = f1 - f2; - if (fcnt < 0) - fcnt += MAX_D_FRAMES; - - if (fcnt) { - printk("BUG\n"); - return; - } - - z1 = get_d_tx_z1(adapter, f1); - z2 = get_d_tx_z2(adapter, f1); //XXX - DBG(DBG_D_XMIT, "z1 %#x z2 %#x", z1, z2); - - cnt = z2 - z1; - if (cnt <= 0) - cnt += D_FIFO_SIZE; - - if (tx_skb->len > cnt) { - printk("BUG\n"); - return; - } - - cnt = tx_skb->len; - if (z1 + cnt <= D_FIFO_END) { - memcpy(fifo_adr + z1, tx_skb->data, cnt); - } else { - memcpy(fifo_adr + z1, tx_skb->data, D_FIFO_END - z1); - memcpy(fifo_adr + D_FIFO_START, - tx_skb->data + (D_FIFO_END - z1), - cnt - (D_FIFO_END - z1)); - } - z1 += cnt; - if (z1 >= D_FIFO_END) - z1 -= D_FIFO_SIZE; - - f1 = (f1 + 1) & (MAX_D_FRAMES - 1); - mb(); - set_d_tx_z1(adapter, f1, z1); - mb(); - set_d_tx_f1(adapter, f1); -} - -static inline void -hfcpci_fill_b_fifo_hdlc(struct hfcpci_bcs *bcs) -{ - u8 f1, f2; - u16 z1, z2; - int cnt, fcnt; - char *fifo_adr = bcs->adapter->fifo + (bcs->channel ? 0x2000 : 0x0000); - struct sk_buff *tx_skb = bcs->tx_skb; - - f1 = get_b_tx_f1(bcs); - f2 = get_b_tx_f2(bcs); - DBG(DBG_B_XMIT, "f1 %#x f2 %#x", f1, f2); - - fcnt = f1 - f2; - if (fcnt < 0) - fcnt += MAX_B_FRAMES; - - if (fcnt) { - printk("BUG\n"); - return; - } - - z1 = get_b_tx_z1(bcs, f1); - z2 = get_b_tx_z2(bcs, f1); //XXX - DBG(DBG_B_XMIT, "z1 %#x z2 %#x", z1, z2); - - cnt = z2 - z1; - if (cnt <= 0) - cnt += B_FIFO_SIZE; - - if (tx_skb->len > cnt) { - printk("BUG\n"); - return; - } - - cnt = tx_skb->len; - if (z1 + cnt <= B_FIFO_END) { - memcpy(fifo_adr + z1, tx_skb->data, cnt); - } else { - memcpy(fifo_adr + z1, tx_skb->data, B_FIFO_END - z1); - memcpy(fifo_adr + B_FIFO_START, - tx_skb->data + (B_FIFO_END - z1), - cnt - (B_FIFO_END - z1)); - } - z1 += cnt; - if (z1 >= B_FIFO_END) - z1 -= B_FIFO_SIZE; - - f1 = (f1 + 1) & (MAX_B_FRAMES - 1); - mb(); - set_b_tx_z1(bcs, f1, z1); - mb(); - set_b_tx_f1(bcs, f1); -} - -static inline void -hfcpci_fill_b_fifo_trans(struct hfcpci_bcs *bcs) -{ - int cnt; - char *fifo_adr = bcs->adapter->fifo + (bcs->channel ? 0x2000 : 0x0000); - struct sk_buff *tx_skb = bcs->tx_skb; - u8 f1, f2; - u16 z1, z2; - - f1 = get_b_tx_f1(bcs); - f2 = get_b_tx_f2(bcs); - - if (f1 != f2) - BUG(); - - z1 = get_b_tx_z1(bcs, f1); - z2 = get_b_tx_z2(bcs, f1); - - cnt = z2 - z1; - if (cnt <= 0) - cnt += B_FIFO_SIZE; - - if (tx_skb->len > cnt) - BUG(); - - if (z1 + cnt <= B_FIFO_END) { - memcpy(fifo_adr + z1, tx_skb->data, cnt); - } else { - memcpy(fifo_adr + z1, tx_skb->data, B_FIFO_END - z1); - memcpy(fifo_adr + B_FIFO_START, - tx_skb->data + (B_FIFO_END - z1), - cnt - (B_FIFO_END - z1)); - } - z1 += cnt; - if (z1 >= B_FIFO_END) - z1 -= B_FIFO_SIZE; - - mb(); - set_b_tx_z1(bcs, f1, z1); -} - -static inline void -hfcpci_fill_b_fifo(struct hfcpci_bcs *bcs) -{ - if (!bcs->tx_skb) { - DBG(DBG_WARN, "?"); - return; - } - - switch (bcs->mode) { - case L1_MODE_TRANS: - hfcpci_fill_b_fifo_trans(bcs); - break; - case L1_MODE_HDLC: - hfcpci_fill_b_fifo_hdlc(bcs); - break; - default: - DBG(DBG_WARN, "?"); - } -} - -static void hfcpci_clear_b_rx_fifo(struct hfcpci_bcs *bcs); -static void hfcpci_clear_b_tx_fifo(struct hfcpci_bcs *bcs); - -static void -hfcpci_b_mode(struct hfcpci_bcs *bcs, int mode) -{ - struct hfcpci_adapter *adapter = bcs->adapter; - - DBG(DBG_B_XMIT, "B%d mode %d --> %d", - bcs->channel + 1, bcs->mode, mode); - - if (bcs->mode == mode) - return; - - switch (mode) { - case L1_MODE_NULL: - if (bcs->channel == 0) { - adapter->sctrl &= ~SCTRL_B1_ENA; - adapter->sctrl_r &= ~SCTRL_B1_ENA; - adapter->fifo_en &= ~HFCPCI_FIFOEN_B1; - adapter->int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); - } else { - adapter->sctrl &= ~SCTRL_B2_ENA; - adapter->sctrl_r &= ~SCTRL_B2_ENA; - adapter->fifo_en &= ~HFCPCI_FIFOEN_B2; - adapter->int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); - } - break; - case L1_MODE_TRANS: - case L1_MODE_HDLC: - hfcpci_clear_b_rx_fifo(bcs); - hfcpci_clear_b_tx_fifo(bcs); - if (bcs->channel == 0) { - adapter->sctrl |= SCTRL_B1_ENA; - adapter->sctrl_r |= SCTRL_B1_ENA; - adapter->fifo_en |= HFCPCI_FIFOEN_B1; - adapter->int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC); - - if (mode == L1_MODE_TRANS) - adapter->ctmt |= 1; - else - adapter->ctmt &= ~1; - - } else { - adapter->sctrl |= SCTRL_B2_ENA; - adapter->sctrl_r |= SCTRL_B2_ENA; - adapter->fifo_en |= HFCPCI_FIFOEN_B2; - adapter->int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC); - - if (mode == L1_MODE_TRANS) - adapter->ctmt |= 2; - else - adapter->ctmt &= ~2; - - } - break; - } - hfcpci_writeb(adapter, adapter->int_m1, HFCPCI_INT_M1); - hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); - hfcpci_writeb(adapter, adapter->sctrl, HFCPCI_SCTRL); - hfcpci_writeb(adapter, adapter->sctrl_r, HFCPCI_SCTRL_R); - hfcpci_writeb(adapter, adapter->ctmt, HFCPCI_CTMT); - hfcpci_writeb(adapter, adapter->conn, HFCPCI_CONNECT); - - bcs->mode = mode; -} - -// ---------------------------------------------------------------------- -// Layer 1 state machine - -static struct Fsm l1fsm; - -enum { - ST_L1_F0, - ST_L1_F2, - ST_L1_F3, - ST_L1_F4, - ST_L1_F5, - ST_L1_F6, - ST_L1_F7, - ST_L1_F8, -}; - -#define L1_STATE_COUNT (ST_L1_F8+1) - -static char *strL1State[] = -{ - "ST_L1_F0", - "ST_L1_F2", - "ST_L1_F3", - "ST_L1_F4", - "ST_L1_F5", - "ST_L1_F6", - "ST_L1_F7", - "ST_L1_F8", -}; - -enum { - EV_PH_F0, - EV_PH_1, - EV_PH_F2, - EV_PH_F3, - EV_PH_F4, - EV_PH_F5, - EV_PH_F6, - EV_PH_F7, - EV_PH_F8, - EV_PH_ACTIVATE_REQ, - EV_PH_DEACTIVATE_REQ, - EV_TIMER3, -}; - -#define L1_EVENT_COUNT (EV_TIMER3 + 1) - -static char *strL1Event[] = -{ - "EV_PH_F0", - "EV_PH_1", - "EV_PH_F2", - "EV_PH_F3", - "EV_PH_F4", - "EV_PH_F5", - "EV_PH_F6", - "EV_PH_F7", - "EV_PH_F8", - "EV_PH_ACTIVATE_REQ", - "EV_PH_DEACTIVATE_REQ", - "EV_TIMER3", -}; - -static void l1_ignore(struct FsmInst *fi, int event, void *arg) -{ -} - -static void l1_go_f3(struct FsmInst *fi, int event, void *arg) -{ - FsmChangeState(fi, ST_L1_F3); -} - -static void l1_go_f3_deact_ind(struct FsmInst *fi, int event, void *arg) -{ - struct hfcpci_adapter *adapter = fi->userdata; - - FsmChangeState(fi, ST_L1_F3); - D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL); -} - -static void l1_go_f4(struct FsmInst *fi, int event, void *arg) -{ - FsmChangeState(fi, ST_L1_F3); -} - -static void l1_go_f5(struct FsmInst *fi, int event, void *arg) -{ - FsmChangeState(fi, ST_L1_F3); -} - -static void l1_go_f6(struct FsmInst *fi, int event, void *arg) -{ - FsmChangeState(fi, ST_L1_F6); -} - -static void l1_go_f6_deact_ind(struct FsmInst *fi, int event, void *arg) -{ - struct hfcpci_adapter *adapter = fi->userdata; - - FsmChangeState(fi, ST_L1_F6); - D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL); -} - -static void l1_go_f7(struct FsmInst *fi, int event, void *arg) -{ - FsmChangeState(fi, ST_L1_F7); -} - -static void l1_go_f7_act_ind(struct FsmInst *fi, int event, void *arg) -{ - struct hfcpci_adapter *adapter = fi->userdata; - - FsmChangeState(fi, ST_L1_F7); - D_L1L2(adapter, PH_ACTIVATE | INDICATION, NULL); -} - -static void l1_go_f8(struct FsmInst *fi, int event, void *arg) -{ - FsmChangeState(fi, ST_L1_F8); -} - -static void l1_go_f8_deact_ind(struct FsmInst *fi, int event, void *arg) -{ - struct hfcpci_adapter *adapter = fi->userdata; - - FsmChangeState(fi, ST_L1_F8); - D_L1L2(adapter, PH_DEACTIVATE | INDICATION, NULL); -} - -static void l1_act_req(struct FsmInst *fi, int event, void *arg) -{ - struct hfcpci_adapter *adapter = fi->userdata; - - hfcpci_writeb(adapter, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION, HFCPCI_STATES); -} - -static struct FsmNode L1FnList[] __initdata = -{ - {ST_L1_F2, EV_PH_F3, l1_go_f3}, - {ST_L1_F2, EV_PH_F6, l1_go_f6}, - {ST_L1_F2, EV_PH_F7, l1_go_f7_act_ind}, - - {ST_L1_F3, EV_PH_F3, l1_ignore}, - {ST_L1_F3, EV_PH_F4, l1_go_f4}, - {ST_L1_F3, EV_PH_F5, l1_go_f5}, - {ST_L1_F3, EV_PH_F6, l1_go_f6}, - {ST_L1_F3, EV_PH_F7, l1_go_f7_act_ind}, - {ST_L1_F3, EV_PH_ACTIVATE_REQ, l1_act_req}, - - {ST_L1_F4, EV_PH_F7, l1_ignore}, - {ST_L1_F4, EV_PH_F3, l1_go_f3}, - {ST_L1_F4, EV_PH_F5, l1_go_f5}, - {ST_L1_F4, EV_PH_F6, l1_go_f6}, - {ST_L1_F4, EV_PH_F7, l1_go_f7}, - - {ST_L1_F5, EV_PH_F7, l1_ignore}, - {ST_L1_F5, EV_PH_F3, l1_go_f3}, - {ST_L1_F5, EV_PH_F6, l1_go_f6}, - {ST_L1_F5, EV_PH_F7, l1_go_f7}, - - {ST_L1_F6, EV_PH_F7, l1_ignore}, - {ST_L1_F6, EV_PH_F3, l1_go_f3}, - {ST_L1_F6, EV_PH_F7, l1_go_f7_act_ind}, - {ST_L1_F6, EV_PH_F8, l1_go_f8}, - - {ST_L1_F7, EV_PH_F7, l1_ignore}, - {ST_L1_F7, EV_PH_F3, l1_go_f3_deact_ind}, - {ST_L1_F7, EV_PH_F6, l1_go_f6_deact_ind}, - {ST_L1_F7, EV_PH_F8, l1_go_f8_deact_ind}, - - {ST_L1_F8, EV_PH_F7, l1_ignore}, - {ST_L1_F8, EV_PH_F3, l1_go_f3}, - {ST_L1_F8, EV_PH_F6, l1_go_f6}, - {ST_L1_F8, EV_PH_F7, l1_go_f7_act_ind}, - -}; - -static void l1m_debug(struct FsmInst *fi, char *fmt, ...) -{ - va_list args; - char buf[256]; - - va_start(args, fmt); - vsprintf(buf, fmt, args); - DBG(DBG_L1M, "%s", buf); - va_end(args); -} - -// ---------------------------------------------------------------------- -// clear FIFOs - -static void -hfcpci_clear_d_rx_fifo(struct hfcpci_adapter *adapter) -{ - u8 fifo_state; - - DBG(DBG_D_RECV, ""); - - fifo_state = adapter->fifo_en & HFCPCI_FIFOEN_DRX; - - if (fifo_state) { // enabled - // XXX locking - adapter->fifo_en &= ~fifo_state; - hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); - } - - adapter->last_fcnt = 0; - - set_d_rx_z1(adapter, MAX_D_FRAMES - 1, D_FIFO_END - 1); - set_d_rx_z2(adapter, MAX_D_FRAMES - 1, D_FIFO_END - 1); - mb(); - set_d_rx_f1(adapter, MAX_D_FRAMES - 1); - set_d_rx_f2(adapter, MAX_D_FRAMES - 1); - mb(); - - if (fifo_state) { - adapter->fifo_en |= fifo_state; - hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); - } -} - -static void -hfcpci_clear_b_rx_fifo(struct hfcpci_bcs *bcs) -{ - struct hfcpci_adapter *adapter = bcs->adapter; - int nr = bcs->channel; - u8 fifo_state; - - DBG(DBG_B_RECV, ""); - - fifo_state = adapter->fifo_en & - (nr ? HFCPCI_FIFOEN_B2RX : HFCPCI_FIFOEN_B1RX); - - if (fifo_state) { // enabled - adapter->fifo_en &= ~fifo_state; - hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); - } - - bcs->last_fcnt = 0; - - set_b_rx_z1(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1); - set_b_rx_z2(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1); - mb(); - set_b_rx_f1(bcs, MAX_B_FRAMES - 1); - set_b_rx_f2(bcs, MAX_B_FRAMES - 1); - mb(); - - if (fifo_state) { - adapter->fifo_en |= fifo_state; - hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); - } -} - -// XXX clear d_tx_fifo? - -static void -hfcpci_clear_b_tx_fifo(struct hfcpci_bcs *bcs) -{ - struct hfcpci_adapter *adapter = bcs->adapter; - int nr = bcs->channel; - u8 fifo_state; - - fifo_state = adapter->fifo_en & - (nr ? HFCPCI_FIFOEN_B2TX : HFCPCI_FIFOEN_B1TX); - - if (fifo_state) { // enabled - adapter->fifo_en &= ~fifo_state; - hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); - } - - bcs->last_fcnt = 0; - - set_b_rx_z1(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1); - set_b_rx_z2(bcs, MAX_B_FRAMES - 1, B_FIFO_END - 1); - mb(); - set_b_rx_f1(bcs, MAX_B_FRAMES - 1); - set_b_rx_f2(bcs, MAX_B_FRAMES - 1); - mb(); - - if (fifo_state) { - adapter->fifo_en |= fifo_state; - hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); - } -} - -// ---------------------------------------------------------------------- -// receive messages from upper layers - -static void -hfcpci_d_l2l1(struct hisax_if *ifc, int pr, void *arg) -{ - struct hfcpci_adapter *adapter = ifc->priv; - struct sk_buff *skb = arg; - - DBG(DBG_PR, "pr %#x", pr); - - switch (pr) { - case PH_ACTIVATE | REQUEST: - FsmEvent(&adapter->l1m, EV_PH_ACTIVATE_REQ, NULL); - break; - case PH_DEACTIVATE | REQUEST: - FsmEvent(&adapter->l1m, EV_PH_DEACTIVATE_REQ, NULL); - break; - case PH_DATA | REQUEST: - DBG(DBG_PR, "PH_DATA REQUEST len %d", skb->len); - DBG_SKB(DBG_D_XMIT, skb); - if (adapter->l1m.state != ST_L1_F7) { - DBG(DBG_WARN, "L1 wrong state %d", adapter->l1m.state); - break; - } - if (adapter->tx_skb) - BUG(); - - adapter->tx_skb = skb; - hfcpci_fill_d_fifo(adapter); - break; - } -} - -static void -hfcpci_b_l2l1(struct hisax_if *ifc, int pr, void *arg) -{ - struct hfcpci_bcs *bcs = ifc->priv; - struct sk_buff *skb = arg; - int mode; - - DBG(DBG_PR, "pr %#x", pr); - - switch (pr) { - case PH_DATA | REQUEST: - if (bcs->tx_skb) - BUG(); - - bcs->tx_skb = skb; - DBG_SKB(DBG_B_XMIT, skb); - hfcpci_fill_b_fifo(bcs); - break; - case PH_ACTIVATE | REQUEST: - mode = (int) arg; - DBG(DBG_PR,"B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode); - hfcpci_b_mode(bcs, mode); - B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL); - break; - case PH_DEACTIVATE | REQUEST: - DBG(DBG_PR,"B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1); - hfcpci_b_mode(bcs, L1_MODE_NULL); - B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL); - break; - } -} - -// ---------------------------------------------------------------------- -// receive IRQ - -static inline void -hfcpci_d_recv_irq(struct hfcpci_adapter *adapter) -{ - struct sk_buff *skb; - char *fifo_adr = adapter->fifo + 0x4000; - char *p; - int cnt, fcnt; - int loop = 5; - u8 f1, f2; - u16 z1, z2; - - while (loop-- > 0) { - f1 = get_d_rx_f1(adapter); - f2 = get_d_rx_f2(adapter); - DBG(DBG_D_RECV, "f1 %#x f2 %#x", f1, f2); - - fcnt = f1 - f2; - if (fcnt < 0) - fcnt += 16; - - if (!fcnt) - return; - - if (fcnt < adapter->last_fcnt) - /* overrun */ - hfcpci_clear_d_rx_fifo(adapter); - // XXX init last_fcnt - - z1 = get_d_rx_z1(adapter, f2); - z2 = get_d_rx_z2(adapter, f2); - DBG(DBG_D_RECV, "z1 %#x z2 %#x", z1, z2); - - cnt = z1 - z2; - if (cnt < 0) - cnt += D_FIFO_SIZE; - cnt++; - - if (cnt < 4) { - DBG(DBG_WARN, "frame too short"); - goto next; - } - if (fifo_adr[z1] != 0) { - DBG(DBG_WARN, "CRC error"); - goto next; - } - cnt -= 3; - skb = dev_alloc_skb(cnt); - if (!skb) { - DBG(DBG_WARN, "no mem"); - goto next; - } - p = skb_put(skb, cnt); - if (z2 + cnt <= D_FIFO_END) { - memcpy(p, fifo_adr + z2, cnt); - } else { - memcpy(p, fifo_adr + z2, D_FIFO_END - z2); - memcpy(p + (D_FIFO_END - z2), fifo_adr + D_FIFO_START, - cnt - (D_FIFO_END - z2)); - } - - DBG_SKB(DBG_D_RECV, skb); - D_L1L2(adapter, PH_DATA | INDICATION, skb); - - next: - if (++z1 >= D_FIFO_END) - z1 -= D_FIFO_START; - - f2 = (f2 + 1) & (MAX_D_FRAMES - 1); - mb(); - set_d_rx_z2(adapter, f2, z1); - mb(); - set_d_rx_f2(adapter, f2); - - adapter->last_fcnt = fcnt - 1; - } -} - -static inline void -hfcpci_b_recv_hdlc_irq(struct hfcpci_adapter *adapter, int nr) -{ - struct hfcpci_bcs *bcs = &adapter->bcs[nr]; - struct sk_buff *skb; - char *fifo_adr = adapter->fifo + (nr ? 0x6000 : 0x4000); - char *p; - int cnt, fcnt; - int loop = 5; - u8 f1, f2; - u16 z1, z2; - - while (loop-- > 0) { - f1 = get_b_rx_f1(bcs); - f2 = get_b_rx_f2(bcs); - DBG(DBG_B_RECV, "f1 %d f2 %d", f1, f2); - - fcnt = f1 - f2; - if (fcnt < 0) - fcnt += 32; - - if (!fcnt) - return; - - if (fcnt < bcs->last_fcnt) - /* overrun */ - hfcpci_clear_b_rx_fifo(bcs); - // XXX init last_fcnt - - z1 = get_b_rx_z1(bcs, f2); - z2 = get_b_rx_z2(bcs, f2); - DBG(DBG_B_RECV, "z1 %d z2 %d", z1, z2); - - cnt = z1 - z2; - if (cnt < 0) - cnt += B_FIFO_SIZE; - cnt++; - - if (cnt < 4) { - DBG(DBG_WARN, "frame too short"); - goto next; - } - if (fifo_adr[z1] != 0) { - DBG(DBG_WARN, "CRC error"); - goto next; - } - cnt -= 3; - skb = dev_alloc_skb(cnt); - if (!skb) { - DBG(DBG_WARN, "no mem"); - goto next; - } - p = skb_put(skb, cnt); - if (z2 + cnt <= B_FIFO_END) { - memcpy(p, fifo_adr + z2, cnt); - } else { - memcpy(p, fifo_adr + z2, B_FIFO_END - z2); - memcpy(p + (B_FIFO_END - z2), fifo_adr + B_FIFO_START, - cnt - (B_FIFO_END - z2)); - } - - DBG_SKB(DBG_B_RECV, skb); - B_L1L2(bcs, PH_DATA | INDICATION, skb); - - next: - if (++z1 >= B_FIFO_END) - z1 -= B_FIFO_SIZE; - - f2 = (f2 + 1) & (MAX_B_FRAMES - 1); - mb(); - set_b_rx_z2(bcs, f2, z1); - mb(); - set_b_rx_f2(bcs, f2); - - bcs->last_fcnt = fcnt - 1; - } -} - -static inline void -hfcpci_b_recv_trans_irq(struct hfcpci_adapter *adapter, int nr) -{ - struct hfcpci_bcs *bcs = &adapter->bcs[nr]; - struct sk_buff *skb; - char *fifo_adr = adapter->fifo + (nr ? 0x6000 : 0x4000); - char *p; - int cnt; - int loop = 5; - u8 f1, f2; - u16 z1, z2; - - f1 = get_b_rx_f1(bcs); - f2 = get_b_rx_f2(bcs); - - if (f1 != f2) - BUG(); - - while (loop-- > 0) { - z1 = get_b_rx_z1(bcs, f2); - z2 = get_b_rx_z2(bcs, f2); - - cnt = z1 - z2; - if (!cnt) - /* no data available */ - return; - - if (cnt < 0) - cnt += B_FIFO_SIZE; - - if (cnt > HFCPCI_BTRANS_THRESHOLD) - cnt = HFCPCI_BTRANS_THRESHOLD; - - skb = dev_alloc_skb(cnt); - if (!skb) { - DBG(DBG_WARN, "no mem"); - goto next; - } - - p = skb_put(skb, cnt); - if (z2 + cnt <= 0x2000) { - memcpy(p, fifo_adr + z2, cnt); - } else { - memcpy(p, fifo_adr + z2, 0x2000 - z2); - p += 0x2000 - z2; - memcpy(p, fifo_adr + 0x200, cnt - (0x2000 - z2)); - } - - DBG_SKB(DBG_B_RECV, skb); - B_L1L2(bcs, PH_DATA | INDICATION, skb); - - next: - z2 += cnt; - if (z2 >= 0x2000) - z2 -= B_FIFO_SIZE; - - mb(); - set_b_rx_z2(bcs, f2, z2); - // XXX always receive buffers of a given size - } -} - -static inline void -hfcpci_b_recv_irq(struct hfcpci_adapter *adapter, int nr) -{ - DBG(DBG_B_RECV, ""); - - switch (adapter->bcs[nr].mode) { - case L1_MODE_NULL: - DBG(DBG_WARN, "?"); - break; - - case L1_MODE_HDLC: - hfcpci_b_recv_hdlc_irq(adapter, nr); - break; - - case L1_MODE_TRANS: - hfcpci_b_recv_trans_irq(adapter, nr); - break; - } -} - -// ---------------------------------------------------------------------- -// transmit IRQ - -// XXX make xmit FIFO deeper than 1 - -static inline void -hfcpci_d_xmit_irq(struct hfcpci_adapter *adapter) -{ - struct sk_buff *skb; - - DBG(DBG_D_XMIT, ""); - - skb = adapter->tx_skb; - if (!skb) { - DBG(DBG_WARN, "?"); - return; - } - - adapter->tx_skb = NULL; - D_L1L2(adapter, PH_DATA | CONFIRM, (void *) skb->truesize); - dev_kfree_skb_irq(skb); -} - -static inline void -hfcpci_b_xmit_irq(struct hfcpci_adapter *adapter, int nr) -{ - struct hfcpci_bcs *bcs = &adapter->bcs[nr]; - struct sk_buff *skb; - - DBG(DBG_B_XMIT, ""); - - skb = bcs->tx_skb; - if (!skb) { - DBG(DBG_WARN, "?"); - return; - } - - bcs->tx_skb = NULL; - B_L1L2(bcs, PH_DATA | CONFIRM, skb); -} - -// ---------------------------------------------------------------------- -// Layer 1 state change IRQ - -static inline void -hfcpci_state_irq(struct hfcpci_adapter *adapter) -{ - u8 val; - - val = hfcpci_readb(adapter, HFCPCI_STATES); - DBG(DBG_L1M, "STATES %#x", val); - FsmEvent(&adapter->l1m, val & 0xf, NULL); -} - -// ---------------------------------------------------------------------- -// Timer IRQ - -static inline void -hfcpci_timer_irq(struct hfcpci_adapter *adapter) -{ - hfcpci_writeb(adapter, adapter->ctmt | HFCPCI_CLTIMER, HFCPCI_CTMT); -} - -// ---------------------------------------------------------------------- -// IRQ handler - -static irqreturn_t -hfcpci_irq(int intno, void *dev, struct pt_regs *regs) -{ - struct hfcpci_adapter *adapter = dev; - int loop = 15; - u8 val, stat; - - if (!(adapter->int_m2 & 0x08)) - return IRQ_NONE; /* not initialised */ // XX - - stat = hfcpci_readb(adapter, HFCPCI_STATUS); - if (!(stat & HFCPCI_ANYINT)) - return IRQ_NONE; - - spin_lock(&adapter->hw_lock); - while (loop-- > 0) { - val = hfcpci_readb(adapter, HFCPCI_INT_S1); - DBG(DBG_IRQ, "stat %02x s1 %02x", stat, val); - val &= adapter->int_m1; - - if (!val) - break; - - if (val & 0x08) - hfcpci_b_recv_irq(adapter, 0); - - if (val & 0x10) - hfcpci_b_recv_irq(adapter, 1); - - if (val & 0x01) - hfcpci_b_xmit_irq(adapter, 0); - - if (val & 0x02) - hfcpci_b_xmit_irq(adapter, 1); - - if (val & 0x20) - hfcpci_d_recv_irq(adapter); - - if (val & 0x04) - hfcpci_d_xmit_irq(adapter); - - if (val & 0x40) - hfcpci_state_irq(adapter); - - if (val & 0x80) - hfcpci_timer_irq(adapter); - } - spin_unlock(&adapter->hw_lock); - return IRQ_HANDLED; -} - -// ---------------------------------------------------------------------- -// reset hardware - -static void -hfcpci_reset(struct hfcpci_adapter *adapter) -{ - /* disable all interrupts */ - adapter->int_m1 = 0; - adapter->int_m2 = 0; - hfcpci_writeb(adapter, adapter->int_m1, HFCPCI_INT_M1); - hfcpci_writeb(adapter, adapter->int_m2, HFCPCI_INT_M2); - - /* reset */ - hfcpci_writeb(adapter, HFCPCI_RESET, HFCPCI_CIRM); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30 * HZ) / 1000); - hfcpci_writeb(adapter, 0, HFCPCI_CIRM); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((20 * HZ) / 1000); - if (hfcpci_readb(adapter, HFCPCI_STATUS) & 2) // XX - printk(KERN_WARNING "HFC-PCI init bit busy\n"); -} - -// ---------------------------------------------------------------------- -// init hardware - -static void -hfcpci_hw_init(struct hfcpci_adapter *adapter) -{ - adapter->fifo_en = 0x30; /* only D fifos enabled */ // XX - hfcpci_writeb(adapter, adapter->fifo_en, HFCPCI_FIFO_EN); - - /* no echo connect , threshold */ - adapter->trm = HFCPCI_BTRANS_THRESMASK; - hfcpci_writeb(adapter, adapter->trm, HFCPCI_TRM); - - /* ST-Bit delay for TE-Mode */ - hfcpci_writeb(adapter, CLKDEL_TE, HFCPCI_CLKDEL); - - /* S/T Auto awake */ - adapter->sctrl_e = HFCPCI_AUTO_AWAKE; - hfcpci_writeb(adapter, adapter->sctrl_e, HFCPCI_SCTRL_E); - - /* no exchange */ - adapter->bswapped = 0; - /* we are in TE mode */ - adapter->nt_mode = 0; - - adapter->ctmt = HFCPCI_TIM3_125 | HFCPCI_AUTO_TIMER; - hfcpci_writeb(adapter, adapter->ctmt, HFCPCI_CTMT); - - adapter->int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC | - HFCPCI_INTS_L1STATE; - hfcpci_writeb(adapter, adapter->int_m1, HFCPCI_INT_M1); - - /* clear already pending ints */ - hfcpci_readb(adapter, HFCPCI_INT_S1); - - adapter->l1m.state = 2; - hfcpci_writeb(adapter, HFCPCI_LOAD_STATE | 2, HFCPCI_STATES); // XX /* HFC ST 2 */ - udelay(10); - hfcpci_writeb(adapter, 2, HFCPCI_STATES); /* HFC ST 2 */ - - /* HFC Master Mode */ - adapter->mst_m = HFCPCI_MASTER; - hfcpci_writeb(adapter, adapter->mst_m, HFCPCI_MST_MODE); - - /* set tx_lo mode, error in datasheet ! */ - adapter->sctrl = 0x40; - hfcpci_writeb(adapter, adapter->sctrl, HFCPCI_SCTRL); - - adapter->sctrl_r = 0; - hfcpci_writeb(adapter, adapter->sctrl_r, HFCPCI_SCTRL_R); - - // XXX - /* Init GCI/IOM2 in master mode */ - /* Slots 0 and 1 are set for B-chan 1 and 2 */ - /* D- and monitor/CI channel are not enabled */ - /* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */ - /* STIO2 is used as data input, B1+B2 from IOM->ST */ - /* ST B-channel send disabled -> continous 1s */ - /* The IOM slots are always enabled */ - adapter->conn = 0; /* set data flow directions */ - hfcpci_writeb(adapter, adapter->conn, HFCPCI_CONNECT); - hfcpci_writeb(adapter, 0x80, HFCPCI_B1_SSL); /* B1-Slot 0 STIO1 out enabled */ - hfcpci_writeb(adapter, 0x81, HFCPCI_B2_SSL); /* B2-Slot 1 STIO1 out enabled */ - hfcpci_writeb(adapter, 0x80, HFCPCI_B1_RSL); /* B1-Slot 0 STIO2 in enabled */ - hfcpci_writeb(adapter, 0x81, HFCPCI_B2_RSL); /* B2-Slot 1 STIO2 in enabled */ - - /* Finally enable IRQ output */ - adapter->int_m2 = HFCPCI_IRQ_ENABLE; - hfcpci_writeb(adapter, adapter->int_m2, HFCPCI_INT_M2); - - hfcpci_readb(adapter, HFCPCI_INT_S2); -} - -// ---------------------------------------------------------------------- -// probe / remove - -static struct hfcpci_adapter * __devinit -new_adapter(struct pci_dev *pdev) -{ - struct hfcpci_adapter *adapter; - struct hisax_b_if *b_if[2]; - int i; - - adapter = kmalloc(sizeof(struct hfcpci_adapter), GFP_KERNEL); - if (!adapter) - return NULL; - - memset(adapter, 0, sizeof(struct hfcpci_adapter)); - - adapter->d_if.owner = THIS_MODULE; - adapter->d_if.ifc.priv = adapter; - adapter->d_if.ifc.l2l1 = hfcpci_d_l2l1; - - for (i = 0; i < 2; i++) { - adapter->bcs[i].adapter = adapter; - adapter->bcs[i].channel = i; - adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i]; - adapter->bcs[i].b_if.ifc.l2l1 = hfcpci_b_l2l1; - } - - pci_set_drvdata(pdev, adapter); - - for (i = 0; i < 2; i++) - b_if[i] = &adapter->bcs[i].b_if; - - hisax_register(&adapter->d_if, b_if, "hfcpci", protocol); - - return adapter; -} - -static void delete_adapter(struct hfcpci_adapter *adapter) -{ - hisax_unregister(&adapter->d_if); - kfree(adapter); -} - -static int __devinit hfcpci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct hfcpci_adapter *adapter; - int retval; - - DBG(DBG_INFO, ""); - retval = -ENOMEM; - adapter = new_adapter(pdev); - if (!adapter) - goto err; - - retval = pci_enable_device(pdev); - if (retval) - goto err_free; - - adapter->irq = pdev->irq; - retval = request_irq(adapter->irq, hfcpci_irq, SA_SHIRQ, - "hfcpci", adapter); - if (retval) - goto err_free; - - retval = -EBUSY; - if (!request_mem_region(pci_resource_start(pdev, 1), 256, "hfcpci")) - goto err_free_irq; - - adapter->mmio = ioremap(pci_resource_start(pdev, 1), 256); // XX pci_io - if (!adapter->mmio) - goto err_release_region; - - /* Allocate 32K for FIFOs */ - if (pci_set_dma_mask(pdev, 0xffffffff)) - goto err_unmap; - - adapter->fifo = pci_alloc_consistent(pdev, 32768, &adapter->fifo_dma); - if (!adapter->fifo) - goto err_unmap; - - pci_write_config_dword(pdev, HFCPCI_MWBA, (u32) adapter->fifo_dma); - pci_set_master(pdev); - - adapter->l1m.fsm = &l1fsm; - adapter->l1m.state = ST_L1_F0; -#ifdef CONFIG_HISAX_DEBUG - adapter->l1m.debug = 1; -#else - adapter->l1m.debug = 0; -#endif - adapter->l1m.userdata = adapter; - adapter->l1m.printdebug = l1m_debug; - FsmInitTimer(&adapter->l1m, &adapter->timer); - - hfcpci_reset(adapter); - hfcpci_hw_init(adapter); - - printk(KERN_INFO "hisax_hfcpci: found adapter %s at %s\n", - (char *) ent->driver_data, pci_name(pdev)); - - return 0; - - err_unmap: - iounmap(adapter->mmio); - err_release_region: - release_mem_region(pci_resource_start(pdev, 1), 256); - err_free_irq: - free_irq(adapter->irq, adapter); - err_free: - delete_adapter(adapter); - err: - return retval; -} - -static void __devexit hfcpci_remove(struct pci_dev *pdev) -{ - struct hfcpci_adapter *adapter = pci_get_drvdata(pdev); - - hfcpci_reset(adapter); - -// del_timer(&cs->hw.hfcpci.timer); XX - - /* disable DMA */ - pci_disable_device(pdev); - pci_write_config_dword(pdev, HFCPCI_MWBA, 0); - pci_free_consistent(pdev, 32768, adapter->fifo, adapter->fifo_dma); - - iounmap(adapter->mmio); - release_mem_region(pci_resource_start(pdev, 1), 256); - free_irq(adapter->irq, adapter); - delete_adapter(adapter); -} - -static struct pci_driver hfcpci_driver = { - .name = "hfcpci", - .probe = hfcpci_probe, - .remove = __devexit_p(hfcpci_remove), - .id_table = hfcpci_ids, -}; - -static int __init hisax_hfcpci_init(void) -{ - int retval; - - printk(KERN_INFO "hisax_hfcpcipnp: HFC PCI ISDN driver v0.0.1\n"); - - l1fsm.state_count = L1_STATE_COUNT; - l1fsm.event_count = L1_EVENT_COUNT; - l1fsm.strState = strL1State; - l1fsm.strEvent = strL1Event; - retval = FsmNew(&l1fsm, L1FnList, ARRAY_SIZE(L1FnList)); - if (retval) - goto err; - - retval = pci_module_init(&hfcpci_driver); - if (retval) - goto err_fsm; - - return 0; - - err_fsm: - FsmFree(&l1fsm); - err: - return retval; -} - -static void __exit hisax_hfcpci_exit(void) -{ - FsmFree(&l1fsm); - pci_unregister_driver(&hfcpci_driver); -} - -module_init(hisax_hfcpci_init); -module_exit(hisax_hfcpci_exit); diff -Nru a/drivers/isdn/hisax/hisax_hfcpci.h b/drivers/isdn/hisax/hisax_hfcpci.h --- a/drivers/isdn/hisax/hisax_hfcpci.h Thu Feb 19 23:44:28 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,40 +0,0 @@ -#include "hisax_if.h" -#include "hisax_isac.h" -#include - -struct hfcpci_bcs { - struct hisax_b_if b_if; - struct hfcpci_adapter *adapter; - int mode; - int channel; - int last_fcnt; - - struct sk_buff *tx_skb; -}; - -struct hfcpci_adapter { - struct hisax_d_if d_if; - spinlock_t hw_lock; - unsigned int irq; - void *mmio; - u8 *fifo; - dma_addr_t fifo_dma; - - struct FsmInst l1m; - struct FsmTimer timer; - struct sk_buff *tx_skb; - int last_fcnt; - - u8 int_m1, int_m2; - u8 fifo_en; - u8 trm; - u8 sctrl, sctrl_r, sctrl_e; - u8 nt_mode; - u8 ctmt; - u8 mst_m; - u8 conn; - u8 bswapped; - - struct hfcpci_bcs bcs[2]; -}; - diff -Nru a/drivers/isdn/hisax/hisax_hscx.c b/drivers/isdn/hisax/hisax_hscx.c --- a/drivers/isdn/hisax/hisax_hscx.c Thu Feb 19 23:44:23 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,420 +0,0 @@ -/* - * Driver for HSCX - * High-Level Serial Communcation Controller Extended - * - * Author Kai Germaschewski - * Copyright 2001 by Kai Germaschewski - * 2001 by Karsten Keil - * - * based upon Karsten Keil's original isac.c driver - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -/* TODO: - * comments in .h - */ - -#include -#include -#include -#include "hisax_hscx.h" - -// debugging cruft - -#define __debug_variable debug -#include "hisax_debug.h" - -#ifdef CONFIG_HISAX_DEBUG -static int debug = 1; -MODULE_PARM(debug, "i"); - -static char *HSCXVer[] = -{"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7", - "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"}; -#endif - -MODULE_AUTHOR("Kai Germaschewski /Karsten Keil "); -MODULE_DESCRIPTION("HSCX driver"); - -#define DBG_WARN 0x0001 -#define DBG_IRQ 0x0002 -#define DBG_L1M 0x0004 -#define DBG_PR 0x0008 -#define DBG_RFIFO 0x0100 -#define DBG_RPACKET 0x0200 -#define DBG_XFIFO 0x1000 -#define DBG_XPACKET 0x2000 - -#define HSCX_ISTA 0x20 -#define HSCX_ISTA_EXB 0x01 -#define HSCX_ISTA_EXA 0x02 -#define HSCX_ISTA_ICA 0x04 -#define HSCX_ISTA_TIN 0x08 -#define HSCX_ISTA_XPR 0x10 -#define HSCX_ISTA_RSC 0x20 -#define HSCX_ISTA_RPF 0x40 -#define HSCX_ISTA_RME 0x80 - -#define HSCX_CMDR 0x21 -#define HSCX_CMDR_RMC 0x80 -#define HSCX_CMDR_RHR 0x40 -#define HSCX_CMDR_RNR 0x20 -#define HSCX_CMDR_STI 0x10 -#define HSCX_CMDR_XTF 0x08 -#define HSCX_CMDR_XIF 0x04 -#define HSCX_CMDR_XME 0x02 -#define HSCX_CMDR_XRES 0x01 - -#define HSCX_EXIR 0x24 -#define HSCX_EXIR_XDU 0x40 - -#define HSCX_RSTA 0x27 -#define HSCX_RSTA_VFR 0x80 -#define HSCX_RSTA_RDO 0x40 -#define HSCX_RSTA_CRC 0x20 -#define HSCX_RSTA_RAB 0x10 - -#define HSCX_CCR1 0x2f -#define HSCX_CCR2 0x2c -#define HSCX_TSAR 0x31 -#define HSCX_TSAX 0x30 -#define HSCX_XCCR 0x32 -#define HSCX_RCCR 0x33 -#define HSCX_MODE 0x22 - -#define HSCX_XAD1 0x24 -#define HSCX_XAD2 0x25 -#define HSCX_RAH2 0x27 -#define HSCX_TIMR 0x23 -#define HSCX_STAR 0x21 -#define HSCX_RBCL 0x25 -#define HSCX_XBCH 0x2d -#define HSCX_VSTR 0x2e -#define HSCX_RLCR 0x2e -#define HSCX_MASK 0x20 - -static inline void B_L1L2(struct hscx *hscx, int pr, void *arg) -{ - struct hisax_if *ifc = (struct hisax_if *) &hscx->b_if; - - DBG(0x10, "pr %#x", pr); - ifc->l1l2(ifc, pr, arg); -} - -static void hscx_version(struct hscx *hscx) -{ - int val; - - val = hscx->read_hscx(hscx, HSCX_VSTR) & 0xf; - DBG(1, "HSCX version (%x): %s", val, HSCXVer[val]); -} - -static void hscx_empty_fifo(struct hscx *hscx, int count) -{ - u8 *ptr; - - DBG(DBG_IRQ, "count %d", count); - - if ((hscx->rcvidx + count) >= HSCX_BUFMAX) { - DBG(DBG_WARN, "overrun %d", hscx->rcvidx + count); - hscx->write_hscx(hscx, HSCX_CMDR, HSCX_CMDR_RMC); - hscx->rcvidx = 0; - return; - } - ptr = hscx->rcvbuf + hscx->rcvidx; - hscx->rcvidx += count; - hscx->read_hscx_fifo(hscx, ptr, count); - hscx->write_hscx(hscx, HSCX_CMDR, HSCX_CMDR_RMC); - DBG_PACKET(DBG_RFIFO, ptr, count); -} - -static void hscx_fill_fifo(struct hscx *hscx) -{ - int count; - unsigned char cmd; - int fifo_size = test_bit(HSCX_IPAC, &hscx->flags)? 64: 32; - unsigned char *ptr; - - if (!hscx->tx_skb) - BUG(); - - count = hscx->tx_skb->len; - if (count <= 0) - BUG(); - - DBG(DBG_IRQ, "count %d", count); - - if (count > fifo_size || hscx->mode == L1_MODE_TRANS) { - count = fifo_size; - cmd = 0x8; - } else { - cmd = 0xa; - } - - ptr = hscx->tx_skb->data; - skb_pull(hscx->tx_skb, count); - hscx->tx_cnt += count; - DBG_PACKET(DBG_XFIFO, ptr, count); - hscx->write_hscx_fifo(hscx, ptr, count); - hscx->write_hscx(hscx, HSCX_CMDR, cmd); -} - -static void hscx_retransmit(struct hscx *hscx) -{ - if (!hscx->tx_skb) { - DBG(DBG_WARN, "no skb"); - return; - } - skb_push(hscx->tx_skb, hscx->tx_cnt); - hscx->tx_cnt = 0; - hscx->write_hscx(hscx, HSCX_CMDR, 0x01); -} - -static inline void hscx_rme_interrupt(struct hscx *hscx) -{ - unsigned char val; - int count; - struct sk_buff *skb; - int fifo_size = test_bit(HSCX_IPAC, &hscx->flags)? 64: 32; - - val = hscx->read_hscx(hscx, HSCX_RSTA); - if ((val & (HSCX_RSTA_VFR | HSCX_RSTA_RDO | HSCX_RSTA_CRC | HSCX_RSTA_RAB) ) - != (HSCX_RSTA_VFR | HSCX_RSTA_CRC)) { - DBG(DBG_WARN, "RSTA %#x, dropped", val); - hscx->write_hscx(hscx, HSCX_CMDR, HSCX_CMDR_RMC); - goto out; - } - - count = hscx->read_hscx(hscx, HSCX_RBCL) & (fifo_size-1); - DBG(DBG_IRQ, "RBCL %#x", count); - if (count == 0) - count = fifo_size; - - hscx_empty_fifo(hscx, count); - - count = hscx->rcvidx; - if (count < 1) { - DBG(DBG_WARN, "count %d < 1", count); - goto out; - } - - skb = alloc_skb(count, GFP_ATOMIC); - if (!skb) { - DBG(DBG_WARN, "no memory, dropping\n"); - goto out; - } - memcpy(skb_put(skb, count), hscx->rcvbuf, count); - DBG_SKB(DBG_RPACKET, skb); - B_L1L2(hscx, PH_DATA | INDICATION, skb); - out: - hscx->rcvidx = 0; -} - -static inline void hscx_xpr_interrupt(struct hscx *hscx) -{ - struct sk_buff *skb; - - skb = hscx->tx_skb; - if (!skb) - return; - - if (skb->len > 0) { - hscx_fill_fifo(hscx); - return; - } - hscx->tx_cnt = 0; - hscx->tx_skb = NULL; - B_L1L2(hscx, PH_DATA | CONFIRM, skb); -} - -static inline void hscx_exi_interrupt(struct hscx *hscx) -{ - unsigned char val; - - val = hscx->read_hscx(hscx, HSCX_EXIR); - DBG(2, "EXIR %#x", val); - - if (val & HSCX_EXIR_XDU) { - DBG(DBG_WARN, "HSCX XDU"); - if (hscx->mode == L1_MODE_TRANS) { - hscx_fill_fifo(hscx); - } else { - hscx_retransmit(hscx); - } - } -} - -static void hscx_reg_interrupt(struct hscx *hscx, unsigned char val) -{ - struct sk_buff *skb; - - if (val & HSCX_ISTA_XPR) { - DBG(DBG_IRQ, "XPR"); - hscx_xpr_interrupt(hscx); - } - if (val & HSCX_ISTA_RME) { - DBG(DBG_IRQ, "RME"); - hscx_rme_interrupt(hscx); - } - if (val & HSCX_ISTA_RPF) { - int fifo_size = test_bit(HSCX_IPAC, &hscx->flags)? 64: 32; - - DBG(DBG_IRQ, "RPF"); - hscx_empty_fifo(hscx, fifo_size); - if (hscx->mode == L1_MODE_TRANS) { - skb = dev_alloc_skb(fifo_size); - if (!skb) { - DBG(DBG_WARN, "no memory, dropping\n"); - goto out; - } - memcpy(skb_put(skb, fifo_size), hscx->rcvbuf, fifo_size); - DBG_SKB(DBG_RPACKET, skb); - B_L1L2(hscx, PH_DATA | INDICATION, skb); - out: - hscx->rcvidx = 0; - } - } -} - -void hscx_irq(struct hscx *hscx_a) -{ - struct hscx *hscx_b = hscx_a + 1; - unsigned char val; - - val = hscx_b->read_hscx(hscx_b, HSCX_ISTA); - DBG(DBG_IRQ, "ISTA B %#x", val); - - if (val & HSCX_ISTA_EXB) { - DBG(DBG_IRQ, "EXI B"); - hscx_exi_interrupt(hscx_b); - } - if (val & HSCX_ISTA_EXA) { - DBG(DBG_IRQ, "EXI A"); - hscx_exi_interrupt(hscx_a); - } - if (val & 0xf8) { - hscx_reg_interrupt(hscx_b, val); - } - if (val & HSCX_ISTA_ICA) { - val = hscx_a->read_hscx(hscx_a, HSCX_ISTA); - DBG(DBG_IRQ, "ISTA A %#x", val); - hscx_reg_interrupt(hscx_a, val); - hscx_a->write_hscx(hscx_a, HSCX_MASK, 0xff); - hscx_a->write_hscx(hscx_a, HSCX_MASK, 0x00); - } - hscx_b->write_hscx(hscx_b, HSCX_MASK, 0xff); - hscx_b->write_hscx(hscx_b, HSCX_MASK, 0x00); -} - -static void modehscx(struct hscx *hscx, int mode) -{ - int bc = hscx->channel; - - DBG(0x40, "hscx %c mode %d --> %d", - 'A' + hscx->channel, hscx->mode, mode); - - hscx->mode = mode; - hscx->write_hscx(hscx, HSCX_XAD1, 0xFF); - hscx->write_hscx(hscx, HSCX_XAD2, 0xFF); - hscx->write_hscx(hscx, HSCX_RAH2, 0xFF); - hscx->write_hscx(hscx, HSCX_XBCH, 0x0); - hscx->write_hscx(hscx, HSCX_RLCR, 0x0); - hscx->write_hscx(hscx, HSCX_CCR1, - test_bit(HSCX_IPAC, &hscx->flags) ? 0x82 : 0x85); - hscx->write_hscx(hscx, HSCX_CCR2, 0x30); - hscx->write_hscx(hscx, HSCX_XCCR, 7); - hscx->write_hscx(hscx, HSCX_RCCR, 7); - - /* Switch IOM 1 SSI */ - if (test_bit(HSCX_IOM1, &hscx->flags)) - bc = 1; - - hscx->write_hscx(hscx, HSCX_TSAX, hscx->tsaxr); - hscx->write_hscx(hscx, HSCX_TSAR, hscx->tsaxr); - - switch (mode) { - case (L1_MODE_NULL): - hscx->write_hscx(hscx, HSCX_TSAX, 0x1f); - hscx->write_hscx(hscx, HSCX_TSAR, 0x1f); - hscx->write_hscx(hscx, HSCX_MODE, 0x84); - break; - case (L1_MODE_TRANS): - hscx->write_hscx(hscx, HSCX_MODE, 0xe4); - break; - case (L1_MODE_HDLC): - hscx->write_hscx(hscx, HSCX_CCR1, test_bit(HSCX_IPAC, &hscx->flags) ? 0x8a : 0x8d); - hscx->write_hscx(hscx, HSCX_MODE, 0x8c); - break; - } - if (mode) - hscx->write_hscx(hscx, HSCX_CMDR, 0x41); - - hscx->write_hscx(hscx, HSCX_ISTA, 0x00); -} - -void hscx_init(struct hscx *hscx) -{ - if (hscx->channel) - hscx->tsaxr = 0x03; - else - hscx->tsaxr = 0x2f; -} - -void hscx_setup(struct hscx *hscx) -{ - hscx_version(hscx); - hscx->mode = -1; - modehscx(hscx, L1_MODE_NULL); -} - -void hscx_b_l2l1(struct hisax_if *ifc, int pr, void *arg) -{ - struct hscx *hscx = ifc->priv; - struct sk_buff *skb = arg; - int mode; - - DBG(0x10, "pr %#x", pr); - - switch (pr) { - case PH_DATA | REQUEST: - if (hscx->tx_skb) - BUG(); - - hscx->tx_skb = skb; - DBG_SKB(1, skb); - hscx_fill_fifo(hscx); - break; - case PH_ACTIVATE | REQUEST: - mode = (int) arg; - DBG(4,"B%d,PH_ACTIVATE_REQUEST %d", hscx->channel + 1, mode); - modehscx(hscx, mode); - B_L1L2(hscx, PH_ACTIVATE | INDICATION, NULL); - break; - case PH_DEACTIVATE | REQUEST: - DBG(4,"B%d,PH_DEACTIVATE_REQUEST", hscx->channel + 1); - modehscx(hscx, L1_MODE_NULL); - B_L1L2(hscx, PH_DEACTIVATE | INDICATION, NULL); - break; - } -} - -static int __init hisax_hscx_init(void) -{ - printk(KERN_INFO "hisax_hscx: HSCX ISDN driver v0.1.0\n"); - return 0; -} - -static void __exit hisax_hscx_exit(void) -{ -} - -EXPORT_SYMBOL(hscx_init); -EXPORT_SYMBOL(hscx_b_l2l1); - -EXPORT_SYMBOL(hscx_setup); -EXPORT_SYMBOL(hscx_irq); - -module_init(hisax_hscx_init); -module_exit(hisax_hscx_exit); diff -Nru a/drivers/isdn/hisax/hisax_hscx.h b/drivers/isdn/hisax/hisax_hscx.h --- a/drivers/isdn/hisax/hisax_hscx.h Thu Feb 19 23:44:26 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,37 +0,0 @@ -#ifndef __HISAX_HSCX_H__ -#define __HISAX_HSCX_H__ - -#include -#include "fsm.h" -#include "hisax_if.h" - -#define HSCX_BUFMAX 4096 - -#define HSCX_IOM1 0 -#define HSCX_IPAC 1 - -struct hscx { - void *priv; - u_long flags; - struct hisax_b_if b_if; - int mode; - int channel; - u8 tsaxr; - struct sk_buff *tx_skb; - int tx_cnt; - u8 rcvbuf[HSCX_BUFMAX]; - int rcvidx; - - u8 (*read_hscx) (struct hscx *, u8); - void (*write_hscx) (struct hscx *, u8, u8); - void (*read_hscx_fifo) (struct hscx *, u8 *, int); - void (*write_hscx_fifo)(struct hscx *, u8 *, int); -}; - -void hscx_init(struct hscx *hscx); -void hscx_b_l2l1(struct hisax_if *hisax_b_if, int pr, void *arg); - -void hscx_setup(struct hscx *hscx); -void hscx_irq(struct hscx *hscx); - -#endif diff -Nru a/drivers/isdn/hisax/hisax_isac.c b/drivers/isdn/hisax/hisax_isac.c --- a/drivers/isdn/hisax/hisax_isac.c Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/hisax_isac.c Thu Feb 19 23:44:23 2004 @@ -450,7 +450,7 @@ { // this also works for isacsx, since // CMDR(D) register works the same - u8 *ptr; + u_char *ptr; DBG(DBG_IRQ, "count %d", count); @@ -474,7 +474,7 @@ int count; unsigned char cmd; - u8 *ptr; + u_char *ptr; if (!isac->tx_skb) BUG(); @@ -770,7 +770,7 @@ FsmInitTimer(&isac->l1m, &isac->timer); } -void hisax_isac_setup(struct isac *isac) +void isac_setup(struct isac *isac) { int val, eval; @@ -890,7 +890,7 @@ EXPORT_SYMBOL(isacsx_setup); EXPORT_SYMBOL(isacsx_irq); -EXPORT_SYMBOL(hisax_isac_setup); +EXPORT_SYMBOL(isac_setup); EXPORT_SYMBOL(isac_irq); module_init(hisax_isac_init); diff -Nru a/drivers/isdn/hisax/hisax_isac.h b/drivers/isdn/hisax/hisax_isac.h --- a/drivers/isdn/hisax/hisax_isac.h Thu Feb 19 23:44:26 2004 +++ b/drivers/isdn/hisax/hisax_isac.h Thu Feb 19 23:44:26 2004 @@ -17,26 +17,26 @@ struct hisax_d_if hisax_d_if; struct FsmInst l1m; struct FsmTimer timer; - u8 mocr; - u8 adf2; + u_char mocr; + u_char adf2; int type; - u8 rcvbuf[MAX_DFRAME_LEN_L1]; + u_char rcvbuf[MAX_DFRAME_LEN_L1]; int rcvidx; struct sk_buff *tx_skb; int tx_cnt; - u8 (*read_isac) (struct isac *, u8); - void (*write_isac) (struct isac *, u8, u8); - void (*read_isac_fifo) (struct isac *, u8 *, int); - void (*write_isac_fifo)(struct isac *, u8 *, int); + u_char (*read_isac) (struct isac *, u_char); + void (*write_isac) (struct isac *, u_char, u_char); + void (*read_isac_fifo) (struct isac *, u_char *, int); + void (*write_isac_fifo)(struct isac *, u_char *, int); }; void isac_init(struct isac *isac); void isac_d_l2l1(struct hisax_if *hisax_d_if, int pr, void *arg); -void hisax_isac_setup(struct isac *isac); +void isac_setup(struct isac *isac); void isac_irq(struct isac *isac); void isacsx_setup(struct isac *isac); diff -Nru a/drivers/isdn/hisax/hscx.c b/drivers/isdn/hisax/hscx.c --- a/drivers/isdn/hisax/hscx.c Thu Feb 19 23:44:22 2004 +++ b/drivers/isdn/hisax/hscx.c Thu Feb 19 23:44:22 2004 @@ -1,4 +1,4 @@ -/* $Id: hscx.c,v 1.21.6.3 2001/09/23 22:24:48 kai Exp $ +/* $Id: hscx.c,v 1.24.2.4 2004/01/24 20:47:23 keil Exp $ * * HSCX specific routines * @@ -17,133 +17,136 @@ #include "isdnl1.h" #include -static char *HSCXVer[] __initdata = +static char *HSCXVer[] = {"A1", "?1", "A2", "?3", "A3", "V2.1", "?6", "?7", "?8", "?9", "?10", "?11", "?12", "?13", "?14", "???"}; -static inline u8 -hscx_read(struct BCState *bcs, u8 addr) -{ - struct IsdnCardState *cs = bcs->cs; - - return cs->bc_hw_ops->read_reg(cs, bcs->unit, addr); -} - -static inline void -hscx_write(struct BCState *bcs, u8 addr, u8 val) -{ - struct IsdnCardState *cs = bcs->cs; - - cs->bc_hw_ops->write_reg(cs, bcs->unit, addr, val); -} - -static inline void -hscx_write_fifo(struct BCState *bcs, u8 *p, int len) -{ - struct IsdnCardState *cs = bcs->cs; - - cs->bc_hw_ops->write_fifo(cs, bcs->unit, p, len); -} - -static int +int HscxVersion(struct IsdnCardState *cs, char *s) { int verA, verB; - verA = cs->bc_hw_ops->read_reg(cs, 0, HSCX_VSTR) & 0xf; - verB = cs->bc_hw_ops->read_reg(cs, 1, HSCX_VSTR) & 0xf; + verA = cs->BC_Read_Reg(cs, 0, HSCX_VSTR) & 0xf; + verB = cs->BC_Read_Reg(cs, 1, HSCX_VSTR) & 0xf; printk(KERN_INFO "%s HSCX version A: %s B: %s\n", s, HSCXVer[verA], HSCXVer[verB]); if ((verA == 0) | (verA == 0xf) | (verB == 0) | (verB == 0xf)) - return 1; + return (1); else - return 0; + return (0); } void modehscx(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - int hscx = bcs->unit; + int hscx = bcs->hw.hscx.hscx; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "hscx %c mode %d ichan %d", 'A' + hscx, mode, bc); bcs->mode = mode; bcs->channel = bc; - hscx_write(bcs, HSCX_XAD1, 0xFF); - hscx_write(bcs, HSCX_XAD2, 0xFF); - hscx_write(bcs, HSCX_RAH2, 0xFF); - hscx_write(bcs, HSCX_XBCH, 0x0); - hscx_write(bcs, HSCX_RLCR, 0x0); - hscx_write(bcs, HSCX_CCR1, + cs->BC_Write_Reg(cs, hscx, HSCX_XAD1, 0xFF); + cs->BC_Write_Reg(cs, hscx, HSCX_XAD2, 0xFF); + cs->BC_Write_Reg(cs, hscx, HSCX_RAH2, 0xFF); + cs->BC_Write_Reg(cs, hscx, HSCX_XBCH, 0x0); + cs->BC_Write_Reg(cs, hscx, HSCX_RLCR, 0x0); + cs->BC_Write_Reg(cs, hscx, HSCX_CCR1, test_bit(HW_IPAC, &cs->HW_Flags) ? 0x82 : 0x85); - hscx_write(bcs, HSCX_CCR2, 0x30); - hscx_write(bcs, HSCX_XCCR, 7); - hscx_write(bcs, HSCX_RCCR, 7); + cs->BC_Write_Reg(cs, hscx, HSCX_CCR2, 0x30); + cs->BC_Write_Reg(cs, hscx, HSCX_XCCR, 7); + cs->BC_Write_Reg(cs, hscx, HSCX_RCCR, 7); /* Switch IOM 1 SSI */ if (test_bit(HW_IOM1, &cs->HW_Flags) && (hscx == 0)) bc = 1 - bc; if (bc == 0) { - hscx_write(bcs, HSCX_TSAX, + cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0); - hscx_write(bcs, HSCX_TSAR, + cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, test_bit(HW_IOM1, &cs->HW_Flags) ? 0x7 : bcs->hw.hscx.tsaxr0); } else { - hscx_write(bcs, HSCX_TSAX, bcs->hw.hscx.tsaxr1); - hscx_write(bcs, HSCX_TSAR, bcs->hw.hscx.tsaxr1); + cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, bcs->hw.hscx.tsaxr1); + cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, bcs->hw.hscx.tsaxr1); } switch (mode) { - case L1_MODE_NULL: - hscx_write(bcs, HSCX_TSAX, 0x1f); - hscx_write(bcs, HSCX_TSAR, 0x1f); - hscx_write(bcs, HSCX_MODE, 0x84); - break; - case L1_MODE_TRANS: - hscx_write(bcs, HSCX_MODE, 0xe4); - break; - case L1_MODE_HDLC: - hscx_write(bcs, HSCX_CCR1, - test_bit(HW_IPAC, &cs->HW_Flags) ? 0x8a : 0x8d); - hscx_write(bcs, HSCX_MODE, 0x8c); - break; + case (L1_MODE_NULL): + cs->BC_Write_Reg(cs, hscx, HSCX_TSAX, 0x1f); + cs->BC_Write_Reg(cs, hscx, HSCX_TSAR, 0x1f); + cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x84); + break; + case (L1_MODE_TRANS): + cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0xe4); + break; + case (L1_MODE_HDLC): + cs->BC_Write_Reg(cs, hscx, HSCX_CCR1, + test_bit(HW_IPAC, &cs->HW_Flags) ? 0x8a : 0x8d); + cs->BC_Write_Reg(cs, hscx, HSCX_MODE, 0x8c); + break; } if (mode) - hscx_write(bcs, HSCX_CMDR, 0x41); - - hscx_write(bcs, HSCX_ISTA, 0x00); + cs->BC_Write_Reg(cs, hscx, HSCX_CMDR, 0x41); + cs->BC_Write_Reg(cs, hscx, HSCX_ISTA, 0x00); } void hscx_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; + u_long flags; struct sk_buff *skb = arg; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->hw.hscx.count = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "hscx_l2l1: this shouldn't happen\n"); + } else { + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->hw.hscx.count = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - modehscx(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + modehscx(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - modehscx(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + modehscx(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -152,17 +155,50 @@ close_hscxstate(struct BCState *bcs) { modehscx(bcs, 0, bcs->channel); - bc_close(bcs); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.hscx.rcvbuf) { + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + } + if (bcs->blog) { + kfree(bcs->blog); + bcs->blog = NULL; + } + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); + if (bcs->tx_skb) { + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } } int open_hscxstate(struct IsdnCardState *cs, struct BCState *bcs) { - bc_open(bcs); + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for hscx.rcvbuf\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + return (1); + } + if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for bcs->blog\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + return (2); + } + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } bcs->tx_skb = NULL; test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->event = 0; - bcs->rcvidx = 0; + bcs->hw.hscx.rcvidx = 0; bcs->tx_cnt = 0; return (0); } @@ -174,80 +210,71 @@ if (open_hscxstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = hscx_l2l1; + st->l2.l2l1 = hscx_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); return (0); } -static void hscx_fill_fifo(struct BCState *bcs); - -static struct bc_l1_ops hscx_l1_ops = { - .fill_fifo = hscx_fill_fifo, - .open = setstack_hscx, - .close = close_hscxstate, -}; - -void __init -inithscx(struct IsdnCardState *cs) +void +clear_pending_hscx_ints(struct IsdnCardState *cs) { int val, eval; - - cs->bc_l1_ops = &hscx_l1_ops; - cs->bcs[0].unit = 0; - cs->bcs[1].unit = 1; - cs->bcs[0].hw.hscx.tsaxr0 = 0x2f; - cs->bcs[0].hw.hscx.tsaxr1 = 3; - cs->bcs[1].hw.hscx.tsaxr0 = 0x2f; - cs->bcs[1].hw.hscx.tsaxr1 = 3; - val = hscx_read(&cs->bcs[1], HSCX_ISTA); + val = cs->BC_Read_Reg(cs, 1, HSCX_ISTA); debugl1(cs, "HSCX B ISTA %x", val); if (val & 0x01) { - eval = hscx_read(&cs->bcs[1], HSCX_EXIR); + eval = cs->BC_Read_Reg(cs, 1, HSCX_EXIR); debugl1(cs, "HSCX B EXIR %x", eval); } if (val & 0x02) { - eval = hscx_read(&cs->bcs[0], HSCX_EXIR); + eval = cs->BC_Read_Reg(cs, 0, HSCX_EXIR); debugl1(cs, "HSCX A EXIR %x", eval); } - val = hscx_read(&cs->bcs[0], HSCX_ISTA); + val = cs->BC_Read_Reg(cs, 0, HSCX_ISTA); debugl1(cs, "HSCX A ISTA %x", val); - val = hscx_read(&cs->bcs[1], HSCX_STAR); + val = cs->BC_Read_Reg(cs, 1, HSCX_STAR); debugl1(cs, "HSCX B STAR %x", val); - val = hscx_read(&cs->bcs[0], HSCX_STAR); + val = cs->BC_Read_Reg(cs, 0, HSCX_STAR); debugl1(cs, "HSCX A STAR %x", val); /* disable all IRQ */ - hscx_write(&cs->bcs[0], HSCX_MASK, 0xFF); - hscx_write(&cs->bcs[1], HSCX_MASK, 0xFF); - - modehscx(&cs->bcs[0], 0, 0); - modehscx(&cs->bcs[1], 0, 0); - - /* Reenable all IRQ */ - hscx_write(&cs->bcs[0], HSCX_MASK, 0x0); - hscx_write(&cs->bcs[1], HSCX_MASK, 0x0); + cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0xFF); + cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0xFF); } void -inithscxisac(struct IsdnCardState *cs) +inithscx(struct IsdnCardState *cs) { - initisac(cs); - inithscx(cs); + cs->bcs[0].BC_SetStack = setstack_hscx; + cs->bcs[1].BC_SetStack = setstack_hscx; + cs->bcs[0].BC_Close = close_hscxstate; + cs->bcs[1].BC_Close = close_hscxstate; + cs->bcs[0].hw.hscx.hscx = 0; + cs->bcs[1].hw.hscx.hscx = 1; + cs->bcs[0].hw.hscx.tsaxr0 = 0x2f; + cs->bcs[0].hw.hscx.tsaxr1 = 3; + cs->bcs[1].hw.hscx.tsaxr0 = 0x2f; + cs->bcs[1].hw.hscx.tsaxr1 = 3; + modehscx(cs->bcs, 0, 0); + modehscx(cs->bcs + 1, 0, 0); } -int -hscxisac_setup(struct IsdnCardState *cs, struct dc_hw_ops *isac_ops, - struct bc_hw_ops *hscx_ops) +void +inithscxisac(struct IsdnCardState *cs, int part) { - isac_setup(cs, isac_ops); - cs->bc_hw_ops = hscx_ops; - if (HscxVersion(cs, "HiSax:")) { - printk(KERN_WARNING "HiSax: invalid HSCX version\n"); - return -ENODEV; + if (part & 1) { + clear_pending_isac_ints(cs); + clear_pending_hscx_ints(cs); + initisac(cs); + inithscx(cs); + } + if (part & 2) { + /* Reenable all IRQ */ + cs->writeisac(cs, ISAC_MASK, 0); + cs->BC_Write_Reg(cs, 0, HSCX_MASK, 0); + cs->BC_Write_Reg(cs, 1, HSCX_MASK, 0); + /* RESET Receiver and Transmitter */ + cs->writeisac(cs, ISAC_CMDR, 0x41); } - return 0; } - -#include "hscx_irq.c" diff -Nru a/drivers/isdn/hisax/hscx.h b/drivers/isdn/hisax/hscx.h --- a/drivers/isdn/hisax/hscx.h Thu Feb 19 23:44:26 2004 +++ b/drivers/isdn/hisax/hscx.h Thu Feb 19 23:44:26 2004 @@ -1,4 +1,4 @@ -/* $Id: hscx.h,v 1.6.6.2 2001/09/23 22:24:48 kai Exp $ +/* $Id: hscx.h,v 1.8.2.2 2004/01/12 22:52:26 keil Exp $ * * HSCX specific defines * @@ -10,8 +10,6 @@ * */ -#include - /* All Registers original Siemens Spec */ #define HSCX_ISTA 0x20 @@ -36,10 +34,8 @@ #define HSCX_RLCR 0x2e #define HSCX_MASK 0x20 +extern int HscxVersion(struct IsdnCardState *cs, char *s); extern void modehscx(struct BCState *bcs, int mode, int bc); -extern void inithscxisac(struct IsdnCardState *cs); -extern void hscx_int_main(struct IsdnCardState *cs, u8 val); -extern irqreturn_t hscxisac_irq(int intno, void *dev_id, struct pt_regs *regs); -extern int hscxisac_setup(struct IsdnCardState *cs, - struct dc_hw_ops *isac_ops, - struct bc_hw_ops *hscx_ops); +extern void clear_pending_hscx_ints(struct IsdnCardState *cs); +extern void inithscx(struct IsdnCardState *cs); +extern void inithscxisac(struct IsdnCardState *cs, int part); diff -Nru a/drivers/isdn/hisax/hscx_irq.c b/drivers/isdn/hisax/hscx_irq.c --- a/drivers/isdn/hisax/hscx_irq.c Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/hisax/hscx_irq.c Thu Feb 19 23:44:28 2004 @@ -1,4 +1,4 @@ -/* $Id: hscx_irq.c,v 1.16.6.2 2001/09/23 22:24:48 kai Exp $ +/* $Id: hscx_irq.c,v 1.18.2.3 2004/02/11 13:21:34 keil Exp $ * * low level b-channel stuff for Siemens HSCX * @@ -12,12 +12,13 @@ * */ -static void -waitforCEC(struct BCState *bcs) + +static inline void +waitforCEC(struct IsdnCardState *cs, int hscx) { int to = 50; - while ((hscx_read(bcs, HSCX_STAR) & 0x04) && to) { + while ((READHSCX(cs, hscx, HSCX_STAR) & 0x04) && to) { udelay(1); to--; } @@ -26,12 +27,12 @@ } -static void -waitforXFW(struct BCState *bcs) +static inline void +waitforXFW(struct IsdnCardState *cs, int hscx) { int to = 50; - while ((!(hscx_read(bcs, HSCX_STAR) & 0x44) == 0x40) && to) { + while ((!(READHSCX(cs, hscx, HSCX_STAR) & 0x44) == 0x40) && to) { udelay(1); to--; } @@ -40,18 +41,42 @@ } static inline void -WriteHSCXCMDR(struct BCState *bcs, u8 data) +WriteHSCXCMDR(struct IsdnCardState *cs, int hscx, u_char data) { - waitforCEC(bcs); - hscx_write(bcs, HSCX_CMDR, data); + waitforCEC(cs, hscx); + WRITEHSCX(cs, hscx, HSCX_CMDR, data); } + static void hscx_empty_fifo(struct BCState *bcs, int count) { - recv_empty_fifo_b(bcs, count); - WriteHSCXCMDR(bcs, 0x80); + u_char *ptr; + struct IsdnCardState *cs = bcs->cs; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hscx_empty_fifo"); + + if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "hscx_empty_fifo: incoming packet too large"); + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); + bcs->hw.hscx.rcvidx = 0; + return; + } + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + bcs->hw.hscx.rcvidx += count; + READHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count); + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x80); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "hscx_empty_fifo %c cnt %d", + bcs->hw.hscx.hscx ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } static void @@ -60,22 +85,46 @@ struct IsdnCardState *cs = bcs->cs; int more, count; int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; - u8 *p; + u_char *ptr; - p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more); - if (!p) + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "hscx_fill_fifo"); + + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) return; - waitforXFW(bcs); - hscx_write_fifo(bcs, p, count); - WriteHSCXCMDR(bcs, more ? 0x8 : 0xa); + more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; + if (bcs->tx_skb->len > fifo_size) { + more = !0; + count = fifo_size; + } else + count = bcs->tx_skb->len; + + waitforXFW(cs, bcs->hw.hscx.hscx); + ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.hscx.count += count; + WRITEHSCXFIFO(cs, bcs->hw.hscx.hscx, ptr, count); + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, more ? 0x8 : 0xa); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "hscx_fill_fifo %c cnt %d", + bcs->hw.hscx.hscx ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } static inline void -hscx_interrupt(struct IsdnCardState *cs, u8 val, u8 hscx) +hscx_interrupt(struct IsdnCardState *cs, u_char val, u_char hscx) { - u8 r; + u_char r; struct BCState *bcs = cs->bcs + hscx; + struct sk_buff *skb; int fifo_size = test_bit(HW_IPAC, &cs->HW_Flags)? 64: 32; int count; @@ -83,7 +132,7 @@ return; if (val & 0x80) { /* RME */ - r = hscx_read(bcs, HSCX_RSTA); + r = READHSCX(cs, hscx, HSCX_RSTA); if ((r & 0xf0) != 0xa0) { if (!(r & 0x80)) { if (cs->debug & L1_DEB_WARN) @@ -107,46 +156,102 @@ bcs->err_crc++; #endif } - WriteHSCXCMDR(bcs, 0x80); - bcs->rcvidx = 0; + WriteHSCXCMDR(cs, hscx, 0x80); } else { - count = hscx_read(bcs, HSCX_RBCL) & (fifo_size-1); + count = READHSCX(cs, hscx, HSCX_RBCL) & ( + test_bit(HW_IPAC, &cs->HW_Flags)? 0x3f: 0x1f); if (count == 0) count = fifo_size; - hscx_empty_fifo(bcs, count); - recv_rme_b(bcs); + if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { + if (cs->debug & L1_DEB_HSCX_FIFO) + debugl1(cs, "HX Frame %d", count); + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "HSCX: receive out of memory\n"); + else { + memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); + skb_queue_tail(&bcs->rqueue, skb); + } + } } + bcs->hw.hscx.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); } if (val & 0x40) { /* RPF */ hscx_empty_fifo(bcs, fifo_size); - recv_rpf_b(bcs); + if (bcs->mode == L1_MODE_TRANS) { + /* receive audio data */ + if (!(skb = dev_alloc_skb(fifo_size))) + printk(KERN_WARNING "HiSax: receive out of memory\n"); + else { + memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.hscx.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); + } } - if (val & 0x10) { - xmit_xpr_b(bcs); + if (val & 0x10) { /* XPR */ + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + hscx_fill_fifo(bcs); + return; + } else { + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hscx.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_irq(bcs->tx_skb); + bcs->hw.hscx.count = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hscx.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + hscx_fill_fifo(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + schedule_event(bcs, B_XMTBUFREADY); + } } } -static void -reset_xmit(struct BCState *bcs) +static inline void +hscx_int_main(struct IsdnCardState *cs, u_char val) { - WriteHSCXCMDR(bcs, 0x01); -} -void -hscx_int_main(struct IsdnCardState *cs, u8 val) -{ - u8 exval; + u_char exval; struct BCState *bcs; if (val & 0x01) { bcs = cs->bcs + 1; - exval = hscx_read(bcs, HSCX_EXIR); - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX B EXIR %x", exval); + exval = READHSCX(cs, 1, HSCX_EXIR); if (exval & 0x40) { - xmit_xdu_b(bcs, reset_xmit); - } + if (bcs->mode == 1) + hscx_fill_fifo(bcs); + else { +#ifdef ERROR_STATISTIC + bcs->err_tx++; +#endif + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hscx.count); + bcs->tx_cnt += bcs->hw.hscx.count; + bcs->hw.hscx.count = 0; + } + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX B EXIR %x Lost TX", exval); + } + } else if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX B EXIR %x", exval); } if (val & 0xf8) { if (cs->debug & L1_DEB_HSCX) @@ -155,72 +260,33 @@ } if (val & 0x02) { bcs = cs->bcs; - exval = hscx_read(bcs, HSCX_EXIR); - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX A EXIR %x", exval); + exval = READHSCX(cs, 0, HSCX_EXIR); if (exval & 0x40) { - xmit_xdu_b(bcs, reset_xmit); - } + if (bcs->mode == L1_MODE_TRANS) + hscx_fill_fifo(bcs); + else { + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ +#ifdef ERROR_STATISTIC + bcs->err_tx++; +#endif + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hscx.count); + bcs->tx_cnt += bcs->hw.hscx.count; + bcs->hw.hscx.count = 0; + } + WriteHSCXCMDR(cs, bcs->hw.hscx.hscx, 0x01); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "HSCX A EXIR %x Lost TX", exval); + } + } else if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX A EXIR %x", exval); } if (val & 0x04) { - bcs = cs->bcs; - exval = hscx_read(bcs, HSCX_ISTA); + exval = READHSCX(cs, 0, HSCX_ISTA); if (cs->debug & L1_DEB_HSCX) debugl1(cs, "HSCX A interrupt %x", exval); hscx_interrupt(cs, exval, 0); } } - -/* ====================================================================== */ - -static inline u8 -isac_read(struct IsdnCardState *cs, u8 addr) -{ - return cs->dc_hw_ops->read_reg(cs, addr); -} - -static inline void -isac_write(struct IsdnCardState *cs, u8 addr, u8 val) -{ - cs->dc_hw_ops->write_reg(cs, addr, val); -} - -irqreturn_t -hscxisac_irq(int intno, void *dev_id, struct pt_regs *regs) -{ - struct IsdnCardState *cs = dev_id; - u8 val; - int count = 0; - - spin_lock(&cs->lock); - val = hscx_read(&cs->bcs[1], HSCX_ISTA); - Start_HSCX: - if (val) - hscx_int_main(cs, val); - val = isac_read(cs, ISAC_ISTA); - Start_ISAC: - if (val) - isac_interrupt(cs, val); - count++; - val = hscx_read(&cs->bcs[1], HSCX_ISTA); - if (val && count < 5) { - if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "HSCX IntStat after IntRoutine"); - goto Start_HSCX; - } - val = isac_read(cs, ISAC_ISTA); - if (val && count < 5) { - if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "ISAC IntStat after IntRoutine"); - goto Start_ISAC; - } - hscx_write(&cs->bcs[0], HSCX_MASK, 0xFF); - hscx_write(&cs->bcs[1], HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(&cs->bcs[0], HSCX_MASK, 0x0); - hscx_write(&cs->bcs[1], HSCX_MASK, 0x0); - spin_unlock(&cs->lock); - return IRQ_HANDLED; -} - diff -Nru a/drivers/isdn/hisax/icc.c b/drivers/isdn/hisax/icc.c --- a/drivers/isdn/hisax/icc.c Thu Feb 19 23:44:22 2004 +++ b/drivers/isdn/hisax/icc.c Thu Feb 19 23:44:22 2004 @@ -1,4 +1,4 @@ -/* $Id: icc.c,v 1.5.6.4 2001/09/23 22:24:48 kai Exp $ +/* $Id: icc.c,v 1.8.2.3 2004/01/13 14:31:25 keil Exp $ * * ICC specific routines * @@ -24,39 +24,15 @@ #define DBUSY_TIMER_VALUE 80 #define ARCOFI_USE 0 -static inline u8 -icc_read_reg(struct IsdnCardState *cs, u8 addr) -{ - return cs->dc_hw_ops->read_reg(cs, addr); -} - -static inline void -icc_write_reg(struct IsdnCardState *cs, u8 addr, u8 val) -{ - cs->dc_hw_ops->write_reg(cs, addr, val); -} - -static inline void -icc_read_fifo(struct IsdnCardState *cs, u8 *p, int len) -{ - return cs->dc_hw_ops->read_fifo(cs, p, len); -} - -static inline void -icc_write_fifo(struct IsdnCardState *cs, u8 *p, int len) -{ - return cs->dc_hw_ops->write_fifo(cs, p, len); -} - static char *ICCVer[] __initdata = {"2070 A1/A3", "2070 B1", "2070 B2/B3", "2070 V2.4"}; -static void +void ICCVersion(struct IsdnCardState *cs, char *s) { int val; - val = icc_read_reg(cs, ICC_RBCH); + val = cs->readisac(cs, ICC_RBCH); printk(KERN_INFO "%s ICC version (%x): %s\n", s, val, ICCVer[(val >> 5) & 3]); } @@ -65,7 +41,7 @@ { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_command %x", command); - icc_write_reg(cs, ICC_CIX0, (command << 2) | 3); + cs->writeisac(cs, ICC_CIX0, (command << 2) | 3); } @@ -101,9 +77,8 @@ } static void -icc_bh(void *data) +icc_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; struct PStack *stptr; if (!cs) @@ -113,7 +88,7 @@ debugl1(cs, "D-Channel Busy cleared"); stptr = cs->stlist; while (stptr != NULL) { - L1L2(stptr, PH_PAUSE | CONFIRM, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); stptr = stptr->next; } } @@ -136,22 +111,58 @@ void icc_empty_fifo(struct IsdnCardState *cs, int count) { - recv_empty_fifo_d(cs, count); - icc_write_reg(cs, ICC_CMDR, 0x80); + u_char *ptr; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, "icc_empty_fifo"); + + if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "icc_empty_fifo overrun %d", + cs->rcvidx + count); + cs->writeisac(cs, ICC_CMDR, 0x80); + cs->rcvidx = 0; + return; + } + ptr = cs->rcvbuf + cs->rcvidx; + cs->rcvidx += count; + cs->readisacfifo(cs, ptr, count); + cs->writeisac(cs, ICC_CMDR, 0x80); + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "icc_empty_fifo cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } } static void icc_fill_fifo(struct IsdnCardState *cs) { int count, more; - unsigned char *p; + u_char *ptr; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, "icc_fill_fifo"); - p = xmit_fill_fifo_d(cs, 32, &count, &more); - if (!p) + if (!cs->tx_skb) return; - icc_write_fifo(cs, p, count); - icc_write_reg(cs, ICC_CMDR, more ? 0x8 : 0xa); + count = cs->tx_skb->len; + if (count <= 0) + return; + + more = 0; + if (count > 32) { + more = !0; + count = 32; + } + ptr = cs->tx_skb->data; + skb_pull(cs->tx_skb, count); + cs->tx_cnt += count; + cs->writeisacfifo(cs, ptr, count); + cs->writeisac(cs, ICC_CMDR, more ? 0x8 : 0xa); if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { debugl1(cs, "icc_fill_fifo dbusytimer running"); del_timer(&cs->dbusytimer); @@ -159,18 +170,26 @@ init_timer(&cs->dbusytimer); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); add_timer(&cs->dbusytimer); + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "icc_fill_fifo cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } } void -icc_interrupt(struct IsdnCardState *cs, u8 val) +icc_interrupt(struct IsdnCardState *cs, u_char val) { - u8 exval, v1; + u_char exval, v1; + struct sk_buff *skb; unsigned int count; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ICC interrupt %x", val); if (val & 0x80) { /* RME */ - exval = icc_read_reg(cs, ICC_RSTA); + exval = cs->readisac(cs, ICC_RSTA); if ((exval & 0x70) != 0x20) { if (exval & 0x40) { if (cs->debug & L1_DEB_WARN) @@ -186,15 +205,24 @@ cs->err_crc++; #endif } - icc_write_reg(cs, ICC_CMDR, 0x80); - cs->rcvidx = 0; + cs->writeisac(cs, ICC_CMDR, 0x80); } else { - count = icc_read_reg(cs, ICC_RBCL) & 0x1f; + count = cs->readisac(cs, ICC_RBCL) & 0x1f; if (count == 0) count = 32; icc_empty_fifo(cs, count); - recv_rme_d(cs); + if ((count = cs->rcvidx) > 0) { + cs->rcvidx = 0; + if (!(skb = alloc_skb(count, GFP_ATOMIC))) + printk(KERN_WARNING "HiSax: D receive out of memory\n"); + else { + memcpy(skb_put(skb, count), cs->rcvbuf, count); + skb_queue_tail(&cs->rq, skb); + } + } } + cs->rcvidx = 0; + schedule_event(cs, D_RCVBUFREADY); } if (val & 0x40) { /* RPF */ icc_empty_fifo(cs, 32); @@ -205,20 +233,39 @@ debugl1(cs, "ICC RSC interrupt"); } if (val & 0x10) { /* XPR */ - xmit_xpr_d(cs); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + icc_fill_fifo(cs); + goto afterXPR; + } else { + dev_kfree_skb_irq(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + icc_fill_fifo(cs); + } else + schedule_event(cs, D_XMTBUFREADY); } + afterXPR: if (val & 0x04) { /* CISQ */ - exval = icc_read_reg(cs, ICC_CIR0); + exval = cs->readisac(cs, ICC_CIR0); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ICC CIR0 %02X", exval ); if (exval & 2) { cs->dc.icc.ph_state = (exval >> 2) & 0xf; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_state change %x", cs->dc.icc.ph_state); - sched_d_event(cs, D_L1STATECHANGE); + schedule_event(cs, D_L1STATECHANGE); } if (exval & 1) { - exval = icc_read_reg(cs, ICC_CIR1); + exval = cs->readisac(cs, ICC_CIR1); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ICC CIR1 %02X", exval ); } @@ -229,7 +276,7 @@ debugl1(cs, "ICC SIN interrupt"); } if (val & 0x01) { /* EXI */ - exval = icc_read_reg(cs, ICC_EXIR); + exval = cs->readisac(cs, ICC_EXIR); if (cs->debug & L1_DEB_WARN) debugl1(cs, "ICC EXIR %02x", exval); if (exval & 0x80) { /* XMR */ @@ -237,10 +284,26 @@ printk(KERN_WARNING "HiSax: ICC XMR\n"); } if (exval & 0x40) { /* XDU */ - xmit_xdu_d(cs, NULL); + debugl1(cs, "ICC XDU"); + printk(KERN_WARNING "HiSax: ICC XDU\n"); +#ifdef ERROR_STATISTIC + cs->err_tx++; +#endif + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { /* Restart frame */ + skb_push(cs->tx_skb, cs->tx_cnt); + cs->tx_cnt = 0; + icc_fill_fifo(cs); + } else { + printk(KERN_WARNING "HiSax: ICC XDU no skb\n"); + debugl1(cs, "ICC XDU no skb"); + } } if (exval & 0x04) { /* MOS */ - v1 = icc_read_reg(cs, ICC_MOSR); + v1 = cs->readisac(cs, ICC_MOSR); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ICC MOSR %02x", v1); #if ARCOFI_USE @@ -251,7 +314,7 @@ debugl1(cs, "ICC MON RX out of memory!"); cs->dc.icc.mocr &= 0xf0; cs->dc.icc.mocr |= 0x0a; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); goto afterMONR0; } else cs->dc.icc.mon_rxp = 0; @@ -259,18 +322,18 @@ if (cs->dc.icc.mon_rxp >= MAX_MON_FRAME) { cs->dc.icc.mocr &= 0xf0; cs->dc.icc.mocr |= 0x0a; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); cs->dc.icc.mon_rxp = 0; if (cs->debug & L1_DEB_WARN) debugl1(cs, "ICC MON RX overflow!"); goto afterMONR0; } - cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = icc_read_reg(cs, ICC_MOR0); + cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = cs->readisac(cs, ICC_MOR0); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ICC MOR0 %02x", cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp -1]); if (cs->dc.icc.mon_rxp == 1) { cs->dc.icc.mocr |= 0x04; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); } } afterMONR0: @@ -281,7 +344,7 @@ debugl1(cs, "ICC MON RX out of memory!"); cs->dc.icc.mocr &= 0x0f; cs->dc.icc.mocr |= 0xa0; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); goto afterMONR1; } else cs->dc.icc.mon_rxp = 0; @@ -289,51 +352,51 @@ if (cs->dc.icc.mon_rxp >= MAX_MON_FRAME) { cs->dc.icc.mocr &= 0x0f; cs->dc.icc.mocr |= 0xa0; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); cs->dc.icc.mon_rxp = 0; if (cs->debug & L1_DEB_WARN) debugl1(cs, "ICC MON RX overflow!"); goto afterMONR1; } - cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = icc_read_reg(cs, ICC_MOR1); + cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp++] = cs->readisac(cs, ICC_MOR1); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ICC MOR1 %02x", cs->dc.icc.mon_rx[cs->dc.icc.mon_rxp -1]); cs->dc.icc.mocr |= 0x40; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); } afterMONR1: if (v1 & 0x04) { cs->dc.icc.mocr &= 0xf0; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); cs->dc.icc.mocr |= 0x0a; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); - sched_d_event(cs, D_RX_MON0); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); + schedule_event(cs, D_RX_MON0); } if (v1 & 0x40) { cs->dc.icc.mocr &= 0x0f; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); cs->dc.icc.mocr |= 0xa0; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); - sched_d_event(cs, D_RX_MON1); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); + schedule_event(cs, D_RX_MON1); } if (v1 & 0x02) { if ((!cs->dc.icc.mon_tx) || (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc) && !(v1 & 0x08))) { cs->dc.icc.mocr &= 0xf0; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); cs->dc.icc.mocr |= 0x0a; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) - sched_d_event(cs, D_TX_MON0); + schedule_event(cs, D_TX_MON0); goto AfterMOX0; } if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) { - sched_d_event(cs, D_TX_MON0); + schedule_event(cs, D_TX_MON0); goto AfterMOX0; } - icc_write_reg(cs, ICC_MOX0, + cs->writeisac(cs, ICC_MOX0, cs->dc.icc.mon_tx[cs->dc.icc.mon_txp++]); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ICC %02x -> MOX0", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp -1]); @@ -344,19 +407,19 @@ (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc) && !(v1 & 0x80))) { cs->dc.icc.mocr &= 0x0f; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); cs->dc.icc.mocr |= 0xa0; - icc_write_reg(cs, ICC_MOCR, cs->dc.icc.mocr); + cs->writeisac(cs, ICC_MOCR, cs->dc.icc.mocr); if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) - sched_d_event(cs, D_TX_MON1); + schedule_event(cs, D_TX_MON1); goto AfterMOX1; } if (cs->dc.icc.mon_txc && (cs->dc.icc.mon_txp >= cs->dc.icc.mon_txc)) { - sched_d_event(cs, D_TX_MON1); + schedule_event(cs, D_TX_MON1); goto AfterMOX1; } - icc_write_reg(cs, ICC_MOX1, + cs->writeisac(cs, ICC_MOX1, cs->dc.icc.mon_tx[cs->dc.icc.mon_txp++]); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ICC %02x -> MOX1", cs->dc.icc.mon_tx[cs->dc.icc.mon_txp -1]); @@ -372,35 +435,91 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; + u_long flags; int val; switch (pr) { case (PH_DATA |REQUEST): - xmit_data_req_d(cs, skb); + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + icc_fill_fifo(cs); + } + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL |INDICATION): - xmit_pull_ind_d(cs, skb); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + break; + } + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + icc_fill_fifo(cs); + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_d(st); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (HW_RESET | REQUEST): + spin_lock_irqsave(&cs->lock, flags); if ((cs->dc.icc.ph_state == ICC_IND_EI1) || (cs->dc.icc.ph_state == ICC_IND_DR)) ph_command(cs, ICC_CMD_DI); else ph_command(cs, ICC_CMD_RES); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_ENABLE | REQUEST): + spin_lock_irqsave(&cs->lock, flags); ph_command(cs, ICC_CMD_DI); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_INFO1 | REQUEST): + spin_lock_irqsave(&cs->lock, flags); ph_command(cs, ICC_CMD_AR); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_INFO3 | REQUEST): + spin_lock_irqsave(&cs->lock, flags); ph_command(cs, ICC_CMD_AI); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_TESTLOOP | REQUEST): + spin_lock_irqsave(&cs->lock, flags); val = 0; if (1 & (long) arg) val |= 0x0c; @@ -409,20 +528,21 @@ if (test_bit(HW_IOM1, &cs->HW_Flags)) { /* IOM 1 Mode */ if (!val) { - icc_write_reg(cs, ICC_SPCR, 0xa); - icc_write_reg(cs, ICC_ADF1, 0x2); + cs->writeisac(cs, ICC_SPCR, 0xa); + cs->writeisac(cs, ICC_ADF1, 0x2); } else { - icc_write_reg(cs, ICC_SPCR, val); - icc_write_reg(cs, ICC_ADF1, 0xa); + cs->writeisac(cs, ICC_SPCR, val); + cs->writeisac(cs, ICC_ADF1, 0xa); } } else { /* IOM 2 Mode */ - icc_write_reg(cs, ICC_SPCR, val); + cs->writeisac(cs, ICC_SPCR, val); if (val) - icc_write_reg(cs, ICC_ADF1, 0x8); + cs->writeisac(cs, ICC_ADF1, 0x8); else - icc_write_reg(cs, ICC_ADF1, 0x0); + cs->writeisac(cs, ICC_ADF1, 0x0); } + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_DEACTIVATE | RESPONSE): skb_queue_purge(&cs->rq); @@ -434,7 +554,7 @@ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); + schedule_event(cs, D_CLEARBUSY); break; default: if (cs->debug & L1_DEB_WARN) @@ -443,11 +563,10 @@ } } -static int +void setstack_icc(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = ICC_l1hw; - return 0; } void @@ -469,8 +588,8 @@ int rbch, star; if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { - rbch = icc_read_reg(cs, ICC_RBCH); - star = icc_read_reg(cs, ICC_STAR); + rbch = cs->readisac(cs, ICC_RBCH); + star = cs->readisac(cs, ICC_STAR); if (cs->debug) debugl1(cs, "D-Channel Busy RBCH %02x STAR %02x", rbch, star); @@ -478,7 +597,7 @@ test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); stptr = cs->stlist; while (stptr != NULL) { - L1L2(stptr, PH_PAUSE | INDICATION, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); stptr = stptr->next; } } else { @@ -492,77 +611,75 @@ printk(KERN_WARNING "HiSax: ICC D-Channel Busy no skb\n"); debugl1(cs, "D-Channel Busy no skb"); } - icc_write_reg(cs, ICC_CMDR, 0x01); /* Transmitter reset */ - cs->card_ops->irq_func(cs->irq, cs, NULL); /* FIXME? */ + cs->writeisac(cs, ICC_CMDR, 0x01); /* Transmitter reset */ + cs->irq_func(cs->irq, cs, NULL); } } } -static struct dc_l1_ops icc_l1_ops = { - .fill_fifo = icc_fill_fifo, - .open = setstack_icc, - .close = DC_Close_icc, - .bh_func = icc_bh, - .dbusy_func = dbusy_timer_handler, -}; - void __init initicc(struct IsdnCardState *cs) { - int val, eval; - - dc_l1_init(cs, &icc_l1_ops); + cs->setstack_d = setstack_icc; + cs->DC_Close = DC_Close_icc; cs->dc.icc.mon_tx = NULL; cs->dc.icc.mon_rx = NULL; + cs->writeisac(cs, ICC_MASK, 0xff); + cs->dc.icc.mocr = 0xaa; + if (test_bit(HW_IOM1, &cs->HW_Flags)) { + /* IOM 1 Mode */ + cs->writeisac(cs, ICC_ADF2, 0x0); + cs->writeisac(cs, ICC_SPCR, 0xa); + cs->writeisac(cs, ICC_ADF1, 0x2); + cs->writeisac(cs, ICC_STCR, 0x70); + cs->writeisac(cs, ICC_MODE, 0xc9); + } else { + /* IOM 2 Mode */ + if (!cs->dc.icc.adf2) + cs->dc.icc.adf2 = 0x80; + cs->writeisac(cs, ICC_ADF2, cs->dc.icc.adf2); + cs->writeisac(cs, ICC_SQXR, 0xa0); + cs->writeisac(cs, ICC_SPCR, 0x20); + cs->writeisac(cs, ICC_STCR, 0x70); + cs->writeisac(cs, ICC_MODE, 0xca); + cs->writeisac(cs, ICC_TIMR, 0x00); + cs->writeisac(cs, ICC_ADF1, 0x20); + } + ph_command(cs, ICC_CMD_RES); + cs->writeisac(cs, ICC_MASK, 0x0); + ph_command(cs, ICC_CMD_DI); +} + +void __init +clear_pending_icc_ints(struct IsdnCardState *cs) +{ + int val, eval; - val = icc_read_reg(cs, ICC_STAR); + val = cs->readisac(cs, ICC_STAR); debugl1(cs, "ICC STAR %x", val); - val = icc_read_reg(cs, ICC_MODE); + val = cs->readisac(cs, ICC_MODE); debugl1(cs, "ICC MODE %x", val); - val = icc_read_reg(cs, ICC_ADF2); + val = cs->readisac(cs, ICC_ADF2); debugl1(cs, "ICC ADF2 %x", val); - val = icc_read_reg(cs, ICC_ISTA); + val = cs->readisac(cs, ICC_ISTA); debugl1(cs, "ICC ISTA %x", val); if (val & 0x01) { - eval = icc_read_reg(cs, ICC_EXIR); + eval = cs->readisac(cs, ICC_EXIR); debugl1(cs, "ICC EXIR %x", eval); } - val = icc_read_reg(cs, ICC_CIR0); + val = cs->readisac(cs, ICC_CIR0); debugl1(cs, "ICC CIR0 %x", val); cs->dc.icc.ph_state = (val >> 2) & 0xf; - sched_d_event(cs, D_L1STATECHANGE); + schedule_event(cs, D_L1STATECHANGE); /* Disable all IRQ */ - icc_write_reg(cs, ICC_MASK, 0xFF); - - cs->dc.icc.mocr = 0xaa; - if (test_bit(HW_IOM1, &cs->HW_Flags)) { - /* IOM 1 Mode */ - icc_write_reg(cs, ICC_ADF2, 0x0); - icc_write_reg(cs, ICC_SPCR, 0xa); - icc_write_reg(cs, ICC_ADF1, 0x2); - icc_write_reg(cs, ICC_STCR, 0x70); - icc_write_reg(cs, ICC_MODE, 0xc9); - } else { - /* IOM 2 Mode */ - if (!cs->dc.icc.adf2) - cs->dc.icc.adf2 = 0x80; - icc_write_reg(cs, ICC_ADF2, cs->dc.icc.adf2); - icc_write_reg(cs, ICC_SQXR, 0xa0); - icc_write_reg(cs, ICC_SPCR, 0x20); - icc_write_reg(cs, ICC_STCR, 0x70); - icc_write_reg(cs, ICC_MODE, 0xca); - icc_write_reg(cs, ICC_TIMR, 0x00); - icc_write_reg(cs, ICC_ADF1, 0x20); - } - ph_command(cs, ICC_CMD_RES); - icc_write_reg(cs, ICC_MASK, 0x0); - ph_command(cs, ICC_CMD_DI); + cs->writeisac(cs, ICC_MASK, 0xFF); } -int -icc_setup(struct IsdnCardState *cs, struct dc_hw_ops *icc_ops) +void __devinit +setup_icc(struct IsdnCardState *cs) { - cs->dc_hw_ops = icc_ops; - ICCVersion(cs, "HiSax:"); - return 0; + INIT_WORK(&cs->tqueue, (void *)(void *) icc_bh, cs); + cs->dbusytimer.function = (void *) dbusy_timer_handler; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); } diff -Nru a/drivers/isdn/hisax/icc.h b/drivers/isdn/hisax/icc.h --- a/drivers/isdn/hisax/icc.h Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/hisax/icc.h Thu Feb 19 23:44:27 2004 @@ -1,4 +1,4 @@ -/* $Id: icc.h,v 1.2.6.3 2001/09/23 22:24:48 kai Exp $ +/* $Id: icc.h,v 1.4.2.2 2004/01/12 22:52:26 keil Exp $ * * ICC specific routines * @@ -65,6 +65,8 @@ #define ICC_IND_AIL 0xE #define ICC_IND_DC 0xF -extern int icc_setup(struct IsdnCardState *cs, struct dc_hw_ops *icc_ops); +extern void ICCVersion(struct IsdnCardState *cs, char *s); extern void initicc(struct IsdnCardState *cs); -extern void icc_interrupt(struct IsdnCardState *cs, u8 val); +extern void icc_interrupt(struct IsdnCardState *cs, u_char val); +extern void clear_pending_icc_ints(struct IsdnCardState *cs); +extern void setup_icc(struct IsdnCardState *); diff -Nru a/drivers/isdn/hisax/ipac.c b/drivers/isdn/hisax/ipac.c --- a/drivers/isdn/hisax/ipac.c Thu Feb 19 23:44:22 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,107 +0,0 @@ -#include "hisax.h" -#include "isdnl1.h" -#include "ipac.h" -#include "hscx.h" -#include "isac.h" - -static inline u8 -ipac_dc_read(struct IsdnCardState *cs, u8 addr) -{ - return cs->dc_hw_ops->read_reg(cs, addr); -} - -static inline void -ipac_dc_write(struct IsdnCardState *cs, u8 addr, u8 val) -{ - cs->dc_hw_ops->write_reg(cs, addr, val); -} - -static inline u8 -ipac_bc_read(struct IsdnCardState *cs, int hscx, u8 addr) -{ - return cs->bc_hw_ops->read_reg(cs, hscx, addr); -} - -static inline void -ipac_bc_write(struct IsdnCardState *cs, int hscx, u8 addr, u8 val) -{ - cs->bc_hw_ops->write_reg(cs, hscx, addr, val); -} - -static inline u8 -ipac_read(struct IsdnCardState *cs, u8 offset) -{ - return ipac_dc_read(cs, offset - 0x80); -} - -static inline void -ipac_write(struct IsdnCardState *cs, u8 offset, u8 value) -{ - ipac_dc_write(cs, offset - 0x80, value); -} - -void -ipac_init(struct IsdnCardState *cs) -{ - set_bit(HW_IPAC, &cs->HW_Flags); - inithscxisac(cs); -} - -irqreturn_t -ipac_irq(int intno, void *dev_id, struct pt_regs *regs) -{ - struct IsdnCardState *cs = dev_id; - u8 ista, val, icnt = 5; - - spin_lock(&cs->lock); - ista = ipac_read(cs, IPAC_ISTA); -Start_IPAC: - if (cs->debug & L1_DEB_IPAC) - debugl1(cs, "IPAC ISTA %02X", ista); - if (ista & 0x0f) { - val = ipac_bc_read(cs, 1, HSCX_ISTA); - if (ista & 0x01) - val |= 0x01; - if (ista & 0x04) - val |= 0x02; - if (ista & 0x08) - val |= 0x04; - if (val) - hscx_int_main(cs, val); - } - if (ista & 0x20) { - val = ipac_dc_read(cs, ISAC_ISTA) & 0xfe; - if (val) { - isac_interrupt(cs, val); - } - } - if (ista & 0x10) { - val = 0x01; - isac_interrupt(cs, val); - } - ista = ipac_read(cs, IPAC_ISTA); - if ((ista & 0x3f) && icnt) { - icnt--; - goto Start_IPAC; - } - if (!icnt) - printk(KERN_WARNING "IRQ LOOP\n"); - - ipac_write(cs, IPAC_MASK, 0xFF); - ipac_write(cs, IPAC_MASK, 0xC0); - spin_unlock(&cs->lock); - return IRQ_HANDLED; -} - -int -ipac_setup(struct IsdnCardState *cs, struct dc_hw_ops *ipac_dc_ops, - struct bc_hw_ops *ipac_bc_ops) -{ - u8 val; - - cs->dc_hw_ops = ipac_dc_ops; - cs->bc_hw_ops = ipac_bc_ops; - val = ipac_read(cs, IPAC_ID); - printk(KERN_INFO "HiSax: IPAC version %#x\n", val); - return 0; -} diff -Nru a/drivers/isdn/hisax/ipac.h b/drivers/isdn/hisax/ipac.h --- a/drivers/isdn/hisax/ipac.h Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/hisax/ipac.h Thu Feb 19 23:44:28 2004 @@ -1,4 +1,4 @@ -/* $Id: ipac.h,v 1.5.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: ipac.h,v 1.7.2.2 2004/01/12 22:52:26 keil Exp $ * * IPAC specific defines * @@ -10,8 +10,6 @@ * */ -#include - /* All Registers original Siemens Spec */ #define IPAC_CONF 0xC0 @@ -29,76 +27,3 @@ #define IPAC_PCFG 0xCA #define IPAC_SCFG 0xCB #define IPAC_TIMR2 0xCC - -void ipac_init(struct IsdnCardState *cs); -irqreturn_t ipac_irq(int intno, void *dev_id, struct pt_regs *regs); -int ipac_setup(struct IsdnCardState *cs, struct dc_hw_ops *ipac_dc_ops, - struct bc_hw_ops *ipac_bc_ops); - -/* Macro to build the needed D- and B-Channel access routines given - * access functions for the IPAC */ - -#define BUILD_IPAC_OPS(ipac) \ - \ -static u8 \ -ipac ## _dc_read(struct IsdnCardState *cs, u8 offset) \ -{ \ - return ipac ## _read(cs, offset+0x80); \ -} \ - \ -static void \ -ipac ## _dc_write(struct IsdnCardState *cs, u8 offset, u8 value) \ -{ \ - ipac ## _write(cs, offset+0x80, value); \ -} \ - \ -static void \ -ipac ## _dc_read_fifo(struct IsdnCardState *cs, u8 * data, int size) \ -{ \ - ipac ## _readfifo(cs, 0x80, data, size); \ -} \ - \ -static void \ -ipac ## _dc_write_fifo(struct IsdnCardState *cs, u8 * data, int size) \ -{ \ - ipac ## _writefifo(cs, 0x80, data, size); \ -} \ - \ -static struct dc_hw_ops ipac ## _dc_ops = { \ - .read_reg = ipac ## _dc_read, \ - .write_reg = ipac ## _dc_write, \ - .read_fifo = ipac ## _dc_read_fifo, \ - .write_fifo = ipac ## _dc_write_fifo, \ -}; \ - \ -static u8 \ -ipac ## _bc_read(struct IsdnCardState *cs, int hscx, u8 offset) \ -{ \ - return ipac ## _read(cs, offset + (hscx ? 0x40 : 0)); \ -} \ - \ -static void \ -ipac ## _bc_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) \ -{ \ - ipac ## _write(cs, offset + (hscx ? 0x40 : 0), value); \ -} \ - \ -static void \ -ipac ## _bc_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) \ -{ \ - ipac ## _readfifo(cs, hscx ? 0x40 : 0, data, size); \ -} \ - \ -static void \ -ipac ## _bc_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size)\ -{ \ - ipac ## _writefifo(cs, hscx ? 0x40 : 0, data, size); \ -} \ - \ -static struct bc_hw_ops ipac ## _bc_ops = { \ - .read_reg = ipac ## _bc_read, \ - .write_reg = ipac ## _bc_write, \ - .read_fifo = ipac ## _bc_read_fifo, \ - .write_fifo = ipac ## _bc_write_fifo, \ -} - diff -Nru a/drivers/isdn/hisax/ipacx.c b/drivers/isdn/hisax/ipacx.c --- a/drivers/isdn/hisax/ipacx.c Thu Feb 19 23:44:25 2004 +++ b/drivers/isdn/hisax/ipacx.c Thu Feb 19 23:44:25 2004 @@ -12,7 +12,6 @@ #include #include #include -#include #include "hisax_if.h" #include "hisax.h" #include "isdnl1.h" @@ -24,6 +23,7 @@ #define B_FIFO_SIZE 64 #define D_FIFO_SIZE 32 + // ipacx interrupt mask values #define _MASK_IMASK 0x2E // global mask #define _MASKB_IMASK 0x0B @@ -37,13 +37,16 @@ static void dch_l2l1(struct PStack *st, int pr, void *arg); static void dbusy_timer_handler(struct IsdnCardState *cs); static void ipacx_new_ph(struct IsdnCardState *cs); -static void dch_bh(void *data); +static void dch_bh(struct IsdnCardState *cs); static void dch_empty_fifo(struct IsdnCardState *cs, int count); static void dch_fill_fifo(struct IsdnCardState *cs); static inline void dch_int(struct IsdnCardState *cs); +static void __devinit dch_setstack(struct PStack *st, struct IsdnCardState *cs); +static void __devinit dch_init(struct IsdnCardState *cs); static void bch_l2l1(struct PStack *st, int pr, void *arg); -static void ipacx_bc_empty_fifo(struct BCState *bcs, int count); -static void bch_int(struct IsdnCardState *cs, u8 hscx); +static void bch_empty_fifo(struct BCState *bcs, int count); +static void bch_fill_fifo(struct BCState *bcs); +static void bch_int(struct IsdnCardState *cs, u_char hscx); static void bch_mode(struct BCState *bcs, int mode, int bc); static void bch_close_state(struct BCState *bcs); static int bch_open_state(struct IsdnCardState *cs, struct BCState *bcs); @@ -51,45 +54,6 @@ static void __devinit bch_init(struct IsdnCardState *cs, int hscx); static void __init clear_pending_ints(struct IsdnCardState *cs); -static inline u8 -ipacx_bc_read_reg(struct BCState *bcs, u8 addr) -{ - struct IsdnCardState *cs = bcs->cs; - - return cs->bc_hw_ops->read_reg(cs, bcs->unit, addr); -} - -static inline void -ipacx_bc_write_reg(struct BCState *bcs, u8 addr, u8 val) -{ - struct IsdnCardState *cs = bcs->cs; - - cs->bc_hw_ops->write_reg(cs, bcs->unit, addr, val); -} - -static inline u8 -ipacx_read_reg(struct IsdnCardState *cs, u8 addr) -{ - return cs->dc_hw_ops->read_reg(cs, addr); -} - -static inline void -ipacx_write_reg(struct IsdnCardState *cs, u8 addr, u8 val) -{ - cs->dc_hw_ops->write_reg(cs, addr, val); -} - -static inline void -ipacx_read_fifo(struct IsdnCardState *cs, u8 *p, int len) -{ - return cs->dc_hw_ops->read_fifo(cs, p, len); -} - -static inline void -ipacx_write_fifo(struct IsdnCardState *cs, u8 *p, int len) -{ - return cs->dc_hw_ops->write_fifo(cs, p, len); -} //---------------------------------------------------------- // Issue Layer 1 command to chip //---------------------------------------------------------- @@ -99,7 +63,10 @@ if (cs->debug &L1_DEB_ISAC) debugl1(cs, "ph_command (%#x) in (%#x)", command, cs->dc.isac.ph_state); - ipacx_write_reg(cs, IPACX_CIX0, (command << 4) | 0x0E); +//################################### +// printk(KERN_INFO "ph_command (%#x)\n", command); +//################################### + cs->writeisac(cs, IPACX_CIX0, (command << 4) | 0x0E); } //---------------------------------------------------------- @@ -108,12 +75,15 @@ static inline void cic_int(struct IsdnCardState *cs) { - u8 event; + u_char event; - event = ipacx_read_reg(cs, IPACX_CIR0) >> 4; + event = cs->readisac(cs, IPACX_CIR0) >> 4; if (cs->debug &L1_DEB_ISAC) debugl1(cs, "cic_int(event=%#x)", event); - cs->dc.isac.ph_state = event; - sched_d_event(cs, D_L1STATECHANGE); +//######################################### +// printk(KERN_INFO "cic_int(%x)\n", event); +//######################################### + cs->dc.isac.ph_state = event; + schedule_event(cs, D_L1STATECHANGE); } //========================================================== @@ -128,21 +98,63 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; - u8 cda1_cr, cda2_cr; + u_char cda1_cr, cda2_cr; switch (pr) { case (PH_DATA |REQUEST): - xmit_data_req_d(cs, skb); + if (cs->debug &DEB_DLOG_HEX) LogFrame(cs, skb->data, skb->len); + if (cs->debug &DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG + if (cs->debug &L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG + if (cs->debug &L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + dch_fill_fifo(cs); + } break; + case (PH_PULL |INDICATION): - xmit_pull_ind_d(cs, skb); + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + break; + } + if (cs->debug & DEB_DLOG_HEX) LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG + if (cs->debug & L1_DEB_LAPD) Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + dch_fill_fifo(cs); break; + case (PH_PULL | REQUEST): - xmit_pull_req_d(st); +#ifdef L2FRAME_DEBUG + if (cs->debug & L1_DEB_LAPD) debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; + case (HW_RESET | REQUEST): case (HW_ENABLE | REQUEST): - ph_command(cs, IPACX_CMD_TIM); + if ((cs->dc.isac.ph_state == IPACX_IND_RES) || + (cs->dc.isac.ph_state == IPACX_IND_DR) || + (cs->dc.isac.ph_state == IPACX_IND_DC)) + ph_command(cs, IPACX_CMD_TIM); + else + ph_command(cs, IPACX_CMD_RES); break; case (HW_INFO3 | REQUEST): @@ -150,21 +162,21 @@ break; case (HW_TESTLOOP | REQUEST): - ipacx_write_reg(cs, IPACX_CDA_TSDP10, 0x80); // Timeslot 0 is B1 - ipacx_write_reg(cs, IPACX_CDA_TSDP11, 0x81); // Timeslot 0 is B1 - cda1_cr = ipacx_read_reg(cs, IPACX_CDA1_CR); - cda2_cr = ipacx_read_reg(cs, IPACX_CDA2_CR); + cs->writeisac(cs, IPACX_CDA_TSDP10, 0x80); // Timeslot 0 is B1 + cs->writeisac(cs, IPACX_CDA_TSDP11, 0x81); // Timeslot 0 is B1 + cda1_cr = cs->readisac(cs, IPACX_CDA1_CR); + cda2_cr = cs->readisac(cs, IPACX_CDA2_CR); if ((long)arg &1) { // loop B1 - ipacx_write_reg(cs, IPACX_CDA1_CR, cda1_cr |0x0a); + cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr |0x0a); } else { // B1 off - ipacx_write_reg(cs, IPACX_CDA1_CR, cda1_cr &~0x0a); + cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr &~0x0a); } if ((long)arg &2) { // loop B2 - ipacx_write_reg(cs, IPACX_CDA1_CR, cda1_cr |0x14); + cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr |0x14); } else { // B2 off - ipacx_write_reg(cs, IPACX_CDA1_CR, cda1_cr &~0x14); + cs->writeisac(cs, IPACX_CDA1_CR, cda1_cr &~0x14); } break; @@ -194,14 +206,14 @@ int rbchd, stard; if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { - rbchd = ipacx_read_reg(cs, IPACX_RBCHD); - stard = ipacx_read_reg(cs, IPACX_STARD); + rbchd = cs->readisac(cs, IPACX_RBCHD); + stard = cs->readisac(cs, IPACX_STARD); if (cs->debug) debugl1(cs, "D-Channel Busy RBCHD %02x STARD %02x", rbchd, stard); if (!(stard &0x40)) { // D-Channel Busy set_bit(FLG_L1_DBUSY, &cs->HW_Flags); for (st = cs->stlist; st; st = st->next) { - st->l2.l1l2(st, PH_PAUSE | INDICATION, NULL); // flow control on + st->l1.l1l2(st, PH_PAUSE | INDICATION, NULL); // flow control on } } else { // seems we lost an interrupt; reset transceiver */ @@ -214,7 +226,7 @@ printk(KERN_WARNING "HiSax: ISAC D-Channel Busy no skb\n"); debugl1(cs, "D-Channel Busy no skb"); } - ipacx_write_reg(cs, IPACX_CMDRD, 0x01); // Tx reset, generates XPR + cs->writeisac(cs, IPACX_CMDRD, 0x01); // Tx reset, generates XPR } } } @@ -268,9 +280,8 @@ // bottom half handler for D channel //---------------------------------------------------------- static void -dch_bh(void *data) +dch_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; struct PStack *st; if (!cs) return; @@ -278,7 +289,7 @@ if (test_and_clear_bit(D_CLEARBUSY, &cs->event)) { if (cs->debug) debugl1(cs, "D-Channel Busy cleared"); for (st = cs->stlist; st; st = st->next) { - st->l2.l1l2(st, PH_PAUSE | CONFIRM, NULL); + st->l1.l1l2(st, PH_PAUSE | CONFIRM, NULL); } } @@ -301,8 +312,33 @@ static void dch_empty_fifo(struct IsdnCardState *cs, int count) { - recv_empty_fifo_d(cs, count); - ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC + u_char *ptr; + + if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO)) + debugl1(cs, "dch_empty_fifo()"); + + // message too large, remove + if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { + if (cs->debug &L1_DEB_WARN) + debugl1(cs, "dch_empty_fifo() incoming message too large"); + cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC + cs->rcvidx = 0; + return; + } + + ptr = cs->rcvbuf + cs->rcvidx; + cs->rcvidx += count; + + cs->readisacfifo(cs, ptr, count); + cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC + + if (cs->debug &L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "dch_empty_fifo() cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } } //---------------------------------------------------------- @@ -311,21 +347,28 @@ static void dch_fill_fifo(struct IsdnCardState *cs) { - int count, more; - unsigned char cmd, *p; + int count; + u_char cmd, *ptr; - p = xmit_fill_fifo_d(cs, 32, &count, &more); - if (!p) - return; + if ((cs->debug &L1_DEB_ISAC) && !(cs->debug &L1_DEB_ISAC_FIFO)) + debugl1(cs, "dch_fill_fifo()"); + + if (!cs->tx_skb) return; + count = cs->tx_skb->len; + if (count <= 0) return; - if (more) { + if (count > D_FIFO_SIZE) { + count = D_FIFO_SIZE; cmd = 0x08; // XTF } else { cmd = 0x0A; // XTF | XME } - ipacx_write_fifo(cs, p, count); - ipacx_write_reg(cs, IPACX_CMDRD, cmd); + ptr = cs->tx_skb->data; + skb_pull(cs->tx_skb, count); + cs->tx_cnt += count; + cs->writeisacfifo(cs, ptr, count); + cs->writeisac(cs, IPACX_CMDRD, cmd); // set timeout for transmission contol if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { @@ -335,6 +378,14 @@ init_timer(&cs->dbusytimer); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); add_timer(&cs->dbusytimer); + + if (cs->debug &L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "dch_fill_fifo() cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } } //---------------------------------------------------------- @@ -343,35 +394,46 @@ static inline void dch_int(struct IsdnCardState *cs) { - u8 istad, rstad; + struct sk_buff *skb; + u_char istad, rstad; int count; - istad = ipacx_read_reg(cs, IPACX_ISTAD); + istad = cs->readisac(cs, IPACX_ISTAD); +//############################################## +// printk(KERN_WARNING "dch_int(istad=%02x)\n", istad); +//############################################## if (istad &0x80) { // RME - rstad = ipacx_read_reg(cs, IPACX_RSTAD); + rstad = cs->readisac(cs, IPACX_RSTAD); if ((rstad &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB) if (!(rstad &0x80)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "dch_int(): invalid frame"); + debugl1(cs, "dch_int(): invalid frame"); if ((rstad &0x40)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "dch_int(): RDO"); + debugl1(cs, "dch_int(): RDO"); if (!(rstad &0x20)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "dch_int(): CRC error"); - ipacx_write_reg(cs, IPACX_CMDRD, 0x80); // RMC - cs->rcvidx = 0; + debugl1(cs, "dch_int(): CRC error"); + cs->writeisac(cs, IPACX_CMDRD, 0x80); // RMC } else { // received frame ok - count = ipacx_read_reg(cs, IPACX_RBCLD); - // FIXME this looks flaky - if (count) count--; // RSTAB is last byte + count = cs->readisac(cs, IPACX_RBCLD); + if (count) count--; // RSTAB is last byte count &= D_FIFO_SIZE-1; - if (count == 0) - count = D_FIFO_SIZE; + if (count == 0) count = D_FIFO_SIZE; dch_empty_fifo(cs, count); - recv_rme_d(cs); - } + if ((count = cs->rcvidx) > 0) { + cs->rcvidx = 0; + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "HiSax dch_int(): receive out of memory\n"); + else { + memcpy(skb_put(skb, count), cs->rcvbuf, count); + skb_queue_tail(&cs->rq, skb); + } + } + } + cs->rcvidx = 0; + schedule_event(cs, D_RCVBUFREADY); } if (istad &0x40) { // RPF @@ -380,34 +442,56 @@ if (istad &0x20) { // RFO if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_int(): RFO"); - ipacx_write_reg(cs, IPACX_CMDRD, 0x40); //RRES + cs->writeisac(cs, IPACX_CMDRD, 0x40); //RRES } - if (istad &0x10) { // XPR - xmit_xpr_d(cs); - } + if (istad &0x10) { // XPR + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + dch_fill_fifo(cs); + goto afterXPR; + } + else { + dev_kfree_skb_irq(cs->tx_skb); + cs->tx_skb = NULL; + cs->tx_cnt = 0; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + dch_fill_fifo(cs); + } + else { + schedule_event(cs, D_XMTBUFREADY); + } + } + afterXPR: if (istad &0x0C) { // XDU or XMR - xmit_xdu_d(cs, NULL); - } + if (cs->debug &L1_DEB_WARN) debugl1(cs, "dch_int(): XDU"); + if (cs->tx_skb) { + skb_push(cs->tx_skb, cs->tx_cnt); // retransmit + cs->tx_cnt = 0; + dch_fill_fifo(cs); + } else { + printk(KERN_WARNING "HiSax: ISAC XDU no skb\n"); + debugl1(cs, "ISAC XDU no skb"); + } + } } //---------------------------------------------------------- //---------------------------------------------------------- -static int +static void __devinit dch_setstack(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = dch_l2l1; - return 0; } -static struct dc_l1_ops ipacx_dc_l1_ops = { - .fill_fifo = dch_fill_fifo, - .open = dch_setstack, - .bh_func = dch_bh, - .dbusy_func = dbusy_timer_handler, -}; - //---------------------------------------------------------- //---------------------------------------------------------- static void __devinit @@ -415,12 +499,16 @@ { printk(KERN_INFO "HiSax: IPACX ISDN driver v0.1.0\n"); - dc_l1_init(cs, &ipacx_dc_l1_ops); + cs->setstack_d = dch_setstack; + + cs->dbusytimer.function = (void *) dbusy_timer_handler; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); - ipacx_write_reg(cs, IPACX_TR_CONF0, 0x00); // clear LDD - ipacx_write_reg(cs, IPACX_TR_CONF2, 0x00); // enable transmitter - ipacx_write_reg(cs, IPACX_MODED, 0xC9); // transparent mode 0, RAC, stop/go - ipacx_write_reg(cs, IPACX_MON_CR, 0x00); // disable monitor channel + cs->writeisac(cs, IPACX_TR_CONF0, 0x00); // clear LDD + cs->writeisac(cs, IPACX_TR_CONF2, 0x00); // enable transmitter + cs->writeisac(cs, IPACX_MODED, 0xC9); // transparent mode 0, RAC, stop/go + cs->writeisac(cs, IPACX_MON_CR, 0x00); // disable monitor channel } @@ -434,31 +522,59 @@ static void bch_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; + set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->hw.hscx.count = 0; + bch_fill_fifo(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "HiSax bch_l2l1(): this shouldn't happen\n"); + } else { + set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->hw.hscx.count = 0; + bch_fill_fifo(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - bch_mode(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + set_bit(BC_FLG_ACTIV, &bcs->Flag); + bch_mode(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - bch_mode(st->l1.bcs, 0, st->l1.bc); - st->l2.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + clear_bit(BC_FLG_ACTIV, &bcs->Flag); + clear_bit(BC_FLG_BUSY, &bcs->Flag); + bch_mode(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -467,94 +583,204 @@ // Read B channel fifo to receive buffer //---------------------------------------------------------- static void -ipacx_bc_empty_fifo(struct BCState *bcs, int count) +bch_empty_fifo(struct BCState *bcs, int count) { - recv_empty_fifo_b(bcs, count); - ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC + u_char *ptr, hscx; + struct IsdnCardState *cs; + int cnt; + + cs = bcs->cs; + hscx = bcs->hw.hscx.hscx; + if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO)) + debugl1(cs, "bch_empty_fifo()"); + + // message too large, remove + if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug &L1_DEB_WARN) + debugl1(cs, "bch_empty_fifo() incoming packet too large"); + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC + bcs->hw.hscx.rcvidx = 0; + return; + } + + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + cnt = count; + while (cnt--) *ptr++ = cs->BC_Read_Reg(cs, hscx, IPACX_RFIFOB); + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC + + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + bcs->hw.hscx.rcvidx += count; + + if (cs->debug &L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "bch_empty_fifo() B-%d cnt %d", hscx, count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } //---------------------------------------------------------- // Fill buffer to transmit FIFO //---------------------------------------------------------- static void -ipacx_bc_fill_fifo(struct BCState *bcs) +bch_fill_fifo(struct BCState *bcs) { - int more, count; - unsigned char *p; - - p = xmit_fill_fifo_b(bcs, B_FIFO_SIZE, &count, &more); - if (!p) - return; - - while (count--) - ipacx_bc_write_reg(bcs, IPACX_XFIFOB, *p++); - - ipacx_bc_write_reg(bcs, IPACX_CMDRB, (more ? 0x08 : 0x0a)); + struct IsdnCardState *cs; + int more, count, cnt; + u_char *ptr, *p, hscx; + + cs = bcs->cs; + if ((cs->debug &L1_DEB_HSCX) && !(cs->debug &L1_DEB_HSCX_FIFO)) + debugl1(cs, "bch_fill_fifo()"); + + if (!bcs->tx_skb) return; + if (bcs->tx_skb->len <= 0) return; + + hscx = bcs->hw.hscx.hscx; + more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; + if (bcs->tx_skb->len > B_FIFO_SIZE) { + more = 1; + count = B_FIFO_SIZE; + } else { + count = bcs->tx_skb->len; + } + cnt = count; + + p = ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.hscx.count += count; + while (cnt--) cs->BC_Write_Reg(cs, hscx, IPACX_XFIFOB, *p++); + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, (more ? 0x08 : 0x0a)); + + if (cs->debug &L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "chb_fill_fifo() B-%d cnt %d", hscx, count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } //---------------------------------------------------------- // B channel interrupt handler //---------------------------------------------------------- - -static void -reset_xmit(struct BCState *bcs) -{ - ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x01); // XRES -} - static void -bch_int(struct IsdnCardState *cs, u8 hscx) +bch_int(struct IsdnCardState *cs, u_char hscx) { - u8 istab; + u_char istab; struct BCState *bcs; + struct sk_buff *skb; int count; - u8 rstab; + u_char rstab; bcs = cs->bcs + hscx; - istab = ipacx_bc_read_reg(bcs, IPACX_ISTAB); + istab = cs->BC_Read_Reg(cs, hscx, IPACX_ISTAB); +//############################################## +// printk(KERN_WARNING "bch_int(istab=%02x)\n", istab); +//############################################## if (!test_bit(BC_FLG_INIT, &bcs->Flag)) return; if (istab &0x80) { // RME - rstab = ipacx_bc_read_reg(bcs, IPACX_RSTAB); + rstab = cs->BC_Read_Reg(cs, hscx, IPACX_RSTAB); if ((rstab &0xf0) != 0xa0) { // !(VFR && !RDO && CRC && !RAB) if (!(rstab &0x80)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "bch_int() B-%d: invalid frame", hscx); + debugl1(cs, "bch_int() B-%d: invalid frame", hscx); if ((rstab &0x40) && (bcs->mode != L1_MODE_NULL)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "bch_int() B-%d: RDO mode=%d", hscx, bcs->mode); + debugl1(cs, "bch_int() B-%d: RDO mode=%d", hscx, bcs->mode); if (!(rstab &0x20)) if (cs->debug &L1_DEB_WARN) - debugl1(cs, "bch_int() B-%d: CRC error", hscx); - ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x80); // RMC - bcs->rcvidx = 0; - } else { // received frame ok - count = ipacx_bc_read_reg(bcs, IPACX_RBCLB) &(B_FIFO_SIZE-1); - if (count == 0) - count = B_FIFO_SIZE; - - ipacx_bc_empty_fifo(bcs, count); - recv_rme_b(bcs); + debugl1(cs, "bch_int() B-%d: CRC error", hscx); + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x80); // RMC + } + else { // received frame ok + count = cs->BC_Read_Reg(cs, hscx, IPACX_RBCLB) &(B_FIFO_SIZE-1); + if (count == 0) count = B_FIFO_SIZE; + bch_empty_fifo(bcs, count); + if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { + if (cs->debug &L1_DEB_HSCX_FIFO) + debugl1(cs, "bch_int Frame %d", count); + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "HiSax bch_int(): receive frame out of memory\n"); + else { + memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); + skb_queue_tail(&bcs->rqueue, skb); + } + } } + bcs->hw.hscx.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); } if (istab &0x40) { // RPF - ipacx_bc_empty_fifo(bcs, B_FIFO_SIZE); - recv_rpf_b(bcs); + bch_empty_fifo(bcs, B_FIFO_SIZE); + + if (bcs->mode == L1_MODE_TRANS) { // queue every chunk + // receive transparent audio data + if (!(skb = dev_alloc_skb(B_FIFO_SIZE))) + printk(KERN_WARNING "HiSax bch_int(): receive transparent out of memory\n"); + else { + memcpy(skb_put(skb, B_FIFO_SIZE), bcs->hw.hscx.rcvbuf, B_FIFO_SIZE); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.hscx.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); + } } if (istab &0x20) { // RFO if (cs->debug &L1_DEB_WARN) debugl1(cs, "bch_int() B-%d: RFO error", hscx); - ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x40); // RRES + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x40); // RRES } if (istab &0x10) { // XPR - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + bch_fill_fifo(bcs); + goto afterXPR; + } else { + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hscx.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + } + dev_kfree_skb_irq(bcs->tx_skb); + bcs->hw.hscx.count = 0; + bcs->tx_skb = NULL; + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hscx.count = 0; + set_bit(BC_FLG_BUSY, &bcs->Flag); + bch_fill_fifo(bcs); + } else { + clear_bit(BC_FLG_BUSY, &bcs->Flag); + schedule_event(bcs, B_XMTBUFREADY); + } } + afterXPR: if (istab &0x04) { // XDU - xmit_xdu_b(bcs, reset_xmit); + if (bcs->mode == L1_MODE_TRANS) { + bch_fill_fifo(bcs); + } + else { + if (bcs->tx_skb) { // restart transmitting the whole frame + skb_push(bcs->tx_skb, bcs->hw.hscx.count); + bcs->tx_cnt += bcs->hw.hscx.count; + bcs->hw.hscx.count = 0; + } + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x01); // XRES + if (cs->debug &L1_DEB_WARN) + debugl1(cs, "bch_int() B-%d XDU error", hscx); + } } } @@ -564,7 +790,7 @@ bch_mode(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - int hscx = bcs->unit; + int hscx = bcs->hw.hscx.hscx; bc = bc ? 1 : 0; // in case bc is greater than 1 if (cs->debug & L1_DEB_HSCX) @@ -575,33 +801,33 @@ // map controller to according timeslot if (!hscx) { - ipacx_write_reg(cs, IPACX_BCHA_TSDP_BC1, 0x80 | bc); - ipacx_write_reg(cs, IPACX_BCHA_CR, 0x88); + cs->writeisac(cs, IPACX_BCHA_TSDP_BC1, 0x80 | bc); + cs->writeisac(cs, IPACX_BCHA_CR, 0x88); } else { - ipacx_write_reg(cs, IPACX_BCHB_TSDP_BC1, 0x80 | bc); - ipacx_write_reg(cs, IPACX_BCHB_CR, 0x88); + cs->writeisac(cs, IPACX_BCHB_TSDP_BC1, 0x80 | bc); + cs->writeisac(cs, IPACX_BCHB_CR, 0x88); } switch (mode) { case (L1_MODE_NULL): - ipacx_bc_write_reg(bcs, IPACX_MODEB, 0xC0); // rec off - ipacx_bc_write_reg(bcs, IPACX_EXMB, 0x30); // std adj. - ipacx_bc_write_reg(bcs, IPACX_MASKB, 0xFF); // ints off - ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x41); // validate adjustments + cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0xC0); // rec off + cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x30); // std adj. + cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, 0xFF); // ints off + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments break; case (L1_MODE_TRANS): - ipacx_bc_write_reg(bcs, IPACX_MODEB, 0x88); // ext transp mode - ipacx_bc_write_reg(bcs, IPACX_EXMB, 0x00); // xxx00000 - ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x41); // validate adjustments - ipacx_bc_write_reg(bcs, IPACX_MASKB, _MASKB_IMASK); + cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0x88); // ext transp mode + cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x00); // xxx00000 + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments + cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, _MASKB_IMASK); break; case (L1_MODE_HDLC): - ipacx_bc_write_reg(bcs, IPACX_MODEB, 0xC8); // transp mode 0 - ipacx_bc_write_reg(bcs, IPACX_EXMB, 0x01); // idle=hdlc flags crc enabled - ipacx_bc_write_reg(bcs, IPACX_CMDRB, 0x41); // validate adjustments - ipacx_bc_write_reg(bcs, IPACX_MASKB, _MASKB_IMASK); + cs->BC_Write_Reg(cs, hscx, IPACX_MODEB, 0xC8); // transp mode 0 + cs->BC_Write_Reg(cs, hscx, IPACX_EXMB, 0x01); // idle=hdlc flags crc enabled + cs->BC_Write_Reg(cs, hscx, IPACX_CMDRB, 0x41); // validate adjustments + cs->BC_Write_Reg(cs, hscx, IPACX_MASKB, _MASKB_IMASK); break; } } @@ -612,7 +838,23 @@ bch_close_state(struct BCState *bcs) { bch_mode(bcs, 0, bcs->channel); - bc_close(bcs); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.hscx.rcvbuf) { + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + } + if (bcs->blog) { + kfree(bcs->blog); + bcs->blog = NULL; + } + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); + if (bcs->tx_skb) { + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } } //---------------------------------------------------------- @@ -620,7 +862,30 @@ static int bch_open_state(struct IsdnCardState *cs, struct BCState *bcs) { - return bc_open(bcs); + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax open_bchstate(): No memory for hscx.rcvbuf\n"); + clear_bit(BC_FLG_INIT, &bcs->Flag); + return (1); + } + if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax open_bchstate: No memory for bcs->blog\n"); + clear_bit(BC_FLG_INIT, &bcs->Flag); + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + return (2); + } + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } + bcs->tx_skb = NULL; + clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->event = 0; + bcs->hw.hscx.rcvidx = 0; + bcs->tx_cnt = 0; + return (0); } //---------------------------------------------------------- @@ -631,7 +896,7 @@ bcs->channel = st->l1.bc; if (bch_open_state(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = bch_l2l1; + st->l2.l2l1 = bch_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); @@ -643,7 +908,9 @@ static void __devinit bch_init(struct IsdnCardState *cs, int hscx) { - cs->bcs[hscx].unit = hscx; + cs->bcs[hscx].BC_SetStack = bch_setstack; + cs->bcs[hscx].BC_Close = bch_close_state; + cs->bcs[hscx].hw.hscx.hscx = hscx; cs->bcs[hscx].cs = cs; bch_mode(cs->bcs + hscx, 0, hscx); } @@ -659,16 +926,18 @@ void interrupt_ipacx(struct IsdnCardState *cs) { - u8 ista; - - spin_lock(&cs->lock); - while ((ista = ipacx_read_reg(cs, IPACX_ISTA))) { - if (ista &0x80) bch_int(cs, 0); // B channel interrupts - if (ista &0x40) bch_int(cs, 1); - if (ista &0x01) dch_int(cs); // D channel - if (ista &0x10) cic_int(cs); // Layer 1 state - } - spin_unlock(&cs->lock); + u_char ista; + + while ((ista = cs->readisac(cs, IPACX_ISTA))) { +//################################################# +// printk(KERN_WARNING "interrupt_ipacx(ista=%02x)\n", ista); +//################################################# + if (ista &0x80) bch_int(cs, 0); // B channel interrupts + if (ista &0x40) bch_int(cs, 1); + + if (ista &0x01) dch_int(cs); // D channel + if (ista &0x10) cic_int(cs); // Layer 1 state + } } //---------------------------------------------------------- @@ -680,23 +949,17 @@ int ista; // all interrupts off - ipacx_write_reg(cs, IPACX_MASK, 0xff); - ipacx_write_reg(cs, IPACX_MASKD, 0xff); - cs->bc_hw_ops->write_reg(cs, 0, IPACX_MASKB, 0xff); - cs->bc_hw_ops->write_reg(cs, 1, IPACX_MASKB, 0xff); - - ista = ipacx_read_reg(cs, IPACX_ISTA); - if (ista &0x80) cs->bc_hw_ops->read_reg(cs, 0, IPACX_ISTAB); - if (ista &0x40) cs->bc_hw_ops->read_reg(cs, 1, IPACX_ISTAB); - if (ista &0x10) ipacx_read_reg(cs, IPACX_CIR0); - if (ista &0x01) ipacx_read_reg(cs, IPACX_ISTAD); -} - -static struct bc_l1_ops ipacx_bc_l1_ops = { - .fill_fifo = ipacx_bc_fill_fifo, - .open = bch_setstack, - .close = bch_close_state, -}; + cs->writeisac(cs, IPACX_MASK, 0xff); + cs->writeisac(cs, IPACX_MASKD, 0xff); + cs->BC_Write_Reg(cs, 0, IPACX_MASKB, 0xff); + cs->BC_Write_Reg(cs, 1, IPACX_MASKB, 0xff); + + ista = cs->readisac(cs, IPACX_ISTA); + if (ista &0x80) cs->BC_Read_Reg(cs, 0, IPACX_ISTAB); + if (ista &0x40) cs->BC_Read_Reg(cs, 1, IPACX_ISTAB); + if (ista &0x10) cs->readisac(cs, IPACX_CIR0); + if (ista &0x01) cs->readisac(cs, IPACX_ISTAD); +} //---------------------------------------------------------- // Does chip configuration work @@ -706,36 +969,36 @@ init_ipacx(struct IsdnCardState *cs, int part) { if (part &1) { // initialise chip - cs->bc_l1_ops = &ipacx_bc_l1_ops; +//################################################## +// printk(KERN_INFO "init_ipacx(%x)\n", part); +//################################################## clear_pending_ints(cs); bch_init(cs, 0); bch_init(cs, 1); dch_init(cs); } if (part &2) { // reenable all interrupts and start chip - cs->bc_hw_ops->write_reg(cs, 0, IPACX_MASKB, _MASKB_IMASK); - cs->bc_hw_ops->write_reg(cs, 1, IPACX_MASKB, _MASKB_IMASK); - ipacx_write_reg(cs, IPACX_MASKD, _MASKD_IMASK); - ipacx_write_reg(cs, IPACX_MASK, _MASK_IMASK); // global mask register - - // reset HDLC Transmitters/receivers - ipacx_write_reg(cs, IPACX_CMDRD, 0x41); - cs->bc_hw_ops->write_reg(cs, 0, IPACX_CMDRB, 0x41); - cs->bc_hw_ops->write_reg(cs, 1, IPACX_CMDRB, 0x41); + cs->BC_Write_Reg(cs, 0, IPACX_MASKB, _MASKB_IMASK); + cs->BC_Write_Reg(cs, 1, IPACX_MASKB, _MASKB_IMASK); + cs->writeisac(cs, IPACX_MASKD, _MASKD_IMASK); + cs->writeisac(cs, IPACX_MASK, _MASK_IMASK); // global mask register + + // reset HDLC Transmitters/receivers + cs->writeisac(cs, IPACX_CMDRD, 0x41); + cs->BC_Write_Reg(cs, 0, IPACX_CMDRB, 0x41); + cs->BC_Write_Reg(cs, 1, IPACX_CMDRB, 0x41); ph_command(cs, IPACX_CMD_RES); } } -int -ipacx_setup(struct IsdnCardState *cs, struct dc_hw_ops *ipacx_dc_ops, - struct bc_hw_ops *ipacx_bc_ops) -{ - u8 val; - - cs->dc_hw_ops = ipacx_dc_ops; - cs->bc_hw_ops = ipacx_bc_ops; - val = ipacx_read_reg(cs, IPACX_ID) & 0x3f; - printk(KERN_INFO "HiSax: IPACX Design Id: %#x\n", val); - return 0; + +void __devinit +setup_ipacx(struct IsdnCardState *cs) +{ + INIT_WORK(&cs->tqueue, (void *)(void *) dch_bh, cs); + cs->dbusytimer.function = (void *) dbusy_timer_handler; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); } +//----------------- end of file ----------------------- diff -Nru a/drivers/isdn/hisax/ipacx.h b/drivers/isdn/hisax/ipacx.h --- a/drivers/isdn/hisax/ipacx.h Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/ipacx.h Thu Feb 19 23:44:23 2004 @@ -155,10 +155,8 @@ #define IPACX_IND_AIL 0xe #define IPACX_IND_DC 0xf -extern void init_ipacx(struct IsdnCardState *cs, int part); -extern void interrupt_ipacx(struct IsdnCardState *cs); -extern int ipacx_setup(struct IsdnCardState *cs, - struct dc_hw_ops *ipacx_dc_ops, - struct bc_hw_ops *ipacx_bc_ops); +extern void init_ipacx(struct IsdnCardState *, int); +extern void interrupt_ipacx(struct IsdnCardState *); +extern void setup_isac(struct IsdnCardState *); #endif diff -Nru a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c --- a/drivers/isdn/hisax/isac.c Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/isac.c Thu Feb 19 23:44:23 2004 @@ -1,4 +1,4 @@ -/* $Id: isac.c,v 1.28.6.3 2001/09/23 22:24:49 kai Exp $ +/* $Id: isac.c,v 1.31.2.3 2004/01/13 14:31:25 keil Exp $ * * ISAC specific routines * @@ -27,30 +27,12 @@ {"2086/2186 V1.1", "2085 B1", "2085 B2", "2085 V2.3"}; -static inline u8 -isac_read(struct IsdnCardState *cs, u8 addr) -{ - return cs->dc_hw_ops->read_reg(cs, addr); -} - -static inline void -isac_write(struct IsdnCardState *cs, u8 addr, u8 val) -{ - cs->dc_hw_ops->write_reg(cs, addr, val); -} - -static inline void -isac_write_fifo(struct IsdnCardState *cs, u8 *p, int len) -{ - return cs->dc_hw_ops->write_fifo(cs, p, len); -} - -static void +void ISACVersion(struct IsdnCardState *cs, char *s) { int val; - val = isac_read(cs, ISAC_RBCH); + val = cs->readisac(cs, ISAC_RBCH); printk(KERN_INFO "%s ISAC version (%x): %s\n", s, val, ISACVer[(val >> 5) & 3]); } @@ -59,7 +41,7 @@ { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_command %x", command); - isac_write(cs, ISAC_CIX0, (command << 2) | 3); + cs->writeisac(cs, ISAC_CIX0, (command << 2) | 3); } @@ -99,9 +81,8 @@ } static void -isac_bh(void *data) +isac_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; struct PStack *stptr; if (!cs) @@ -111,7 +92,7 @@ debugl1(cs, "D-Channel Busy cleared"); stptr = cs->stlist; while (stptr != NULL) { - L1L2(stptr, PH_PAUSE | CONFIRM, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); stptr = stptr->next; } } @@ -134,22 +115,58 @@ void isac_empty_fifo(struct IsdnCardState *cs, int count) { - recv_empty_fifo_d(cs, count); - isac_write(cs, ISAC_CMDR, 0x80); + u_char *ptr; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, "isac_empty_fifo"); + + if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "isac_empty_fifo overrun %d", + cs->rcvidx + count); + cs->writeisac(cs, ISAC_CMDR, 0x80); + cs->rcvidx = 0; + return; + } + ptr = cs->rcvbuf + cs->rcvidx; + cs->rcvidx += count; + cs->readisacfifo(cs, ptr, count); + cs->writeisac(cs, ISAC_CMDR, 0x80); + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "isac_empty_fifo cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } } static void isac_fill_fifo(struct IsdnCardState *cs) { int count, more; - unsigned char *p; + u_char *ptr; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, "isac_fill_fifo"); + + if (!cs->tx_skb) + return; - p = xmit_fill_fifo_d(cs, 32, &count, &more); - if (!p) + count = cs->tx_skb->len; + if (count <= 0) return; - isac_write_fifo(cs, p, count); - isac_write(cs, ISAC_CMDR, more ? 0x8 : 0xa); + more = 0; + if (count > 32) { + more = !0; + count = 32; + } + ptr = cs->tx_skb->data; + skb_pull(cs->tx_skb, count); + cs->tx_cnt += count; + cs->writeisacfifo(cs, ptr, count); + cs->writeisac(cs, ISAC_CMDR, more ? 0x8 : 0xa); if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { debugl1(cs, "isac_fill_fifo dbusytimer running"); del_timer(&cs->dbusytimer); @@ -157,18 +174,26 @@ init_timer(&cs->dbusytimer); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ)/1000); add_timer(&cs->dbusytimer); + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "isac_fill_fifo cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } } void -isac_interrupt(struct IsdnCardState *cs, u8 val) +isac_interrupt(struct IsdnCardState *cs, u_char val) { - u8 exval, v1; + u_char exval, v1; + struct sk_buff *skb; unsigned int count; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ISAC interrupt %x", val); if (val & 0x80) { /* RME */ - exval = isac_read(cs, ISAC_RSTA); + exval = cs->readisac(cs, ISAC_RSTA); if ((exval & 0x70) != 0x20) { if (exval & 0x40) { if (cs->debug & L1_DEB_WARN) @@ -184,17 +209,24 @@ cs->err_crc++; #endif } - isac_write(cs, ISAC_CMDR, 0x80); - cs->rcvidx = 0; + cs->writeisac(cs, ISAC_CMDR, 0x80); } else { - count = isac_read(cs, ISAC_RBCL) & 0x1f; + count = cs->readisac(cs, ISAC_RBCL) & 0x1f; if (count == 0) count = 32; isac_empty_fifo(cs, count); - recv_rme_d(cs); + if ((count = cs->rcvidx) > 0) { + cs->rcvidx = 0; + if (!(skb = alloc_skb(count, GFP_ATOMIC))) + printk(KERN_WARNING "HiSax: D receive out of memory\n"); + else { + memcpy(skb_put(skb, count), cs->rcvbuf, count); + skb_queue_tail(&cs->rq, skb); + } + } } cs->rcvidx = 0; - sched_d_event(cs, D_RCVBUFREADY); + schedule_event(cs, D_RCVBUFREADY); } if (val & 0x40) { /* RPF */ isac_empty_fifo(cs, 32); @@ -205,20 +237,39 @@ debugl1(cs, "ISAC RSC interrupt"); } if (val & 0x10) { /* XPR */ - xmit_xpr_d(cs); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + isac_fill_fifo(cs); + goto afterXPR; + } else { + dev_kfree_skb_irq(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + isac_fill_fifo(cs); + } else + schedule_event(cs, D_XMTBUFREADY); } + afterXPR: if (val & 0x04) { /* CISQ */ - exval = isac_read(cs, ISAC_CIR0); + exval = cs->readisac(cs, ISAC_CIR0); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ISAC CIR0 %02X", exval ); if (exval & 2) { cs->dc.isac.ph_state = (exval >> 2) & 0xf; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_state change %x", cs->dc.isac.ph_state); - sched_d_event(cs, D_L1STATECHANGE); + schedule_event(cs, D_L1STATECHANGE); } if (exval & 1) { - exval = isac_read(cs, ISAC_CIR1); + exval = cs->readisac(cs, ISAC_CIR1); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ISAC CIR1 %02X", exval ); } @@ -229,7 +280,7 @@ debugl1(cs, "ISAC SIN interrupt"); } if (val & 0x01) { /* EXI */ - exval = isac_read(cs, ISAC_EXIR); + exval = cs->readisac(cs, ISAC_EXIR); if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC EXIR %02x", exval); if (exval & 0x80) { /* XMR */ @@ -237,10 +288,26 @@ printk(KERN_WARNING "HiSax: ISAC XMR\n"); } if (exval & 0x40) { /* XDU */ - xmit_xdu_d(cs, NULL); + debugl1(cs, "ISAC XDU"); + printk(KERN_WARNING "HiSax: ISAC XDU\n"); +#ifdef ERROR_STATISTIC + cs->err_tx++; +#endif + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { /* Restart frame */ + skb_push(cs->tx_skb, cs->tx_cnt); + cs->tx_cnt = 0; + isac_fill_fifo(cs); + } else { + printk(KERN_WARNING "HiSax: ISAC XDU no skb\n"); + debugl1(cs, "ISAC XDU no skb"); + } } if (exval & 0x04) { /* MOS */ - v1 = isac_read(cs, ISAC_MOSR); + v1 = cs->readisac(cs, ISAC_MOSR); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ISAC MOSR %02x", v1); #if ARCOFI_USE @@ -251,7 +318,7 @@ debugl1(cs, "ISAC MON RX out of memory!"); cs->dc.isac.mocr &= 0xf0; cs->dc.isac.mocr |= 0x0a; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); goto afterMONR0; } else cs->dc.isac.mon_rxp = 0; @@ -259,18 +326,18 @@ if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) { cs->dc.isac.mocr &= 0xf0; cs->dc.isac.mocr |= 0x0a; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); cs->dc.isac.mon_rxp = 0; if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC MON RX overflow!"); goto afterMONR0; } - cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = isac_read(cs, ISAC_MOR0); + cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = cs->readisac(cs, ISAC_MOR0); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ISAC MOR0 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp -1]); if (cs->dc.isac.mon_rxp == 1) { cs->dc.isac.mocr |= 0x04; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); } } afterMONR0: @@ -281,7 +348,7 @@ debugl1(cs, "ISAC MON RX out of memory!"); cs->dc.isac.mocr &= 0x0f; cs->dc.isac.mocr |= 0xa0; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); goto afterMONR1; } else cs->dc.isac.mon_rxp = 0; @@ -289,51 +356,51 @@ if (cs->dc.isac.mon_rxp >= MAX_MON_FRAME) { cs->dc.isac.mocr &= 0x0f; cs->dc.isac.mocr |= 0xa0; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); cs->dc.isac.mon_rxp = 0; if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC MON RX overflow!"); goto afterMONR1; } - cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = isac_read(cs, ISAC_MOR1); + cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp++] = cs->readisac(cs, ISAC_MOR1); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ISAC MOR1 %02x", cs->dc.isac.mon_rx[cs->dc.isac.mon_rxp -1]); cs->dc.isac.mocr |= 0x40; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); } afterMONR1: if (v1 & 0x04) { cs->dc.isac.mocr &= 0xf0; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); cs->dc.isac.mocr |= 0x0a; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); - sched_d_event(cs, D_RX_MON0); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); + schedule_event(cs, D_RX_MON0); } if (v1 & 0x40) { cs->dc.isac.mocr &= 0x0f; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); cs->dc.isac.mocr |= 0xa0; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); - sched_d_event(cs, D_RX_MON1); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); + schedule_event(cs, D_RX_MON1); } if (v1 & 0x02) { if ((!cs->dc.isac.mon_tx) || (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) && !(v1 & 0x08))) { cs->dc.isac.mocr &= 0xf0; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); cs->dc.isac.mocr |= 0x0a; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) - sched_d_event(cs, D_TX_MON0); + schedule_event(cs, D_TX_MON0); goto AfterMOX0; } if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) { - sched_d_event(cs, D_TX_MON0); + schedule_event(cs, D_TX_MON0); goto AfterMOX0; } - isac_write(cs, ISAC_MOX0, + cs->writeisac(cs, ISAC_MOX0, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ISAC %02x -> MOX0", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp -1]); @@ -344,19 +411,19 @@ (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc) && !(v1 & 0x80))) { cs->dc.isac.mocr &= 0x0f; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); cs->dc.isac.mocr |= 0xa0; - isac_write(cs, ISAC_MOCR, cs->dc.isac.mocr); + cs->writeisac(cs, ISAC_MOCR, cs->dc.isac.mocr); if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) - sched_d_event(cs, D_TX_MON1); + schedule_event(cs, D_TX_MON1); goto AfterMOX1; } if (cs->dc.isac.mon_txc && (cs->dc.isac.mon_txp >= cs->dc.isac.mon_txc)) { - sched_d_event(cs, D_TX_MON1); + schedule_event(cs, D_TX_MON1); goto AfterMOX1; } - isac_write(cs, ISAC_MOX1, + cs->writeisac(cs, ISAC_MOX1, cs->dc.isac.mon_tx[cs->dc.isac.mon_txp++]); if (cs->debug & L1_DEB_MONITOR) debugl1(cs, "ISAC %02x -> MOX1", cs->dc.isac.mon_tx[cs->dc.isac.mon_txp -1]); @@ -372,33 +439,87 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; + u_long flags; int val; switch (pr) { case (PH_DATA |REQUEST): - xmit_data_req_d(cs, skb); + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + isac_fill_fifo(cs); + } + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL |INDICATION): - xmit_pull_ind_d(cs, skb); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + } else { + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + isac_fill_fifo(cs); + } + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_d(st); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (HW_RESET | REQUEST): + spin_lock_irqsave(&cs->lock, flags); if ((cs->dc.isac.ph_state == ISAC_IND_EI) || (cs->dc.isac.ph_state == ISAC_IND_DR) || (cs->dc.isac.ph_state == ISAC_IND_RS)) ph_command(cs, ISAC_CMD_TIM); else ph_command(cs, ISAC_CMD_RS); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_ENABLE | REQUEST): + spin_lock_irqsave(&cs->lock, flags); ph_command(cs, ISAC_CMD_TIM); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_INFO3 | REQUEST): + spin_lock_irqsave(&cs->lock, flags); ph_command(cs, ISAC_CMD_AR8); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_TESTLOOP | REQUEST): + spin_lock_irqsave(&cs->lock, flags); val = 0; if (1 & (long) arg) val |= 0x0c; @@ -407,20 +528,21 @@ if (test_bit(HW_IOM1, &cs->HW_Flags)) { /* IOM 1 Mode */ if (!val) { - isac_write(cs, ISAC_SPCR, 0xa); - isac_write(cs, ISAC_ADF1, 0x2); + cs->writeisac(cs, ISAC_SPCR, 0xa); + cs->writeisac(cs, ISAC_ADF1, 0x2); } else { - isac_write(cs, ISAC_SPCR, val); - isac_write(cs, ISAC_ADF1, 0xa); + cs->writeisac(cs, ISAC_SPCR, val); + cs->writeisac(cs, ISAC_ADF1, 0xa); } } else { /* IOM 2 Mode */ - isac_write(cs, ISAC_SPCR, val); + cs->writeisac(cs, ISAC_SPCR, val); if (val) - isac_write(cs, ISAC_ADF1, 0x8); + cs->writeisac(cs, ISAC_ADF1, 0x8); else - isac_write(cs, ISAC_ADF1, 0x0); + cs->writeisac(cs, ISAC_ADF1, 0x0); } + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_DEACTIVATE | RESPONSE): skb_queue_purge(&cs->rq); @@ -432,7 +554,7 @@ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); + schedule_event(cs, D_CLEARBUSY); break; default: if (cs->debug & L1_DEB_WARN) @@ -441,14 +563,13 @@ } } -static int +void setstack_isac(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = ISAC_l1hw; - return 0; } -static void +void DC_Close_isac(struct IsdnCardState *cs) { if (cs->dc.isac.mon_rx) { kfree(cs->dc.isac.mon_rx); @@ -467,8 +588,8 @@ int rbch, star; if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { - rbch = isac_read(cs, ISAC_RBCH); - star = isac_read(cs, ISAC_STAR); + rbch = cs->readisac(cs, ISAC_RBCH); + star = cs->readisac(cs, ISAC_STAR); if (cs->debug) debugl1(cs, "D-Channel Busy RBCH %02x STAR %02x", rbch, star); @@ -476,7 +597,7 @@ test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); stptr = cs->stlist; while (stptr != NULL) { - L1L2(stptr, PH_PAUSE | INDICATION, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); stptr = stptr->next; } } else { @@ -490,80 +611,74 @@ printk(KERN_WARNING "HiSax: ISAC D-Channel Busy no skb\n"); debugl1(cs, "D-Channel Busy no skb"); } - isac_write(cs, ISAC_CMDR, 0x01); /* Transmitter reset */ - cs->card_ops->irq_func(cs->irq, cs, NULL); + cs->writeisac(cs, ISAC_CMDR, 0x01); /* Transmitter reset */ + cs->irq_func(cs->irq, cs, NULL); } } } -static struct dc_l1_ops isac_l1_ops = { - .fill_fifo = isac_fill_fifo, - .open = setstack_isac, - .close = DC_Close_isac, - .bh_func = isac_bh, - .dbusy_func = dbusy_timer_handler, -}; - void __devinit initisac(struct IsdnCardState *cs) { - int val, eval; - - dc_l1_init(cs, &isac_l1_ops); - - val = isac_read(cs, ISAC_STAR); - debugl1(cs, "ISAC STAR %x", val); - val = isac_read(cs, ISAC_MODE); - debugl1(cs, "ISAC MODE %x", val); - val = isac_read(cs, ISAC_ADF2); - debugl1(cs, "ISAC ADF2 %x", val); - val = isac_read(cs, ISAC_ISTA); - debugl1(cs, "ISAC ISTA %x", val); - if (val & 0x01) { - eval = isac_read(cs, ISAC_EXIR); - debugl1(cs, "ISAC EXIR %x", eval); - } - /* Disable all IRQ */ - isac_write(cs, ISAC_MASK, 0xFF); - + cs->setstack_d = setstack_isac; + cs->DC_Close = DC_Close_isac; cs->dc.isac.mon_tx = NULL; cs->dc.isac.mon_rx = NULL; + cs->writeisac(cs, ISAC_MASK, 0xff); cs->dc.isac.mocr = 0xaa; if (test_bit(HW_IOM1, &cs->HW_Flags)) { /* IOM 1 Mode */ - isac_write(cs, ISAC_ADF2, 0x0); - isac_write(cs, ISAC_SPCR, 0xa); - isac_write(cs, ISAC_ADF1, 0x2); - isac_write(cs, ISAC_STCR, 0x70); - isac_write(cs, ISAC_MODE, 0xc9); + cs->writeisac(cs, ISAC_ADF2, 0x0); + cs->writeisac(cs, ISAC_SPCR, 0xa); + cs->writeisac(cs, ISAC_ADF1, 0x2); + cs->writeisac(cs, ISAC_STCR, 0x70); + cs->writeisac(cs, ISAC_MODE, 0xc9); } else { /* IOM 2 Mode */ if (!cs->dc.isac.adf2) cs->dc.isac.adf2 = 0x80; - isac_write(cs, ISAC_ADF2, cs->dc.isac.adf2); - isac_write(cs, ISAC_SQXR, 0x2f); - isac_write(cs, ISAC_SPCR, 0x00); - isac_write(cs, ISAC_STCR, 0x70); - isac_write(cs, ISAC_MODE, 0xc9); - isac_write(cs, ISAC_TIMR, 0x00); - isac_write(cs, ISAC_ADF1, 0x00); + cs->writeisac(cs, ISAC_ADF2, cs->dc.isac.adf2); + cs->writeisac(cs, ISAC_SQXR, 0x2f); + cs->writeisac(cs, ISAC_SPCR, 0x00); + cs->writeisac(cs, ISAC_STCR, 0x70); + cs->writeisac(cs, ISAC_MODE, 0xc9); + cs->writeisac(cs, ISAC_TIMR, 0x00); + cs->writeisac(cs, ISAC_ADF1, 0x00); } ph_command(cs, ISAC_CMD_RS); - isac_write(cs, ISAC_MASK, 0x0); + cs->writeisac(cs, ISAC_MASK, 0x0); +} - val = isac_read(cs, ISAC_CIR0); +void __devinit +clear_pending_isac_ints(struct IsdnCardState *cs) +{ + int val, eval; + + val = cs->readisac(cs, ISAC_STAR); + debugl1(cs, "ISAC STAR %x", val); + val = cs->readisac(cs, ISAC_MODE); + debugl1(cs, "ISAC MODE %x", val); + val = cs->readisac(cs, ISAC_ADF2); + debugl1(cs, "ISAC ADF2 %x", val); + val = cs->readisac(cs, ISAC_ISTA); + debugl1(cs, "ISAC ISTA %x", val); + if (val & 0x01) { + eval = cs->readisac(cs, ISAC_EXIR); + debugl1(cs, "ISAC EXIR %x", eval); + } + val = cs->readisac(cs, ISAC_CIR0); debugl1(cs, "ISAC CIR0 %x", val); cs->dc.isac.ph_state = (val >> 2) & 0xf; - sched_d_event(cs, D_L1STATECHANGE); - - /* RESET Receiver and Transmitter */ - isac_write(cs, ISAC_CMDR, 0x41); + schedule_event(cs, D_L1STATECHANGE); + /* Disable all IRQ */ + cs->writeisac(cs, ISAC_MASK, 0xFF); } -int -isac_setup(struct IsdnCardState *cs, struct dc_hw_ops *isac_ops) +void __devinit +setup_isac(struct IsdnCardState *cs) { - cs->dc_hw_ops = isac_ops; - ISACVersion(cs, "HiSax:"); - return 0; + INIT_WORK(&cs->tqueue, (void *)(void *) isac_bh, cs); + cs->dbusytimer.function = (void *) dbusy_timer_handler; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); } diff -Nru a/drivers/isdn/hisax/isac.h b/drivers/isdn/hisax/isac.h --- a/drivers/isdn/hisax/isac.h Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/hisax/isac.h Thu Feb 19 23:44:28 2004 @@ -1,4 +1,4 @@ -/* $Id: isac.h,v 1.7.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: isac.h,v 1.9.2.2 2004/01/12 22:52:27 keil Exp $ * * ISAC specific defines * @@ -63,6 +63,8 @@ #define ISAC_IND_AI10 0xD #define ISAC_IND_DID 0xF -extern void initisac(struct IsdnCardState *cs); -extern void isac_interrupt(struct IsdnCardState *cs, u8 val); -extern int isac_setup(struct IsdnCardState *cs, struct dc_hw_ops *isac_ops); +extern void ISACVersion(struct IsdnCardState *, char *); +extern void setup_isac(struct IsdnCardState *); +extern void initisac(struct IsdnCardState *); +extern void isac_interrupt(struct IsdnCardState *, u_char); +extern void clear_pending_isac_ints(struct IsdnCardState *); diff -Nru a/drivers/isdn/hisax/isar.c b/drivers/isdn/hisax/isar.c --- a/drivers/isdn/hisax/isar.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hisax/isar.c Thu Feb 19 23:44:24 2004 @@ -1,4 +1,4 @@ -/* $Id: isar.c,v 1.17.6.5 2001/09/23 11:51:33 keil Exp $ +/* $Id: isar.c,v 1.22.2.6 2004/02/11 13:21:34 keil Exp $ * * isar.c ISAR (Siemens PSB 7110) specific routines * @@ -20,33 +20,22 @@ #define DLE 0x10 #define ETX 0x03 - -const u8 faxmodulation_s[] = "3,24,48,72,73,74,96,97,98,121,122,145,146"; -const u8 faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146}; -#define FAXMODCNT 13 - -static void __isar_setup(struct IsdnCardState *cs); -static void isar_pump_cmd(struct BCState *bcs, u8 cmd, u8 para); -static inline void ll_deliver_faxstat(struct BCState *bcs, u8 status); -static spinlock_t isar_lock = SPIN_LOCK_UNLOCKED; - -static inline u8 -isar_read_reg(struct IsdnCardState *cs, int mode, u8 addr) -{ - return cs->bc_hw_ops->read_reg(cs, mode, addr); -} - -static inline void -isar_write_reg(struct IsdnCardState *cs, int mode, u8 addr, u8 val) -{ - cs->bc_hw_ops->write_reg(cs, mode, addr, val); -} +#define FAXMODCNT 13 +const u_char faxmodulation[] = {3,24,48,72,73,74,96,97,98,121,122,145,146}; +static u_int modmask = 0x1fff; +static int frm_extra_delay = 2; +static int para_TOA = 6; +const u_char *FC1_CMD[] = {"FAE", "FTS", "FRS", "FTM", "FRM", "FTH", "FRH", "CTRL" }; + +void isar_setup(struct IsdnCardState *cs); +static void isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para); +static void ll_deliver_faxstat(struct BCState *bcs, u_char status); static inline int waitforHIA(struct IsdnCardState *cs, int timeout) { - while ((isar_read_reg(cs, 0, ISAR_HIA) & 1) && timeout) { + while ((cs->BC_Read_Reg(cs, 0, ISAR_HIA) & 1) && timeout) { udelay(1); timeout--; } @@ -57,10 +46,9 @@ int -sendmsg(struct IsdnCardState *cs, u8 his, u8 creg, u8 len, - u8 *msg) +sendmsg(struct IsdnCardState *cs, u_char his, u_char creg, u_char len, + u_char *msg) { - unsigned long flags; int i; if (!waitforHIA(cs, 4000)) @@ -69,14 +57,13 @@ if (cs->debug & L1_DEB_HSCX) debugl1(cs, "sendmsg(%02x,%02x,%d)", his, creg, len); #endif - spin_lock_irqsave(&isar_lock, flags); - isar_write_reg(cs, 0, ISAR_CTRL_H, creg); - isar_write_reg(cs, 0, ISAR_CTRL_L, len); - isar_write_reg(cs, 0, ISAR_WADR, 0); + cs->BC_Write_Reg(cs, 0, ISAR_CTRL_H, creg); + cs->BC_Write_Reg(cs, 0, ISAR_CTRL_L, len); + cs->BC_Write_Reg(cs, 0, ISAR_WADR, 0); if (msg && len) { - isar_write_reg(cs, 1, ISAR_MBOX, msg[0]); + cs->BC_Write_Reg(cs, 1, ISAR_MBOX, msg[0]); for (i=1; iBC_Write_Reg(cs, 2, ISAR_MBOX, msg[i]); #if DUMP_MBOXFRAME>1 if (cs->debug & L1_DEB_HSCX_FIFO) { char tmp[256], *t; @@ -92,23 +79,22 @@ } #endif } - isar_write_reg(cs, 1, ISAR_HIS, his); - spin_unlock_irqrestore(&isar_lock, flags); + cs->BC_Write_Reg(cs, 1, ISAR_HIS, his); waitforHIA(cs, 10000); return(1); } /* Call only with IRQ disabled !!! */ inline void -rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u8 *msg) +rcv_mbox(struct IsdnCardState *cs, struct isar_reg *ireg, u_char *msg) { int i; - isar_write_reg(cs, 1, ISAR_RADR, 0); + cs->BC_Write_Reg(cs, 1, ISAR_RADR, 0); if (msg && ireg->clsb) { - msg[0] = isar_read_reg(cs, 1, ISAR_MBOX); + msg[0] = cs->BC_Read_Reg(cs, 1, ISAR_MBOX); for (i=1; i < ireg->clsb; i++) - msg[i] = isar_read_reg(cs, 2, ISAR_MBOX); + msg[i] = cs->BC_Read_Reg(cs, 2, ISAR_MBOX); #if DUMP_MBOXFRAME>1 if (cs->debug & L1_DEB_HSCX_FIFO) { char tmp[256], *t; @@ -124,85 +110,90 @@ } #endif } - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } /* Call only with IRQ disabled !!! */ inline void get_irq_infos(struct IsdnCardState *cs, struct isar_reg *ireg) { - ireg->iis = isar_read_reg(cs, 1, ISAR_IIS); - ireg->cmsb = isar_read_reg(cs, 1, ISAR_CTRL_H); - ireg->clsb = isar_read_reg(cs, 1, ISAR_CTRL_L); + ireg->iis = cs->BC_Read_Reg(cs, 1, ISAR_IIS); + ireg->cmsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_H); + ireg->clsb = cs->BC_Read_Reg(cs, 1, ISAR_CTRL_L); #if DUMP_MBOXFRAME if (cs->debug & L1_DEB_HSCX) - debugl1(cs, "rcv_mbox(%02x,%02x,%d)", ireg->iis, ireg->cmsb, + debugl1(cs, "irq_stat(%02x,%02x,%d)", ireg->iis, ireg->cmsb, ireg->clsb); #endif } int -waitrecmsg(struct IsdnCardState *cs, u8 *len, - u8 *msg, int maxdelay) +waitrecmsg(struct IsdnCardState *cs, u_char *len, + u_char *msg, int maxdelay) { int timeout = 0; - unsigned long flags; struct isar_reg *ir = cs->bcs[0].hw.isar.reg; - while((!(isar_read_reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) && + while((!(cs->BC_Read_Reg(cs, 0, ISAR_IRQBIT) & ISAR_IRQSTA)) && (timeout++ < maxdelay)) udelay(1); if (timeout >= maxdelay) { printk(KERN_WARNING"isar recmsg IRQSTA timeout\n"); return(0); } - spin_lock_irqsave(&isar_lock, flags); get_irq_infos(cs, ir); rcv_mbox(cs, ir, msg); *len = ir->clsb; - spin_unlock_irqrestore(&isar_lock, flags); return(1); } -static int +int ISARVersion(struct IsdnCardState *cs, char *s) { int ver; - u8 msg[] = ISAR_MSG_HWVER; - u8 tmp[64]; - u8 len; + u_char msg[] = ISAR_MSG_HWVER; + u_char tmp[64]; + u_char len; + u_long flags; int debug; - cs->card_ops->reset(cs); + cs->cardmsg(cs, CARD_RESET, NULL); + spin_lock_irqsave(&cs->lock, flags); /* disable ISAR IRQ */ - isar_write_reg(cs, 0, ISAR_IRQBIT, 0); + cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); debug = cs->debug; cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO); - if (!sendmsg(cs, ISAR_HIS_VNR, 0, 3, msg)) + if (!sendmsg(cs, ISAR_HIS_VNR, 0, 3, msg)) { + spin_unlock_irqrestore(&cs->lock, flags); return(-1); - if (!waitrecmsg(cs, &len, tmp, 100000)) - return(-2); + } + if (!waitrecmsg(cs, &len, tmp, 100000)) { + spin_unlock_irqrestore(&cs->lock, flags); + return(-2); + } cs->debug = debug; if (cs->bcs[0].hw.isar.reg->iis == ISAR_IIS_VNR) { if (len == 1) { ver = tmp[0] & 0xf; printk(KERN_INFO "%s ISAR version %d\n", s, ver); - return(ver); - } - return(-3); - } - return(-4); + } else + ver = -3; + } else + ver = -4; + spin_unlock_irqrestore(&cs->lock, flags); + return(ver); } int -isar_load_firmware(struct IsdnCardState *cs, u8 *buf) +isar_load_firmware(struct IsdnCardState *cs, u_char *buf) { int ret, size, cnt, debug; - u8 len, nom, noc; + u_char len, nom, noc; u_short sadr, left, *sp; - u8 *p = buf; - u8 *msg, *tmpmsg, *mp, tmp[64]; + u_char *p = buf; + u_char *msg, *tmpmsg, *mp, tmp[64]; + u_long flags; struct isar_reg *ireg = cs->bcs[0].hw.isar.reg; struct {u_short sadr; @@ -219,16 +210,16 @@ #if DBG_LOADFIRM<2 cs->debug &= ~(L1_DEB_HSCX | L1_DEB_HSCX_FIFO); #endif - printk(KERN_DEBUG"isar_load_firmware buf %#lx\n", (u_long)buf); + if ((ret = copy_from_user(&size, p, sizeof(int)))) { printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret); - return -EFAULT; + return ret; } p += sizeof(int); printk(KERN_DEBUG"isar_load_firmware size: %d\n", size); cnt = 0; /* disable ISAR IRQ */ - isar_write_reg(cs, 0, ISAR_IRQBIT, 0); + cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); if (!(msg = kmalloc(256, GFP_KERNEL))) { printk(KERN_ERR"isar_load_firmware no buffer\n"); return (1); @@ -238,10 +229,13 @@ kfree(msg); return (1); } + spin_lock_irqsave(&cs->lock, flags); + /* disable ISAR IRQ */ + cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); + spin_unlock_irqrestore(&cs->lock, flags); while (cnt < size) { if ((ret = copy_from_user(&blk_head, p, BLK_HEAD_SIZE))) { printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret); - ret = -EFAULT; goto reterror; } #ifdef __BIG_ENDIAN @@ -258,19 +252,21 @@ blk_head.sadr, blk_head.len, blk_head.d_key & 0xff); sadr = blk_head.sadr; left = blk_head.len; + spin_lock_irqsave(&cs->lock, flags); if (!sendmsg(cs, ISAR_HIS_DKEY, blk_head.d_key & 0xff, 0, NULL)) { printk(KERN_ERR"isar sendmsg dkey failed\n"); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } if (!waitrecmsg(cs, &len, tmp, 100000)) { printk(KERN_ERR"isar waitrecmsg dkey failed\n"); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } if ((ireg->iis != ISAR_IIS_DKEY) || ireg->cmsb || len) { printk(KERN_ERR"isar wrong dkey response (%x,%x,%x)\n", ireg->iis, ireg->cmsb, len); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } + spin_unlock_irqrestore(&cs->lock, flags); while (left>0) { if (left > 126) noc = 126; @@ -284,7 +280,6 @@ *mp++ = noc; if ((ret = copy_from_user(tmpmsg, p, nom))) { printk(KERN_ERR"isar_load_firmware copy_from_user ret %d\n", ret); - ret = -EFAULT; goto reterror; } p += nom; @@ -307,19 +302,21 @@ sp++; noc--; } + spin_lock_irqsave(&cs->lock, flags); if (!sendmsg(cs, ISAR_HIS_FIRM, 0, nom, msg)) { printk(KERN_ERR"isar sendmsg prog failed\n"); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } if (!waitrecmsg(cs, &len, tmp, 100000)) { printk(KERN_ERR"isar waitrecmsg prog failed\n"); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } if ((ireg->iis != ISAR_IIS_FIRM) || ireg->cmsb || len) { printk(KERN_ERR"isar wrong prog response (%x,%x,%x)\n", ireg->iis, ireg->cmsb, len); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } + spin_unlock_irqrestore(&cs->lock, flags); } printk(KERN_DEBUG"isar firmware block %5d words loaded\n", blk_head.len); @@ -331,23 +328,25 @@ msg[0] = 0xff; msg[1] = 0xfe; ireg->bstat = 0; + spin_lock_irqsave(&cs->lock, flags); if (!sendmsg(cs, ISAR_HIS_STDSP, 0, 2, msg)) { printk(KERN_ERR"isar sendmsg start dsp failed\n"); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } if (!waitrecmsg(cs, &len, tmp, 100000)) { printk(KERN_ERR"isar waitrecmsg start dsp failed\n"); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } if ((ireg->iis != ISAR_IIS_STDSP) || ireg->cmsb || len) { printk(KERN_ERR"isar wrong start dsp response (%x,%x,%x)\n", ireg->iis, ireg->cmsb, len); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } else printk(KERN_DEBUG"isar start dsp success\n"); /* NORMAL mode entered */ /* Enable IRQs of ISAR */ - isar_write_reg(cs, 0, ISAR_IRQBIT, ISAR_IRQSTA); + cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, ISAR_IRQSTA); + spin_unlock_irqrestore(&cs->lock, flags); cnt = 1000; /* max 1s */ while ((!ireg->bstat) && cnt) { udelay(1000); @@ -364,12 +363,14 @@ cnt = 10; while (cnt--) udelay(1000); + spin_lock_irqsave(&cs->lock, flags); ireg->iis = 0; if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_STST, 0, NULL)) { printk(KERN_ERR"isar sendmsg self tst failed\n"); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } cnt = 10000; /* max 100 ms */ + spin_unlock_irqrestore(&cs->lock, flags); while ((ireg->iis != ISAR_IIS_DIAG) && cnt) { udelay(10); cnt--; @@ -387,11 +388,13 @@ ireg->cmsb, ireg->clsb, ireg->par[0]); ret = 1;goto reterror; } + spin_lock_irqsave(&cs->lock, flags); ireg->iis = 0; if (!sendmsg(cs, ISAR_HIS_DIAG, ISAR_CTRL_SWVER, 0, NULL)) { printk(KERN_ERR"isar RQST SVN failed\n"); - ret = 1;goto reterror; + ret = 1;goto reterr_unlock; } + spin_unlock_irqrestore(&cs->lock, flags); cnt = 30000; /* max 300 ms */ while ((ireg->iis != ISAR_IIS_DIAG) && cnt) { udelay(10); @@ -411,26 +414,31 @@ ret = 1;goto reterror; } } + spin_lock_irqsave(&cs->lock, flags); cs->debug = debug; - __isar_setup(cs); + isar_setup(cs); + ret = 0; +reterr_unlock: + spin_unlock_irqrestore(&cs->lock, flags); reterror: cs->debug = debug; if (ret) /* disable ISAR IRQ */ - isar_write_reg(cs, 0, ISAR_IRQBIT, 0); + cs->BC_Write_Reg(cs, 0, ISAR_IRQBIT, 0); kfree(msg); kfree(tmpmsg); return(ret); } extern void BChannel_bh(struct BCState *); +#define B_LL_NOCARRIER 8 +#define B_LL_CONNECT 9 +#define B_LL_OK 10 static void -isar_bh(void *data) +isar_bh(struct BCState *bcs) { - struct BCState *bcs = data; - BChannel_bh(bcs); if (test_and_clear_bit(B_LL_NOCARRIER, &bcs->event)) ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_NOCARR); @@ -440,16 +448,16 @@ ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_OK); } -static inline void +static void send_DLE_ETX(struct BCState *bcs) { - u8 dleetx[2] = {DLE,ETX}; + u_char dleetx[2] = {DLE,ETX}; struct sk_buff *skb; if ((skb = dev_alloc_skb(2))) { memcpy(skb_put(skb, 2), dleetx, 2); skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + schedule_event(bcs, B_RCVBUFREADY); } else { printk(KERN_WARNING "HiSax: skb out of memory\n"); } @@ -476,16 +484,16 @@ } } -static inline void +static void isar_rcv_frame(struct IsdnCardState *cs, struct BCState *bcs) { - u8 *ptr; + u_char *ptr; struct sk_buff *skb; struct isar_reg *ireg = bcs->hw.isar.reg; if (!ireg->clsb) { debugl1(cs, "isar zero len frame"); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); return; } switch (bcs->mode) { @@ -494,24 +502,24 @@ ireg->iis, ireg->cmsb, ireg->clsb); printk(KERN_WARNING"isar mode 0 spurious IIS_RDATA %x/%x/%x\n", ireg->iis, ireg->cmsb, ireg->clsb); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); break; case L1_MODE_TRANS: case L1_MODE_V32: if ((skb = dev_alloc_skb(ireg->clsb))) { - rcv_mbox(cs, ireg, (u8 *)skb_put(skb, ireg->clsb)); + rcv_mbox(cs, ireg, (u_char *)skb_put(skb, ireg->clsb)); skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + schedule_event(bcs, B_RCVBUFREADY); } else { printk(KERN_WARNING "HiSax: skb out of memory\n"); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } break; case L1_MODE_HDLC: if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar_rcv_frame: incoming packet too large"); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); bcs->hw.isar.rcvidx = 0; } else if (ireg->cmsb & HDLC_ERROR) { if (cs->debug & L1_DEB_WARN) @@ -524,7 +532,7 @@ bcs->err_crc++; #endif bcs->hw.isar.rcvidx = 0; - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } else { if (ireg->cmsb & HDLC_FSD) bcs->hw.isar.rcvidx = 0; @@ -542,7 +550,7 @@ memcpy(skb_put(skb, bcs->hw.isar.rcvidx-2), bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx-2); skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + schedule_event(bcs, B_RCVBUFREADY); } bcs->hw.isar.rcvidx = 0; } @@ -552,7 +560,7 @@ if (bcs->hw.isar.state != STFAX_ACTIV) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar_rcv_frame: not ACTIV"); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); bcs->hw.isar.rcvidx = 0; break; } @@ -564,25 +572,23 @@ debugl1(cs, "isar_rcv_frame: raw(%d) dle(%d)", ireg->clsb, bcs->hw.isar.rcvidx); if ((skb = dev_alloc_skb(bcs->hw.isar.rcvidx))) { - insert_dle((u8 *)skb_put(skb, bcs->hw.isar.rcvidx), + insert_dle((u_char *)skb_put(skb, bcs->hw.isar.rcvidx), bcs->hw.isar.rcvbuf, ireg->clsb); skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + schedule_event(bcs, B_RCVBUFREADY); if (ireg->cmsb & SART_NMD) { /* ABORT */ if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar_rcv_frame: no more data"); - isar_write_reg(cs, 1, ISAR_IIA, 0); bcs->hw.isar.rcvidx = 0; send_DLE_ETX(bcs); sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL); bcs->hw.isar.state = STFAX_ESCAPE; - sched_b_event(bcs, B_LL_NOCARRIER); + schedule_event(bcs, B_LL_NOCARRIER); } } else { printk(KERN_WARNING "HiSax: skb out of memory\n"); - isar_write_reg(cs, 1, ISAR_IIA, 0); } break; } @@ -590,7 +596,7 @@ if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar_rcv_frame: unknown fax mode %x", bcs->hw.isar.cmd); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); bcs->hw.isar.rcvidx = 0; break; } @@ -598,17 +604,18 @@ if ((bcs->hw.isar.rcvidx + ireg->clsb) > HSCX_BUFMAX) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar_rcv_frame: incoming packet too large"); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); bcs->hw.isar.rcvidx = 0; } else if (ireg->cmsb & HDLC_ERROR) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar frame error %x len %d", ireg->cmsb, ireg->clsb); bcs->hw.isar.rcvidx = 0; - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } else { - if (ireg->cmsb & HDLC_FSD) + if (ireg->cmsb & HDLC_FSD) { bcs->hw.isar.rcvidx = 0; + } ptr = bcs->hw.isar.rcvbuf + bcs->hw.isar.rcvidx; bcs->hw.isar.rcvidx += ireg->clsb; rcv_mbox(cs, ireg, ptr); @@ -619,16 +626,19 @@ if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar frame to short %d", bcs->hw.isar.rcvidx); - } else if (!(skb = dev_alloc_skb(bcs->hw.isar.rcvidx))) { + printk(KERN_WARNING "ISAR: frame to short %d\n", + bcs->hw.isar.rcvidx); + } else if (!(skb = dev_alloc_skb(len))) { printk(KERN_WARNING "ISAR: receive out of memory\n"); } else { - insert_dle((u8 *)skb_put(skb, len), + insert_dle((u_char *)skb_put(skb, len), bcs->hw.isar.rcvbuf, bcs->hw.isar.rcvidx); skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); + schedule_event(bcs, B_RCVBUFREADY); send_DLE_ETX(bcs); - sched_b_event(bcs, B_LL_OK); + schedule_event(bcs, B_LL_OK); + test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag); } bcs->hw.isar.rcvidx = 0; } @@ -636,18 +646,19 @@ if (ireg->cmsb & SART_NMD) { /* ABORT */ if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar_rcv_frame: no more data"); - isar_write_reg(cs, 1, ISAR_IIA, 0); bcs->hw.isar.rcvidx = 0; - send_DLE_ETX(bcs); sendmsg(cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_PUMPCTRL, PCTRL_CMD_ESC, 0, NULL); bcs->hw.isar.state = STFAX_ESCAPE; - sched_b_event(bcs, B_LL_NOCARRIER); + if (test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag)) { + send_DLE_ETX(bcs); + schedule_event(bcs, B_LL_NOCARRIER); + } } break; default: printk(KERN_ERR"isar_rcv_frame mode (%x)error\n", bcs->mode); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); break; } } @@ -657,8 +668,8 @@ { struct IsdnCardState *cs = bcs->cs; int count; - u8 msb; - u8 *ptr; + u_char msb; + u_char *ptr; if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) debugl1(cs, "isar_fill_fifo"); @@ -669,7 +680,7 @@ if (!(bcs->hw.isar.reg->bstat & (bcs->hw.isar.dpath == 1 ? BSTAT_RDM1 : BSTAT_RDM2))) return; - if (bcs->tx_skb->len > (u_int)bcs->hw.isar.mml) { + if (bcs->tx_skb->len > bcs->hw.isar.mml) { msb = 0; count = bcs->hw.isar.mml; } else { @@ -677,7 +688,7 @@ msb = HDLC_FED; } ptr = bcs->tx_skb->data; - if (!bcs->count) { + if (!bcs->hw.isar.txcnt) { msb |= HDLC_FST; if ((bcs->mode == L1_MODE_FAX) && (bcs->hw.isar.cmd == PCTRL_CMD_FTH)) { @@ -691,7 +702,7 @@ } skb_pull(bcs->tx_skb, count); bcs->tx_cnt -= count; - bcs->count += count; + bcs->hw.isar.txcnt += count; switch (bcs->mode) { case L1_MODE_NULL: printk(KERN_ERR"isar_fill_fifo wrong mode 0\n"); @@ -729,7 +740,7 @@ } inline -struct BCState *sel_bcs_isar(struct IsdnCardState *cs, u8 dpath) +struct BCState *sel_bcs_isar(struct IsdnCardState *cs, u_char dpath) { if ((!dpath) || (dpath == 3)) return(NULL); @@ -740,7 +751,7 @@ return(NULL); } -inline void +void send_frames(struct BCState *bcs) { if (bcs->tx_skb) { @@ -748,7 +759,14 @@ isar_fill_fifo(bcs); return; } else { - xmit_complete_b(bcs); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.isar.txcnt; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } if (bcs->mode == L1_MODE_FAX) { if (bcs->hw.isar.cmd == PCTRL_CMD_FTH) { if (test_bit(BC_FLG_LASTDATA, &bcs->Flag)) { @@ -761,33 +779,35 @@ } } } - bcs->count = 0; + dev_kfree_skb_any(bcs->tx_skb); + bcs->hw.isar.txcnt = 0; + bcs->tx_skb = NULL; } } if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { - bcs->count = 0; + bcs->hw.isar.txcnt = 0; test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); isar_fill_fifo(bcs); } else { if (test_and_clear_bit(BC_FLG_DLEETX, &bcs->Flag)) { if (test_and_clear_bit(BC_FLG_LASTDATA, &bcs->Flag)) { if (test_and_clear_bit(BC_FLG_NMD_DATA, &bcs->Flag)) { - u8 dummy = 0; + u_char dummy = 0; sendmsg(bcs->cs, SET_DPS(bcs->hw.isar.dpath) | ISAR_HIS_SDATA, 0x01, 1, &dummy); } test_and_set_bit(BC_FLG_LL_OK, &bcs->Flag); } else { - sched_b_event(bcs, B_LL_CONNECT); + schedule_event(bcs, B_LL_CONNECT); } } test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); - sched_b_event(bcs, B_XMTBUFREADY); + schedule_event(bcs, B_XMTBUFREADY); } } inline void -check_send(struct IsdnCardState *cs, u8 rdm) +check_send(struct IsdnCardState *cs, u_char rdm) { struct BCState *bcs; @@ -817,8 +837,8 @@ static void isar_pump_status_rsp(struct BCState *bcs, struct isar_reg *ireg) { struct IsdnCardState *cs = bcs->cs; - u8 ril = ireg->par[0]; - u8 rim; + u_char ril = ireg->par[0]; + u_char rim; if (!test_and_clear_bit(ISAR_RATE_REQ, &bcs->hw.isar.reg->Flags)) return; @@ -869,9 +889,9 @@ } static void -isar_pump_statev_modem(struct BCState *bcs, u8 devt) { +isar_pump_statev_modem(struct BCState *bcs, u_char devt) { struct IsdnCardState *cs = bcs->cs; - u8 dps = SET_DPS(bcs->hw.isar.dpath); + u_char dps = SET_DPS(bcs->hw.isar.dpath); switch(devt) { case PSEV_10MS_TIMER: @@ -938,8 +958,8 @@ } } -static inline void -ll_deliver_faxstat(struct BCState *bcs, u8 status) +static void +ll_deliver_faxstat(struct BCState *bcs, u_char status) { isdn_ctrl ic; struct Channel *chanp = (struct Channel *) bcs->st->lli.userdata; @@ -954,10 +974,10 @@ } static void -isar_pump_statev_fax(struct BCState *bcs, u8 devt) { +isar_pump_statev_fax(struct BCState *bcs, u_char devt) { struct IsdnCardState *cs = bcs->cs; - u8 dps = SET_DPS(bcs->hw.isar.dpath); - u8 p1; + u_char dps = SET_DPS(bcs->hw.isar.dpath); + u_char p1; switch(devt) { case PSEV_10MS_TIMER: @@ -1041,7 +1061,7 @@ &bcs->Flag); add_timer(&bcs->hw.isar.ftimer); } else { - sched_b_event(bcs, B_LL_CONNECT); + schedule_event(bcs, B_LL_CONNECT); } } else { if (cs->debug & L1_DEB_WARN) @@ -1057,19 +1077,22 @@ if (cs->debug & L1_DEB_HSCX) debugl1(cs, "pump stev RSP_DISC"); if (bcs->hw.isar.state == STFAX_ESCAPE) { + p1 = 5; switch(bcs->hw.isar.newcmd) { case 0: bcs->hw.isar.state = STFAX_READY; break; - case PCTRL_CMD_FTH: case PCTRL_CMD_FTM: - p1 = 10; + p1 = 2; + case PCTRL_CMD_FTH: sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, PCTRL_CMD_SILON, 1, &p1); bcs->hw.isar.state = STFAX_SILDET; break; - case PCTRL_CMD_FRH: case PCTRL_CMD_FRM: + if (frm_extra_delay) + mdelay(frm_extra_delay); + case PCTRL_CMD_FRH: p1 = bcs->hw.isar.mod = bcs->hw.isar.newmod; bcs->hw.isar.newmod = 0; bcs->hw.isar.cmd = bcs->hw.isar.newcmd; @@ -1086,10 +1109,10 @@ } } else if (bcs->hw.isar.state == STFAX_ACTIV) { if (test_and_clear_bit(BC_FLG_LL_OK, &bcs->Flag)) { - sched_b_event(bcs, B_LL_OK); + schedule_event(bcs, B_LL_OK); } else if (bcs->hw.isar.cmd == PCTRL_CMD_FRM) { send_DLE_ETX(bcs); - sched_b_event(bcs, B_LL_NOCARRIER); + schedule_event(bcs, B_LL_NOCARRIER); } else { ll_deliver_faxstat(bcs, ISDN_FAX_CLASS1_FCERROR); } @@ -1156,11 +1179,11 @@ } else { debugl1(cs, "isar spurious IIS_RDATA %x/%x/%x", ireg->iis, ireg->cmsb, ireg->clsb); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } break; case ISAR_IIS_GSTEV: - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); ireg->bstat |= ireg->cmsb; check_send(cs, ireg->cmsb); break; @@ -1176,15 +1199,18 @@ if (cs->debug & L1_DEB_WARN) debugl1(cs, "Buffer STEV dpath%d msb(%x)", ireg->iis>>6, ireg->cmsb); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); break; case ISAR_IIS_PSTEV: if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { - rcv_mbox(cs, ireg, (u8 *)ireg->par); + rcv_mbox(cs, ireg, (u_char *)ireg->par); if (bcs->mode == L1_MODE_V32) { isar_pump_statev_modem(bcs, ireg->cmsb); } else if (bcs->mode == L1_MODE_FAX) { isar_pump_statev_fax(bcs, ireg->cmsb); + } else if (ireg->cmsb == PSEV_10MS_TIMER) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "pump stev TIMER"); } else { if (cs->debug & L1_DEB_WARN) debugl1(cs, "isar IIS_PSTEV pmode %d stat %x", @@ -1193,30 +1219,30 @@ } else { debugl1(cs, "isar spurious IIS_PSTEV %x/%x/%x", ireg->iis, ireg->cmsb, ireg->clsb); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } break; case ISAR_IIS_PSTRSP: if ((bcs = sel_bcs_isar(cs, ireg->iis >> 6))) { - rcv_mbox(cs, ireg, (u8 *)ireg->par); + rcv_mbox(cs, ireg, (u_char *)ireg->par); isar_pump_status_rsp(bcs, ireg); } else { debugl1(cs, "isar spurious IIS_PSTRSP %x/%x/%x", ireg->iis, ireg->cmsb, ireg->clsb); - isar_write_reg(cs, 1, ISAR_IIA, 0); + cs->BC_Write_Reg(cs, 1, ISAR_IIA, 0); } break; case ISAR_IIS_DIAG: case ISAR_IIS_BSTRSP: case ISAR_IIS_IOM2RSP: - rcv_mbox(cs, ireg, (u8 *)ireg->par); + rcv_mbox(cs, ireg, (u_char *)ireg->par); if ((cs->debug & (L1_DEB_HSCX | L1_DEB_HSCX_FIFO)) == L1_DEB_HSCX) { - u8 *tp=debbuf; + u_char *tp=debbuf; tp += sprintf(debbuf, "msg iis(%x) msb(%x)", ireg->iis, ireg->cmsb); - QuickHex(tp, (u8 *)ireg->par, ireg->clsb); + QuickHex(tp, (u_char *)ireg->par, ireg->clsb); debugl1(cs, debbuf); } break; @@ -1242,15 +1268,18 @@ bcs->Flag); test_and_clear_bit(BC_FLG_FTI_RUN, &bcs->Flag); if (test_and_clear_bit(BC_FLG_LL_CONN, &bcs->Flag)) { - sched_b_event(bcs, B_LL_CONNECT); + schedule_event(bcs, B_LL_CONNECT); + } + if (test_and_clear_bit(BC_FLG_FTI_FTS, &bcs->Flag)) { + schedule_event(bcs, B_LL_OK); } } static void setup_pump(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - u8 dps = SET_DPS(bcs->hw.isar.dpath); - u8 ctrl, param[6]; + u_char dps = SET_DPS(bcs->hw.isar.dpath); + u_char ctrl, param[6]; switch (bcs->mode) { case L1_MODE_NULL: @@ -1266,7 +1295,7 @@ } else { param[5] = PV32P6_ATN; } - param[0] = 6; /* 6 db */ + param[0] = para_TOA; /* 6 db */ param[1] = PV32P2_V23R | PV32P2_V22A | PV32P2_V22B | PV32P2_V22C | PV32P2_V21 | PV32P2_BEL; param[2] = PV32P3_AMOD | PV32P3_V32B | PV32P3_V23B; @@ -1282,7 +1311,7 @@ } else { param[1] = PFAXP2_ATN; } - param[0] = 6; /* 6 db */ + param[0] = para_TOA; /* 6 db */ sendmsg(cs, dps | ISAR_HIS_PUMPCFG, ctrl, 2, param); bcs->hw.isar.state = STFAX_NULL; bcs->hw.isar.newcmd = 0; @@ -1298,8 +1327,8 @@ static void setup_sart(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - u8 dps = SET_DPS(bcs->hw.isar.dpath); - u8 ctrl, param[2]; + u_char dps = SET_DPS(bcs->hw.isar.dpath); + u_char ctrl, param[2]; switch (bcs->mode) { case L1_MODE_NULL: @@ -1311,7 +1340,6 @@ "\0\0"); break; case L1_MODE_HDLC: - case L1_MODE_FAX: param[0] = 0; sendmsg(cs, dps | ISAR_HIS_SARTCFG, SMODE_HDLC, 1, param); @@ -1323,6 +1351,9 @@ sendmsg(cs, dps | ISAR_HIS_SARTCFG, ctrl, 2, param); break; + case L1_MODE_FAX: + /* SART must not configured with FAX */ + break; } udelay(1000); sendmsg(cs, dps | ISAR_HIS_BSTREQ, 0, 0, NULL); @@ -1332,8 +1363,8 @@ static void setup_iom2(struct BCState *bcs) { struct IsdnCardState *cs = bcs->cs; - u8 dps = SET_DPS(bcs->hw.isar.dpath); - u8 cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD,0,0,0,0}; + u_char dps = SET_DPS(bcs->hw.isar.dpath); + u_char cmsb = IOM_CTRL_ENA, msg[5] = {IOM_P1_TXD,0,0,0,0}; if (bcs->channel) msg[1] = msg[3] = 1; @@ -1418,14 +1449,15 @@ } static void -isar_pump_cmd(struct BCState *bcs, u8 cmd, u8 para) +isar_pump_cmd(struct BCState *bcs, u_char cmd, u_char para) { struct IsdnCardState *cs = bcs->cs; - u8 dps = SET_DPS(bcs->hw.isar.dpath); - u8 ctrl = 0, nom = 0, p1 = 0; + u_char dps = SET_DPS(bcs->hw.isar.dpath); + u_char ctrl = 0, nom = 0, p1 = 0; switch(cmd) { case ISDN_FAX_CLASS1_FTM: + test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag); if (bcs->hw.isar.state == STFAX_READY) { p1 = para; ctrl = PCTRL_CMD_FTM; @@ -1449,6 +1481,7 @@ } break; case ISDN_FAX_CLASS1_FTH: + test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag); if (bcs->hw.isar.state == STFAX_READY) { p1 = para; ctrl = PCTRL_CMD_FTH; @@ -1472,6 +1505,7 @@ } break; case ISDN_FAX_CLASS1_FRM: + test_and_clear_bit(BC_FLG_FRH_WAIT, &bcs->Flag); if (bcs->hw.isar.state == STFAX_READY) { p1 = para; ctrl = PCTRL_CMD_FRM; @@ -1495,6 +1529,7 @@ } break; case ISDN_FAX_CLASS1_FRH: + test_and_set_bit(BC_FLG_FRH_WAIT, &bcs->Flag); if (bcs->hw.isar.state == STFAX_READY) { p1 = para; ctrl = PCTRL_CMD_FRH; @@ -1517,15 +1552,20 @@ bcs->hw.isar.state = STFAX_ESCAPE; } break; + case ISDN_FAXPUMP_HALT: + bcs->hw.isar.state = STFAX_NULL; + nom = 0; + ctrl = PCTRL_CMD_HALT; + break; } if (ctrl) sendmsg(cs, dps | ISAR_HIS_PUMPCTRL, ctrl, nom, &p1); } void -__isar_setup(struct IsdnCardState *cs) +isar_setup(struct IsdnCardState *cs) { - u8 msg; + u_char msg; int i; /* Dpath 1, 2 */ @@ -1538,57 +1578,105 @@ cs->bcs[i].mode = 0; cs->bcs[i].hw.isar.dpath = i + 1; modeisar(&cs->bcs[i], 0, 0); - INIT_WORK(&cs->bcs[i].work, isar_bh, &cs->bcs[i]); + INIT_WORK(&cs->bcs[i].tqueue, (void *)(void *) isar_bh, &cs->bcs[i]); } } void isar_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; + int ret; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs, "DRQ set BC_FLG_BUSY"); + bcs->hw.isar.txcnt = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "isar_l2l1: this shouldn't happen\n"); + } else { + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs, "PUI set BC_FLG_BUSY"); + bcs->tx_skb = skb; + bcs->hw.isar.txcnt = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - st->l1.bcs->hw.isar.conmsg[0] = 0; + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + bcs->hw.isar.conmsg[0] = 0; if (test_bit(FLG_ORIG, &st->l2.flag)) - test_and_set_bit(BC_FLG_ORIG, &st->l1.bcs->Flag); + test_and_set_bit(BC_FLG_ORIG, &bcs->Flag); else - test_and_clear_bit(BC_FLG_ORIG, &st->l1.bcs->Flag); + test_and_clear_bit(BC_FLG_ORIG, &bcs->Flag); switch(st->l1.mode) { case L1_MODE_TRANS: case L1_MODE_HDLC: - if (modeisar(st->l1.bcs, st->l1.mode, st->l1.bc)) + ret = modeisar(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + if (ret) l1_msg_b(st, PH_DEACTIVATE | REQUEST, arg); else l1_msg_b(st, PH_ACTIVATE | REQUEST, arg); break; case L1_MODE_V32: case L1_MODE_FAX: - if (modeisar(st->l1.bcs, st->l1.mode, st->l1.bc)) + ret = modeisar(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + if (ret) l1_msg_b(st, PH_DEACTIVATE | REQUEST, arg); break; + default: + spin_unlock_irqrestore(&bcs->cs->lock, flags); + break; } break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - if (st->l1.bcs->cs->debug & L1_DEB_HSCX) - debugl1(st->l1.bcs->cs, "PDAC clear BC_FLG_BUSY"); - modeisar(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + switch(st->l1.mode) { + case L1_MODE_TRANS: + case L1_MODE_HDLC: + case L1_MODE_V32: + break; + case L1_MODE_FAX: + isar_pump_cmd(bcs, ISDN_FAXPUMP_HALT, 0); + break; + } + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + if (bcs->cs->debug & L1_DEB_HSCX) + debugl1(bcs->cs, "PDAC clear BC_FLG_BUSY"); + modeisar(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -1634,9 +1722,6 @@ bcs->event = 0; bcs->hw.isar.rcvidx = 0; bcs->tx_cnt = 0; - bcs->hw.isar.ftimer.function = (void *) ftimer_handler; - bcs->hw.isar.ftimer.data = (long) bcs; - init_timer(&bcs->hw.isar.ftimer); return (0); } @@ -1647,7 +1732,7 @@ if (open_isarstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = isar_l2l1; + st->l2.l2l1 = isar_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); @@ -1674,6 +1759,51 @@ test_and_set_bit(BC_FLG_DLEETX, &bcs->Flag); break; + case ISDN_FAX_CLASS1_FTS: + if (ic->parm.aux.subcmd == AT_QUERY) { + ic->command = ISDN_STAT_FAXIND; + ic->parm.aux.cmd = ISDN_FAX_CLASS1_OK; + cs->iif.statcallb(ic); + return(0); + } else if (ic->parm.aux.subcmd == AT_EQ_QUERY) { + strcpy(ic->parm.aux.para, "0-255"); + ic->command = ISDN_STAT_FAXIND; + ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY; + cs->iif.statcallb(ic); + return(0); + } else if (ic->parm.aux.subcmd == AT_EQ_VALUE) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "isar_auxcmd %s=%d", + FC1_CMD[ic->parm.aux.cmd], ic->parm.aux.para[0]); + if (bcs->hw.isar.state == STFAX_READY) { + if (! ic->parm.aux.para[0]) { + ic->command = ISDN_STAT_FAXIND; + ic->parm.aux.cmd = ISDN_FAX_CLASS1_OK; + cs->iif.statcallb(ic); + return(0); + } + if (! test_and_set_bit(BC_FLG_FTI_RUN, &bcs->Flag)) { + /* n*10 ms */ + bcs->hw.isar.ftimer.expires = + jiffies + ((ic->parm.aux.para[0] * 10 * HZ)/1000); + test_and_set_bit(BC_FLG_FTI_FTS, &bcs->Flag); + add_timer(&bcs->hw.isar.ftimer); + return(0); + } else { + if (cs->debug) + debugl1(cs, "isar FTS=%d and FTI busy", + ic->parm.aux.para[0]); + } + } else { + if (cs->debug) + debugl1(cs, "isar FTS=%d and isar.state not ready(%x)", + ic->parm.aux.para[0],bcs->hw.isar.state); + } + ic->command = ISDN_STAT_FAXIND; + ic->parm.aux.cmd = ISDN_FAX_CLASS1_ERROR; + cs->iif.statcallb(ic); + } + break; case ISDN_FAX_CLASS1_FRM: case ISDN_FAX_CLASS1_FRH: case ISDN_FAX_CLASS1_FTM: @@ -1686,16 +1816,24 @@ cs->iif.statcallb(ic); return(0); } else if (ic->parm.aux.subcmd == AT_EQ_QUERY) { - strcpy(ic->parm.aux.para, faxmodulation_s); + char *p = ic->parm.aux.para; + for(i=0;icommand = ISDN_STAT_FAXIND; ic->parm.aux.cmd = ISDN_FAX_CLASS1_QUERY; cs->iif.statcallb(ic); return(0); } else if (ic->parm.aux.subcmd == AT_EQ_VALUE) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "isar_auxcmd %s=%d", + FC1_CMD[ic->parm.aux.cmd], ic->parm.aux.para[0]); for(i=0;iparm.aux.para[0]) break; - if ((FAXMODCNT > i) && + if ((i < FAXMODCNT) && ((1<Flag)) { isar_pump_cmd(bcs, ic->parm.aux.cmd, @@ -1713,16 +1851,36 @@ break; case (ISDN_CMD_IOCTL): switch (ic->arg) { - case (9): /* load firmware */ + case 9: /* load firmware */ features = ISDN_FEATURE_L2_MODEM | ISDN_FEATURE_L2_FAX | ISDN_FEATURE_L3_FCLASS1; memcpy(&adr, ic->parm.num, sizeof(ulong)); - if (isar_load_firmware(cs, (u8 *)adr)) + if (isar_load_firmware(cs, (u_char *)adr)) return(1); else ll_run(cs, features); break; + case 20: + features = *(unsigned int *) ic->parm.num; + printk(KERN_DEBUG "HiSax: max modulation old(%04x) new(%04x)\n", + modmask, features); + modmask = features; + break; + case 21: + features = *(unsigned int *) ic->parm.num; + printk(KERN_DEBUG "HiSax: FRM extra delay old(%d) new(%d) ms\n", + frm_extra_delay, features); + if (features >= 0) + frm_extra_delay = features; + break; + case 22: + features = *(unsigned int *) ic->parm.num; + printk(KERN_DEBUG "HiSax: TOA old(%d) new(%d) db\n", + para_TOA, features); + if (features >= 0 && features < 32) + para_TOA = features; + break; default: printk(KERN_DEBUG "HiSax: invalid ioctl %d\n", (int) ic->arg); @@ -1735,21 +1893,17 @@ return(0); } -static struct bc_l1_ops isar_l1_ops = { - .fill_fifo = isar_fill_fifo, - .open = setstack_isar, - .close = close_isarstate, -}; - void __devinit initisar(struct IsdnCardState *cs) { - cs->bc_l1_ops = &isar_l1_ops; -} - -int -isar_setup(struct IsdnCardState *cs, struct bc_hw_ops *isar_ops) -{ - cs->bc_hw_ops = isar_ops; - return ISARVersion(cs, "HiSax:"); + cs->bcs[0].BC_SetStack = setstack_isar; + cs->bcs[1].BC_SetStack = setstack_isar; + cs->bcs[0].BC_Close = close_isarstate; + cs->bcs[1].BC_Close = close_isarstate; + cs->bcs[0].hw.isar.ftimer.function = (void *) ftimer_handler; + cs->bcs[0].hw.isar.ftimer.data = (long) &cs->bcs[0]; + init_timer(&cs->bcs[0].hw.isar.ftimer); + cs->bcs[1].hw.isar.ftimer.function = (void *) ftimer_handler; + cs->bcs[1].hw.isar.ftimer.data = (long) &cs->bcs[1]; + init_timer(&cs->bcs[1].hw.isar.ftimer); } diff -Nru a/drivers/isdn/hisax/isar.h b/drivers/isdn/hisax/isar.h --- a/drivers/isdn/hisax/isar.h Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hisax/isar.h Thu Feb 19 23:44:24 2004 @@ -1,4 +1,4 @@ -/* $Id: isar.h,v 1.9.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: isar.h,v 1.11.2.2 2004/01/12 22:52:27 keil Exp $ * * ISAR (Siemens PSB 7110) specific defines * @@ -28,6 +28,8 @@ #define ISAR_HIS_FIRM 0x1e #define ISAR_HIS_STDSP 0x08 #define ISAR_HIS_DIAG 0x05 +#define ISAR_HIS_WAITSTATE 0x27 +#define ISAR_HIS_TIMERIRQ 0x25 #define ISAR_HIS_P0CFG 0x3c #define ISAR_HIS_P12CFG 0x24 #define ISAR_HIS_SARTCFG 0x25 @@ -43,6 +45,10 @@ #define ISAR_HIS_DPS2 0x80 #define SET_DPS(x) ((x<<6) & 0xc0) +#define ISAR_CMD_TIMERIRQ_OFF 0x20 +#define ISAR_CMD_TIMERIRQ_ON 0x21 + + #define ISAR_IIS_MSCMSD 0x3f #define ISAR_IIS_VNR 0x15 #define ISAR_IIS_DKEY 0x03 @@ -207,8 +213,10 @@ #define STFAX_ESCAPE 5 #define STFAX_SILDET 6 +#define ISDN_FAXPUMP_HALT 100 + +extern int ISARVersion(struct IsdnCardState *cs, char *s); extern void isar_int_main(struct IsdnCardState *cs); extern void initisar(struct IsdnCardState *cs); extern void isar_fill_fifo(struct BCState *bcs); extern int isar_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic); -extern int isar_setup(struct IsdnCardState *cs, struct bc_hw_ops *isar_ops); diff -Nru a/drivers/isdn/hisax/isdnhdlc.c b/drivers/isdn/hisax/isdnhdlc.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/isdn/hisax/isdnhdlc.c Thu Feb 19 23:44:29 2004 @@ -0,0 +1,669 @@ +/* + * isdnhdlc.c -- General purpose ISDN HDLC decoder. + * + *Copyright (C) 2002 Wolfgang Mües + * 2001 Frode Isaksen + * 2001 Kai Germaschewski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include "isdnhdlc.h" + +/*-------------------------------------------------------------------*/ + +MODULE_AUTHOR("Wolfgang Mües , " + "Frode Isaksen , " + "Kai Germaschewski "); +MODULE_DESCRIPTION("General purpose ISDN HDLC decoder"); +MODULE_LICENSE("GPL"); + +/*-------------------------------------------------------------------*/ + +/* bit swap table. + * Very handy for devices with different bit order, + * and neccessary for each transparent B-channel access for all + * devices which works with this HDLC decoder without bit reversal. + */ +const unsigned char isdnhdlc_bit_rev_tab[256] = { + 0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0, + 0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8, + 0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4, + 0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC, + 0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2, + 0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA, + 0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6, + 0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE, + 0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1, + 0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9, + 0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5, + 0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD, + 0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3, + 0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB, + 0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7, + 0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF +}; + +/* Table for CRC16. Internal used only. */ +static const unsigned short int crc16_tab[] = { + 0x0000,0x1189,0x2312,0x329b,0x4624,0x57ad,0x6536,0x74bf, + 0x8c48,0x9dc1,0xaf5a,0xbed3,0xca6c,0xdbe5,0xe97e,0xf8f7, + 0x1081,0x0108,0x3393,0x221a,0x56a5,0x472c,0x75b7,0x643e, + 0x9cc9,0x8d40,0xbfdb,0xae52,0xdaed,0xcb64,0xf9ff,0xe876, + 0x2102,0x308b,0x0210,0x1399,0x6726,0x76af,0x4434,0x55bd, + 0xad4a,0xbcc3,0x8e58,0x9fd1,0xeb6e,0xfae7,0xc87c,0xd9f5, + 0x3183,0x200a,0x1291,0x0318,0x77a7,0x662e,0x54b5,0x453c, + 0xbdcb,0xac42,0x9ed9,0x8f50,0xfbef,0xea66,0xd8fd,0xc974, + 0x4204,0x538d,0x6116,0x709f,0x0420,0x15a9,0x2732,0x36bb, + 0xce4c,0xdfc5,0xed5e,0xfcd7,0x8868,0x99e1,0xab7a,0xbaf3, + 0x5285,0x430c,0x7197,0x601e,0x14a1,0x0528,0x37b3,0x263a, + 0xdecd,0xcf44,0xfddf,0xec56,0x98e9,0x8960,0xbbfb,0xaa72, + 0x6306,0x728f,0x4014,0x519d,0x2522,0x34ab,0x0630,0x17b9, + 0xef4e,0xfec7,0xcc5c,0xddd5,0xa96a,0xb8e3,0x8a78,0x9bf1, + 0x7387,0x620e,0x5095,0x411c,0x35a3,0x242a,0x16b1,0x0738, + 0xffcf,0xee46,0xdcdd,0xcd54,0xb9eb,0xa862,0x9af9,0x8b70, + 0x8408,0x9581,0xa71a,0xb693,0xc22c,0xd3a5,0xe13e,0xf0b7, + 0x0840,0x19c9,0x2b52,0x3adb,0x4e64,0x5fed,0x6d76,0x7cff, + 0x9489,0x8500,0xb79b,0xa612,0xd2ad,0xc324,0xf1bf,0xe036, + 0x18c1,0x0948,0x3bd3,0x2a5a,0x5ee5,0x4f6c,0x7df7,0x6c7e, + 0xa50a,0xb483,0x8618,0x9791,0xe32e,0xf2a7,0xc03c,0xd1b5, + 0x2942,0x38cb,0x0a50,0x1bd9,0x6f66,0x7eef,0x4c74,0x5dfd, + 0xb58b,0xa402,0x9699,0x8710,0xf3af,0xe226,0xd0bd,0xc134, + 0x39c3,0x284a,0x1ad1,0x0b58,0x7fe7,0x6e6e,0x5cf5,0x4d7c, + 0xc60c,0xd785,0xe51e,0xf497,0x8028,0x91a1,0xa33a,0xb2b3, + 0x4a44,0x5bcd,0x6956,0x78df,0x0c60,0x1de9,0x2f72,0x3efb, + 0xd68d,0xc704,0xf59f,0xe416,0x90a9,0x8120,0xb3bb,0xa232, + 0x5ac5,0x4b4c,0x79d7,0x685e,0x1ce1,0x0d68,0x3ff3,0x2e7a, + 0xe70e,0xf687,0xc41c,0xd595,0xa12a,0xb0a3,0x8238,0x93b1, + 0x6b46,0x7acf,0x4854,0x59dd,0x2d62,0x3ceb,0x0e70,0x1ff9, + 0xf78f,0xe606,0xd49d,0xc514,0xb1ab,0xa022,0x92b9,0x8330, + 0x7bc7,0x6a4e,0x58d5,0x495c,0x3de3,0x2c6a,0x1ef1,0x0f78 +}; + + +enum { + HDLC_FAST_IDLE,HDLC_GET_FLAG_B0,HDLC_GETFLAG_B1A6,HDLC_GETFLAG_B7, + HDLC_GET_DATA,HDLC_FAST_FLAG +}; + +enum { + HDLC_SEND_DATA,HDLC_SEND_CRC1,HDLC_SEND_FAST_FLAG, + HDLC_SEND_FIRST_FLAG,HDLC_SEND_CRC2,HDLC_SEND_CLOSING_FLAG, + HDLC_SEND_IDLE1,HDLC_SEND_FAST_IDLE,HDLC_SENDFLAG_B0, + HDLC_SENDFLAG_B1A6,HDLC_SENDFLAG_B7,STOPPED +}; + +void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56) +{ + hdlc->bit_shift = 0; + hdlc->hdlc_bits1 = 0; + hdlc->data_bits = 0; + hdlc->ffbit_shift = 0; + hdlc->data_received = 0; + hdlc->state = HDLC_GET_DATA; + hdlc->do_adapt56 = do_adapt56; + hdlc->dchannel = 0; + hdlc->crc = 0; + hdlc->cbin = 0; + hdlc->shift_reg = 0; + hdlc->ffvalue = 0; + hdlc->dstpos = 0; +} + +void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc, int is_d_channel, int do_adapt56) +{ + hdlc->bit_shift = 0; + hdlc->hdlc_bits1 = 0; + hdlc->data_bits = 0; + hdlc->ffbit_shift = 0; + hdlc->data_received = 0; + hdlc->do_closing = 0; + hdlc->ffvalue = 0; + if (is_d_channel) { + hdlc->dchannel = 1; + hdlc->state = HDLC_SEND_FIRST_FLAG; + } else { + hdlc->dchannel = 0; + hdlc->state = HDLC_SEND_FAST_FLAG; + hdlc->ffvalue = 0x7e; + } + hdlc->cbin = 0x7e; + hdlc->bit_shift = 0; + if(do_adapt56){ + hdlc->do_adapt56 = 1; + hdlc->data_bits = 0; + hdlc->state = HDLC_SENDFLAG_B0; + } else { + hdlc->do_adapt56 = 0; + hdlc->data_bits = 8; + } + hdlc->shift_reg = 0; +} + +/* + isdnhdlc_decode - decodes HDLC frames from a transparent bit stream. + + The source buffer is scanned for valid HDLC frames looking for + flags (01111110) to indicate the start of a frame. If the start of + the frame is found, the bit stuffing is removed (0 after 5 1's). + When a new flag is found, the complete frame has been received + and the CRC is checked. + If a valid frame is found, the function returns the frame length + excluding the CRC with the bit HDLC_END_OF_FRAME set. + If the beginning of a valid frame is found, the function returns + the length. + If a framing error is found (too many 1s and not a flag) the function + returns the length with the bit HDLC_FRAMING_ERROR set. + If a CRC error is found the function returns the length with the + bit HDLC_CRC_ERROR set. + If the frame length exceeds the destination buffer size, the function + returns the length with the bit HDLC_LENGTH_ERROR set. + + src - source buffer + slen - source buffer length + count - number of bytes removed (decoded) from the source buffer + dst _ destination buffer + dsize - destination buffer size + returns - number of decoded bytes in the destination buffer and status + flag. + */ +int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, + int slen, int *count, unsigned char *dst, int dsize) +{ + int status=0; + + static const unsigned char fast_flag[]={ + 0x00,0x00,0x00,0x20,0x30,0x38,0x3c,0x3e,0x3f + }; + + static const unsigned char fast_flag_value[]={ + 0x00,0x7e,0xfc,0xf9,0xf3,0xe7,0xcf,0x9f,0x3f + }; + + static const unsigned char fast_abort[]={ + 0x00,0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff + }; + + *count = slen; + + while(slen > 0){ + if(hdlc->bit_shift==0){ + hdlc->cbin = *src++; + slen--; + hdlc->bit_shift = 8; + if(hdlc->do_adapt56){ + hdlc->bit_shift --; + } + } + + switch(hdlc->state){ + case STOPPED: + return 0; + case HDLC_FAST_IDLE: + if(hdlc->cbin == 0xff){ + hdlc->bit_shift = 0; + break; + } + hdlc->state = HDLC_GET_FLAG_B0; + hdlc->hdlc_bits1 = 0; + hdlc->bit_shift = 8; + break; + case HDLC_GET_FLAG_B0: + if(!(hdlc->cbin & 0x80)) { + hdlc->state = HDLC_GETFLAG_B1A6; + hdlc->hdlc_bits1 = 0; + } else { + if(!hdlc->do_adapt56){ + if(++hdlc->hdlc_bits1 >=8 ) if(hdlc->bit_shift==1) + hdlc->state = HDLC_FAST_IDLE; + } + } + hdlc->cbin<<=1; + hdlc->bit_shift --; + break; + case HDLC_GETFLAG_B1A6: + if(hdlc->cbin & 0x80){ + hdlc->hdlc_bits1++; + if(hdlc->hdlc_bits1==6){ + hdlc->state = HDLC_GETFLAG_B7; + } + } else { + hdlc->hdlc_bits1 = 0; + } + hdlc->cbin<<=1; + hdlc->bit_shift --; + break; + case HDLC_GETFLAG_B7: + if(hdlc->cbin & 0x80) { + hdlc->state = HDLC_GET_FLAG_B0; + } else { + hdlc->state = HDLC_GET_DATA; + hdlc->crc = 0xffff; + hdlc->shift_reg = 0; + hdlc->hdlc_bits1 = 0; + hdlc->data_bits = 0; + hdlc->data_received = 0; + } + hdlc->cbin<<=1; + hdlc->bit_shift --; + break; + case HDLC_GET_DATA: + if(hdlc->cbin & 0x80){ + hdlc->hdlc_bits1++; + switch(hdlc->hdlc_bits1){ + case 6: + break; + case 7: + if(hdlc->data_received) { + // bad frame + status = -HDLC_FRAMING_ERROR; + } + if(!hdlc->do_adapt56){ + if(hdlc->cbin==fast_abort[hdlc->bit_shift+1]){ + hdlc->state = HDLC_FAST_IDLE; + hdlc->bit_shift=1; + break; + } + } else { + hdlc->state = HDLC_GET_FLAG_B0; + } + break; + default: + hdlc->shift_reg>>=1; + hdlc->shift_reg |= 0x80; + hdlc->data_bits++; + break; + } + } else { + switch(hdlc->hdlc_bits1){ + case 5: + break; + case 6: + if(hdlc->data_received){ + if (hdlc->dstpos < 2) { + status = -HDLC_FRAMING_ERROR; + } else if (hdlc->crc != 0xf0b8){ + // crc error + status = -HDLC_CRC_ERROR; + } else { + // remove CRC + hdlc->dstpos -= 2; + // good frame + status = hdlc->dstpos; + } + } + hdlc->crc = 0xffff; + hdlc->shift_reg = 0; + hdlc->data_bits = 0; + if(!hdlc->do_adapt56){ + if(hdlc->cbin==fast_flag[hdlc->bit_shift]){ + hdlc->ffvalue = fast_flag_value[hdlc->bit_shift]; + hdlc->state = HDLC_FAST_FLAG; + hdlc->ffbit_shift = hdlc->bit_shift; + hdlc->bit_shift = 1; + } else { + hdlc->state = HDLC_GET_DATA; + hdlc->data_received = 0; + } + } else { + hdlc->state = HDLC_GET_DATA; + hdlc->data_received = 0; + } + break; + default: + hdlc->shift_reg>>=1; + hdlc->data_bits++; + break; + } + hdlc->hdlc_bits1 = 0; + } + if (status) { + hdlc->dstpos = 0; + *count -= slen; + hdlc->cbin <<= 1; + hdlc->bit_shift--; + return status; + } + if(hdlc->data_bits==8){ + unsigned cval; + + hdlc->data_bits = 0; + hdlc->data_received = 1; + cval = (hdlc->crc^hdlc->shift_reg) & 0xff; + hdlc->crc = (hdlc->crc>>8)^crc16_tab[cval]; + // good byte received + if (dsize--) { + dst[hdlc->dstpos++] = hdlc->shift_reg; + } else { + // frame too long + status = -HDLC_LENGTH_ERROR; + hdlc->dstpos = 0; + } + } + hdlc->cbin <<= 1; + hdlc->bit_shift--; + break; + case HDLC_FAST_FLAG: + if(hdlc->cbin==hdlc->ffvalue){ + hdlc->bit_shift = 0; + break; + } else { + if(hdlc->cbin == 0xff){ + hdlc->state = HDLC_FAST_IDLE; + hdlc->bit_shift=0; + } else if(hdlc->ffbit_shift==8){ + hdlc->state = HDLC_GETFLAG_B7; + break; + } else { + hdlc->shift_reg = fast_abort[hdlc->ffbit_shift-1]; + hdlc->hdlc_bits1 = hdlc->ffbit_shift-2; + if(hdlc->hdlc_bits1<0)hdlc->hdlc_bits1 = 0; + hdlc->data_bits = hdlc->ffbit_shift-1; + hdlc->state = HDLC_GET_DATA; + hdlc->data_received = 0; + } + } + break; + default: + break; + } + } + *count -= slen; + return 0; +} + +/* + isdnhdlc_encode - encodes HDLC frames to a transparent bit stream. + + The bit stream starts with a beginning flag (01111110). After + that each byte is added to the bit stream with bit stuffing added + (0 after 5 1's). + When the last byte has been removed from the source buffer, the + CRC (2 bytes is added) and the frame terminates with the ending flag. + For the dchannel, the idle character (all 1's) is also added at the end. + If this function is called with empty source buffer (slen=0), flags or + idle character will be generated. + + src - source buffer + slen - source buffer length + count - number of bytes removed (encoded) from source buffer + dst _ destination buffer + dsize - destination buffer size + returns - number of encoded bytes in the destination buffer +*/ +int isdnhdlc_encode(struct isdnhdlc_vars *hdlc, const unsigned char *src, + unsigned short slen, int *count, + unsigned char *dst, int dsize) +{ + static const unsigned char xfast_flag_value[] = { + 0x7e,0x3f,0x9f,0xcf,0xe7,0xf3,0xf9,0xfc,0x7e + }; + + int len = 0; + + *count = slen; + + while (dsize > 0) { + if(hdlc->bit_shift==0){ + if(slen && !hdlc->do_closing){ + hdlc->shift_reg = *src++; + slen--; + if (slen == 0) + hdlc->do_closing = 1; /* closing sequence, CRC + flag(s) */ + hdlc->bit_shift = 8; + } else { + if(hdlc->state == HDLC_SEND_DATA){ + if(hdlc->data_received){ + hdlc->state = HDLC_SEND_CRC1; + hdlc->crc ^= 0xffff; + hdlc->bit_shift = 8; + hdlc->shift_reg = hdlc->crc & 0xff; + } else if(!hdlc->do_adapt56){ + hdlc->state = HDLC_SEND_FAST_FLAG; + } else { + hdlc->state = HDLC_SENDFLAG_B0; + } + } + + } + } + + switch(hdlc->state){ + case STOPPED: + while (dsize--) + *dst++ = 0xff; + + return dsize; + case HDLC_SEND_FAST_FLAG: + hdlc->do_closing = 0; + if(slen == 0){ + *dst++ = hdlc->ffvalue; + len++; + dsize--; + break; + } + if(hdlc->bit_shift==8){ + hdlc->cbin = hdlc->ffvalue>>(8-hdlc->data_bits); + hdlc->state = HDLC_SEND_DATA; + hdlc->crc = 0xffff; + hdlc->hdlc_bits1 = 0; + hdlc->data_received = 1; + } + break; + case HDLC_SENDFLAG_B0: + hdlc->do_closing = 0; + hdlc->cbin <<= 1; + hdlc->data_bits++; + hdlc->hdlc_bits1 = 0; + hdlc->state = HDLC_SENDFLAG_B1A6; + break; + case HDLC_SENDFLAG_B1A6: + hdlc->cbin <<= 1; + hdlc->data_bits++; + hdlc->cbin++; + if(++hdlc->hdlc_bits1 == 6) + hdlc->state = HDLC_SENDFLAG_B7; + break; + case HDLC_SENDFLAG_B7: + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(slen == 0){ + hdlc->state = HDLC_SENDFLAG_B0; + break; + } + if(hdlc->bit_shift==8){ + hdlc->state = HDLC_SEND_DATA; + hdlc->crc = 0xffff; + hdlc->hdlc_bits1 = 0; + hdlc->data_received = 1; + } + break; + case HDLC_SEND_FIRST_FLAG: + hdlc->data_received = 1; + if(hdlc->data_bits==8){ + hdlc->state = HDLC_SEND_DATA; + hdlc->crc = 0xffff; + hdlc->hdlc_bits1 = 0; + break; + } + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(hdlc->shift_reg & 0x01) + hdlc->cbin++; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + if(hdlc->bit_shift==0){ + hdlc->state = HDLC_SEND_DATA; + hdlc->crc = 0xffff; + hdlc->hdlc_bits1 = 0; + } + break; + case HDLC_SEND_DATA: + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(hdlc->hdlc_bits1 == 5){ + hdlc->hdlc_bits1 = 0; + break; + } + if(hdlc->bit_shift==8){ + unsigned cval; + + cval = (hdlc->crc^hdlc->shift_reg) & 0xff; + hdlc->crc = (hdlc->crc>>8)^crc16_tab[cval]; + } + if(hdlc->shift_reg & 0x01){ + hdlc->hdlc_bits1++; + hdlc->cbin++; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } else { + hdlc->hdlc_bits1 = 0; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } + break; + case HDLC_SEND_CRC1: + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(hdlc->hdlc_bits1 == 5){ + hdlc->hdlc_bits1 = 0; + break; + } + if(hdlc->shift_reg & 0x01){ + hdlc->hdlc_bits1++; + hdlc->cbin++; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } else { + hdlc->hdlc_bits1 = 0; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } + if(hdlc->bit_shift==0){ + hdlc->shift_reg = (hdlc->crc >> 8); + hdlc->state = HDLC_SEND_CRC2; + hdlc->bit_shift = 8; + } + break; + case HDLC_SEND_CRC2: + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(hdlc->hdlc_bits1 == 5){ + hdlc->hdlc_bits1 = 0; + break; + } + if(hdlc->shift_reg & 0x01){ + hdlc->hdlc_bits1++; + hdlc->cbin++; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } else { + hdlc->hdlc_bits1 = 0; + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + } + if(hdlc->bit_shift==0){ + hdlc->shift_reg = 0x7e; + hdlc->state = HDLC_SEND_CLOSING_FLAG; + hdlc->bit_shift = 8; + } + break; + case HDLC_SEND_CLOSING_FLAG: + hdlc->cbin <<= 1; + hdlc->data_bits++; + if(hdlc->hdlc_bits1 == 5){ + hdlc->hdlc_bits1 = 0; + break; + } + if(hdlc->shift_reg & 0x01){ + hdlc->cbin++; + } + hdlc->shift_reg >>= 1; + hdlc->bit_shift--; + if(hdlc->bit_shift==0){ + hdlc->ffvalue = xfast_flag_value[hdlc->data_bits]; + if(hdlc->dchannel){ + hdlc->ffvalue = 0x7e; + hdlc->state = HDLC_SEND_IDLE1; + hdlc->bit_shift = 8-hdlc->data_bits; + if(hdlc->bit_shift==0) + hdlc->state = HDLC_SEND_FAST_IDLE; + } else { + if(!hdlc->do_adapt56){ + hdlc->state = HDLC_SEND_FAST_FLAG; + hdlc->data_received = 0; + } else { + hdlc->state = HDLC_SENDFLAG_B0; + hdlc->data_received = 0; + } + // Finished with this frame, send flags + if (dsize > 1) dsize = 1; + } + } + break; + case HDLC_SEND_IDLE1: + hdlc->do_closing = 0; + hdlc->cbin <<= 1; + hdlc->cbin++; + hdlc->data_bits++; + hdlc->bit_shift--; + if(hdlc->bit_shift==0){ + hdlc->state = HDLC_SEND_FAST_IDLE; + hdlc->bit_shift = 0; + } + break; + case HDLC_SEND_FAST_IDLE: + hdlc->do_closing = 0; + hdlc->cbin = 0xff; + hdlc->data_bits = 8; + if(hdlc->bit_shift == 8){ + hdlc->cbin = 0x7e; + hdlc->state = HDLC_SEND_FIRST_FLAG; + } else { + *dst++ = hdlc->cbin; + hdlc->bit_shift = hdlc->data_bits = 0; + len++; + dsize = 0; + } + break; + default: + break; + } + if(hdlc->do_adapt56){ + if(hdlc->data_bits==7){ + hdlc->cbin <<= 1; + hdlc->cbin++; + hdlc->data_bits++; + } + } + if(hdlc->data_bits==8){ + *dst++ = hdlc->cbin; + hdlc->data_bits = 0; + len++; + dsize--; + } + } + *count -= slen; + + return len; +} + +EXPORT_SYMBOL(isdnhdlc_bit_rev_tab); +EXPORT_SYMBOL(isdnhdlc_rcv_init); +EXPORT_SYMBOL(isdnhdlc_decode); +EXPORT_SYMBOL(isdnhdlc_out_init); +EXPORT_SYMBOL(isdnhdlc_encode); diff -Nru a/drivers/isdn/hisax/isdnhdlc.h b/drivers/isdn/hisax/isdnhdlc.h --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/isdn/hisax/isdnhdlc.h Thu Feb 19 23:44:29 2004 @@ -0,0 +1,72 @@ +/* + * isdnhdlc.h -- General purpose ISDN HDLC decoder. + * + * Implementation of a HDLC decoder/encoder in software. + * Neccessary because some ISDN devices don't have HDLC + * controllers. Also included: a bit reversal table. + * + *Copyright (C) 2002 Wolfgang Mües + * 2001 Frode Isaksen + * 2001 Kai Germaschewski + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __ISDNHDLC_H__ +#define __ISDNHDLC_H__ + +struct isdnhdlc_vars { + int bit_shift; + int hdlc_bits1; + int data_bits; + int ffbit_shift; // encoding only + int state; + int dstpos; + + unsigned short crc; + + unsigned char cbin; + unsigned char shift_reg; + unsigned char ffvalue; + + int data_received:1; // set if transferring data + int dchannel:1; // set if D channel (send idle instead of flags) + int do_adapt56:1; // set if 56K adaptation + int do_closing:1; // set if in closing phase (need to send CRC + flag +}; + + +/* + The return value from isdnhdlc_decode is + the frame length, 0 if no complete frame was decoded, + or a negative error number +*/ +#define HDLC_FRAMING_ERROR 1 +#define HDLC_CRC_ERROR 2 +#define HDLC_LENGTH_ERROR 3 + +extern const unsigned char isdnhdlc_bit_rev_tab[256]; + +extern void isdnhdlc_rcv_init (struct isdnhdlc_vars *hdlc, int do_adapt56); + +extern int isdnhdlc_decode (struct isdnhdlc_vars *hdlc, const unsigned char *src, int slen,int *count, + unsigned char *dst, int dsize); + +extern void isdnhdlc_out_init (struct isdnhdlc_vars *hdlc,int is_d_channel,int do_adapt56); + +extern int isdnhdlc_encode (struct isdnhdlc_vars *hdlc,const unsigned char *src,unsigned short slen,int *count, + unsigned char *dst,int dsize); + +#endif /* __ISDNHDLC_H__ */ diff -Nru a/drivers/isdn/hisax/isdnl1.c b/drivers/isdn/hisax/isdnl1.c --- a/drivers/isdn/hisax/isdnl1.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hisax/isdnl1.c Thu Feb 19 23:44:24 2004 @@ -1,4 +1,4 @@ -/* $Id: isdnl1.c,v 2.41.6.5 2001/09/23 22:24:49 kai Exp $ +/* $Id: isdnl1.c,v 2.46.2.5 2004/02/11 13:21:34 keil Exp $ * * common low level stuff for Siemens Chipsetbased isdn cards * @@ -18,7 +18,7 @@ * */ -const char *l1_revision = "$Revision: 2.41.6.5 $"; +const char *l1_revision = "$Revision: 2.46.2.5 $"; #include #include "hisax.h" @@ -126,7 +126,7 @@ }; void -debugl1(struct IsdnCardState *cs, const char *fmt, ...) +debugl1(struct IsdnCardState *cs, char *fmt, ...) { va_list args; char tmp[8]; @@ -159,9 +159,9 @@ st = cs->stlist; while (st) { if (test_and_clear_bit(FLG_L1_ACTIVATING, &st->l1.Flags)) - L1L2(st, PH_ACTIVATE | CONFIRM, NULL); + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); else - L1L2(st, PH_ACTIVATE | INDICATION, NULL); + st->l1.l1l2(st, PH_ACTIVATE | INDICATION, NULL); st = st->next; } } @@ -174,8 +174,8 @@ st = cs->stlist; while (st) { if (test_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - L1L2(st, PH_PAUSE | CONFIRM, NULL); - L1L2(st, PH_DEACTIVATE | INDICATION, NULL); + st->l1.l1l2(st, PH_PAUSE | CONFIRM, NULL); + st->l1.l1l2(st, PH_DEACTIVATE | INDICATION, NULL); st = st->next; } test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags); @@ -190,12 +190,13 @@ return; stptr = cs->stlist; - while (stptr != NULL) + while (stptr != NULL) { if (test_and_clear_bit(FLG_L1_PULL_REQ, &stptr->l1.Flags)) { - L1L2(stptr, PH_PULL | CONFIRM, NULL); + stptr->l1.l1l2(stptr, PH_PULL | CONFIRM, NULL); break; } else stptr = stptr->next; + } } void @@ -234,7 +235,7 @@ if (sapi == CTRL_SAPI) { /* sapi 0 */ while (stptr != NULL) { if ((nskb = skb_clone(skb, GFP_ATOMIC))) - L1L2(stptr, PH_DATA | INDICATION, nskb); + stptr->l1.l1l2(stptr, PH_DATA | INDICATION, nskb); else printk(KERN_WARNING "HiSax: isdn broadcast buffer shortage\n"); stptr = stptr->next; @@ -253,7 +254,7 @@ found = 0; while (stptr != NULL) if (tei == stptr->l2.tei) { - L1L2(stptr, PH_DATA | INDICATION, skb); + stptr->l1.l1l2(stptr, PH_DATA | INDICATION, skb); found = !0; break; } else @@ -276,10 +277,10 @@ } if (test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags)) - L1L2(st, PH_PULL | CONFIRM, NULL); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); if (!test_bit(BC_FLG_ACTIV, &bcs->Flag)) { if (!test_bit(BC_FLG_BUSY, &bcs->Flag) && (!skb_queue_len(&bcs->squeue))) { - L2L1(st, PH_DEACTIVATE | CONFIRM, NULL); + st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL); } } } @@ -294,31 +295,35 @@ FsmEvent(&bcs->st->l1.l1m, EV_TIMER_ACT, NULL); } while ((skb = skb_dequeue(&bcs->rqueue))) { - L1L2(bcs->st, PH_DATA | INDICATION, skb); + bcs->st->l1.l1l2(bcs->st, PH_DATA | INDICATION, skb); } } static void -BChannel_proc_cmpl(struct BCState *bcs) +BChannel_proc_ack(struct BCState *bcs) { - struct sk_buff *skb; + u_long flags; + int ack; - while ((skb = skb_dequeue(&bcs->cmpl_queue))) { - L1L2(bcs->st, PH_DATA | CONFIRM, skb); - } + spin_lock_irqsave(&bcs->aclock, flags); + ack = bcs->ackcnt; + bcs->ackcnt = 0; + spin_unlock_irqrestore(&bcs->aclock, flags); + if (ack) + lli_writewakeup(bcs->st, ack); } void -BChannel_bh(void *data) +BChannel_bh(struct BCState *bcs) { - struct BCState *bcs = data; - + if (!bcs) + return; if (test_and_clear_bit(B_RCVBUFREADY, &bcs->event)) BChannel_proc_rcv(bcs); if (test_and_clear_bit(B_XMTBUFREADY, &bcs->event)) BChannel_proc_xmt(bcs); - if (test_and_clear_bit(B_CMPLREADY, &bcs->event)) - BChannel_proc_cmpl(bcs); + if (test_and_clear_bit(B_ACKPENDING, &bcs->event)) + BChannel_proc_ack(bcs); } void @@ -350,21 +355,23 @@ } void -init_bcstate(struct IsdnCardState *cs, - int bc) +init_bcstate(struct IsdnCardState *cs, int bc) { struct BCState *bcs = cs->bcs + bc; bcs->cs = cs; bcs->channel = bc; - INIT_WORK(&bcs->work, BChannel_bh, bcs); + INIT_WORK(&bcs->tqueue, (void *)(void *) BChannel_bh, bcs); + spin_lock_init(&bcs->aclock); + bcs->BC_SetStack = NULL; + bcs->BC_Close = NULL; bcs->Flag = 0; } #ifdef L2FRAME_DEBUG /* psa */ char * -l2cmd(u8 cmd) +l2cmd(u_char cmd) { switch (cmd & ~0x10) { case 1: @@ -398,7 +405,7 @@ static char tmpdeb[32]; char * -l2frames(u8 * ptr) +l2frames(u_char * ptr) { switch (ptr[2] & ~0x10) { case 1: @@ -430,7 +437,7 @@ void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir) { - u8 *ptr; + u_char *ptr; ptr = skb->data; @@ -724,7 +731,7 @@ struct PStack *st = fi->userdata; FsmChangeState(fi, ST_L1_ACTIV); - L1L2(st, PH_ACTIVATE | CONFIRM, NULL); + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); } static void @@ -733,7 +740,7 @@ struct PStack *st = fi->userdata; FsmChangeState(fi, ST_L1_NULL); - L2L1(st, PH_DEACTIVATE | CONFIRM, NULL); + st->l2.l2l1(st, PH_DEACTIVATE | CONFIRM, NULL); } static struct FsmNode L1BFnList[] __initdata = @@ -808,7 +815,7 @@ debugl1(cs, "PH_ACTIVATE_REQ %s", st->l1.l1m.fsm->strState[st->l1.l1m.state]); if (test_bit(FLG_L1_ACTIVATED, &st->l1.Flags)) - L1L2(st, PH_ACTIVATE | CONFIRM, NULL); + st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL); else { test_and_set_bit(FLG_L1_ACTIVATING, &st->l1.Flags); FsmEvent(&st->l1.l1m, EV_PH_ACTIVATE, arg); @@ -904,19 +911,9 @@ setstack_tei(st); setstack_manager(st); st->l1.stlistp = &(cs->stlist); - st->l1.l2l1 = dch_l2l1; - if (cs->dc_l1_ops->open) - cs->dc_l1_ops->open(st, cs); -} - -void -dc_l1_init(struct IsdnCardState *cs, struct dc_l1_ops *ops) -{ - cs->dc_l1_ops = ops; - INIT_WORK(&cs->work, ops->bh_func, cs); - init_timer(&cs->dbusytimer); - cs->dbusytimer.function = (void *)(unsigned long) ops->dbusy_func; - cs->dbusytimer.data = (unsigned long) cs; + st->l2.l2l1 = dch_l2l1; + if (cs->setstack_d) + cs->setstack_d(st, cs); } void diff -Nru a/drivers/isdn/hisax/isdnl1.h b/drivers/isdn/hisax/isdnl1.h --- a/drivers/isdn/hisax/isdnl1.h Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/hisax/isdnl1.h Thu Feb 19 23:44:27 2004 @@ -1,4 +1,4 @@ -/* $Id: isdnl1.h,v 2.9.6.3 2001/09/23 22:24:49 kai Exp $ +/* $Id: isdnl1.h,v 2.12.2.3 2004/02/11 13:21:34 keil Exp $ * * Layer 1 defines * @@ -7,9 +7,6 @@ * */ -#ifndef __ISDNL1_H__ -#define __ISDNL1_H__ - #define D_RCVBUFREADY 0 #define D_XMTBUFREADY 1 #define D_L1STATECHANGE 2 @@ -20,578 +17,16 @@ #define D_TX_MON1 7 #define E_RCVBUFREADY 8 -#define B_RCVBUFREADY 0 -#define B_XMTBUFREADY 1 -#define B_CMPLREADY 2 - -#define B_LL_NOCARRIER 8 -#define B_LL_CONNECT 9 -#define B_LL_OK 10 +#define B_RCVBUFREADY 0 +#define B_XMTBUFREADY 1 +#define B_ACKPENDING 2 -extern void debugl1(struct IsdnCardState *cs, const char *fmt, ...); +extern void debugl1(struct IsdnCardState *cs, char *fmt, ...); extern void DChannel_proc_xmt(struct IsdnCardState *cs); extern void DChannel_proc_rcv(struct IsdnCardState *cs); extern void l1_msg(struct IsdnCardState *cs, int pr, void *arg); extern void l1_msg_b(struct PStack *st, int pr, void *arg); -void dc_l1_init(struct IsdnCardState *cs, struct dc_l1_ops *ops); - -static inline void -fill_fifo_b(struct BCState *bcs) -{ - bcs->cs->bc_l1_ops->fill_fifo(bcs); -} - -static inline void -fill_fifo_d(struct IsdnCardState *cs) -{ - cs->dc_l1_ops->fill_fifo(cs); -} - #ifdef L2FRAME_DEBUG extern void Logl2Frame(struct IsdnCardState *cs, struct sk_buff *skb, char *buf, int dir); -#endif - -static inline void -sched_b_event(struct BCState *bcs, int event) -{ - set_bit(event, &bcs->event); - schedule_work(&bcs->work); -} - -static inline void -sched_d_event(struct IsdnCardState *cs, int event) -{ - set_bit(event, &cs->event); - schedule_work(&cs->work); -} - -/* called with the card lock held */ -static inline void -xmit_complete_b(struct BCState *bcs) -{ - skb_queue_tail(&bcs->cmpl_queue, bcs->tx_skb); - sched_b_event(bcs, B_CMPLREADY); - bcs->tx_skb = NULL; -} - -/* called with the card lock held */ -static inline void -xmit_complete_d(struct IsdnCardState *cs) -{ - dev_kfree_skb_irq(cs->tx_skb); - cs->tx_skb = NULL; -} - -/* called with the card lock held */ -static inline void -xmit_ready_b(struct BCState *bcs) -{ - bcs->tx_skb = skb_dequeue(&bcs->squeue); - if (bcs->tx_skb) { - bcs->count = 0; - set_bit(BC_FLG_BUSY, &bcs->Flag); - fill_fifo_b(bcs); - } else { - clear_bit(BC_FLG_BUSY, &bcs->Flag); - sched_b_event(bcs, B_XMTBUFREADY); - } -} - -/* called with the card lock held */ -static inline void -xmit_ready_d(struct IsdnCardState *cs) -{ - cs->tx_skb = skb_dequeue(&cs->sq); - if (cs->tx_skb) { - cs->tx_cnt = 0; - fill_fifo_d(cs); - } else { - sched_d_event(cs, D_XMTBUFREADY); - } -} - -static inline void -xmit_data_req_b(struct BCState *bcs, struct sk_buff *skb) -{ - struct IsdnCardState *cs = bcs->cs; - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - if (bcs->tx_skb) { - skb_queue_tail(&bcs->squeue, skb); - } else { - set_bit(BC_FLG_BUSY, &bcs->Flag); - bcs->tx_skb = skb; - bcs->count = 0; - fill_fifo_b(bcs); - } - spin_unlock_irqrestore(&cs->lock, flags); -} - -static inline void -xmit_data_req_d(struct IsdnCardState *cs, struct sk_buff *skb) -{ - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - if (cs->debug & DEB_DLOG_HEX) - LogFrame(cs, skb->data, skb->len); - if (cs->debug & DEB_DLOG_VERBOSE) - dlogframe(cs, skb, 0); - if (cs->tx_skb) { - skb_queue_tail(&cs->sq, skb); -#ifdef L2FRAME_DEBUG - if (cs->debug & L1_DEB_LAPD) - Logl2Frame(cs, skb, "PH_DATA Queued", 0); -#endif - } else { - cs->tx_skb = skb; - cs->tx_cnt = 0; -#ifdef L2FRAME_DEBUG - if (cs->debug & L1_DEB_LAPD) - Logl2Frame(cs, skb, "PH_DATA", 0); -#endif - fill_fifo_d(cs); - } - spin_unlock_irqrestore(&cs->lock, flags); -} - -static inline void -xmit_pull_ind_b(struct BCState *bcs, struct sk_buff *skb) -{ - struct IsdnCardState *cs = bcs->cs; - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - if (bcs->tx_skb) { - WARN_ON(1); - } else { - set_bit(BC_FLG_BUSY, &bcs->Flag); - bcs->tx_skb = skb; - bcs->count = 0; - fill_fifo_b(bcs); - } - spin_unlock_irqrestore(&cs->lock, flags); -} - -static inline void -xmit_pull_ind_d(struct IsdnCardState *cs, struct sk_buff *skb) -{ - unsigned long flags; - - spin_lock_irqsave(&cs->lock, flags); - if (cs->tx_skb) { - WARN_ON(1); - } else { - if (cs->debug & DEB_DLOG_HEX) - LogFrame(cs, skb->data, skb->len); - if (cs->debug & DEB_DLOG_VERBOSE) - dlogframe(cs, skb, 0); -#ifdef L2FRAME_DEBUG - if (cs->debug & L1_DEB_LAPD) - Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); -#endif - cs->tx_skb = skb; - cs->tx_cnt = 0; - fill_fifo_d(cs); - } - spin_unlock_irqrestore(&cs->lock, flags); -} - -/* If busy, the PH_PULL | CONFIRM scheduling is handled under - * the card lock by xmit_ready_b() above, so no race */ -static inline void -xmit_pull_req_b(struct PStack *st) -{ - struct BCState *bcs = st->l1.bcs; - struct IsdnCardState *cs = bcs->cs; - unsigned long flags; - int busy = 0; - - spin_lock_irqsave(&cs->lock, flags); - if (bcs->tx_skb) { - set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - busy = 1; - } - spin_unlock_irqrestore(&cs->lock, flags); - if (!busy) - L1L2(st, PH_PULL | CONFIRM, NULL); -} - -/* If busy, the PH_PULL | CONFIRM scheduling is handled under - * the card lock by xmit_ready_d() above, so no race */ -static inline void -xmit_pull_req_d(struct PStack *st) -{ - struct IsdnCardState *cs = st->l1.hardware; - unsigned long flags; - int busy = 0; - -#ifdef L2FRAME_DEBUG - if (cs->debug & L1_DEB_LAPD) - debugl1(cs, "-> PH_REQUEST_PULL"); -#endif - spin_lock_irqsave(&cs->lock, flags); - if (cs->tx_skb) { - set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); - busy = 1; - } - spin_unlock_irqrestore(&cs->lock, flags); - if (!busy) - L1L2(st, PH_PULL | CONFIRM, NULL); -} - -/* called with the card lock held */ -static inline void -xmit_restart_b(struct BCState *bcs) -{ -#ifdef ERROR_STATISTIC - bcs->err_tx++; -#endif - if (!bcs->tx_skb) { - WARN_ON(1); - return; - } - skb_push(bcs->tx_skb, bcs->count); - bcs->tx_cnt += bcs->count; - bcs->count = 0; -} - -/* called with the card lock held */ -static inline void -xmit_restart_d(struct IsdnCardState *cs) -{ -#ifdef ERROR_STATISTIC - cs->err_tx++; -#endif - if (!cs->tx_skb) { - WARN_ON(1); - return; - } - skb_push(cs->tx_skb, cs->tx_cnt); - cs->tx_cnt = 0; -} - -/* Useful for HSCX/ISAC work-alike's */ -/* ---------------------------------------------------------------------- */ - -/* XPR - transmit pool ready */ -/* called with the card lock held */ -static inline void -xmit_xpr_b(struct BCState *bcs) -{ - /* current frame? */ - if (bcs->tx_skb) { - /* last frame not done yet? */ - if (bcs->tx_skb->len) { - fill_fifo_b(bcs); - return; - } - xmit_complete_b(bcs); - bcs->count = 0; - } - xmit_ready_b(bcs); -} - -/* XPR - transmit pool ready */ -/* called with the card lock held */ -static inline void -xmit_xpr_d(struct IsdnCardState *cs) -{ - if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) - del_timer(&cs->dbusytimer); - if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); - /* current frame? */ - if (cs->tx_skb) { - /* last frame not done yet? */ - if (cs->tx_skb->len) { - fill_fifo_d(cs); - return; - } - xmit_complete_d(cs); - cs->tx_cnt = 0; - } - xmit_ready_d(cs); -} - -/* XDU - transmit data underrun */ -/* called with the card lock held */ -static inline void -xmit_xdu_b(struct BCState *bcs, void (*reset_xmit)(struct BCState *bcs)) -{ - struct IsdnCardState *cs = bcs->cs; - - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "HSCX %c EXIR XDU", 'A' + bcs->channel); - - if (bcs->mode == L1_MODE_TRANS) { - fill_fifo_b(bcs); - } else { - xmit_restart_b(bcs); - reset_xmit(bcs); - } -} - -/* XDU - transmit data underrun */ -/* called with the card lock held */ -static inline void -xmit_xdu_d(struct IsdnCardState *cs, void (*reset_xmit)(struct IsdnCardState *cs)) -{ - printk(KERN_WARNING "HiSax: D XDU\n"); - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "D XDU"); - - if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) - del_timer(&cs->dbusytimer); - if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); - - xmit_restart_d(cs); - if (reset_xmit) - reset_xmit(cs); -} - -static inline unsigned char * -xmit_fill_fifo_b(struct BCState *bcs, u_int fifo_size, int *count, int *more) -{ - struct IsdnCardState *cs = bcs->cs; - unsigned char *p; - - if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) - debugl1(cs, __FUNCTION__); - - if (!bcs->tx_skb || bcs->tx_skb->len <= 0) { - WARN_ON(1); - return NULL; - } - - *more = (bcs->mode == L1_MODE_TRANS); - if (bcs->tx_skb->len > fifo_size) { - *more = 1; - *count = fifo_size; - } else { - *count = bcs->tx_skb->len; - } - p = bcs->tx_skb->data; - skb_pull(bcs->tx_skb, *count); - bcs->tx_cnt -= *count; - bcs->count += *count; - - if (cs->debug & L1_DEB_HSCX_FIFO) { - char *t = bcs->blog; - - t += sprintf(t, "%s %c cnt %d", __FUNCTION__, - bcs->unit ? 'B' : 'A', *count); - QuickHex(t, p, *count); - debugl1(cs, bcs->blog); - } - return p; -} - -static inline unsigned char * -xmit_fill_fifo_d(struct IsdnCardState *cs, u_int fifo_size, int *count, int *more) -{ - unsigned char *p; - - if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) - debugl1(cs, __FUNCTION__); - - if (!cs->tx_skb || cs->tx_skb->len <= 0) { - WARN_ON(1); - return NULL; - } - - *more = 0; - if (cs->tx_skb->len > fifo_size) { - *more = 1; - *count = fifo_size; - } else { - *count = cs->tx_skb->len; - } - - p = cs->tx_skb->data; - skb_pull(cs->tx_skb, *count); - cs->tx_cnt += *count; - - if (cs->debug & L1_DEB_ISAC_FIFO) { - char *t = cs->dlog; - - t += sprintf(t, "%s cnt %d", __FUNCTION__, *count); - QuickHex(t, p, *count); - debugl1(cs, cs->dlog); - } - return p; -} - -static inline void -recv_empty_fifo_d(struct IsdnCardState *cs, int count) -{ - u8 *p; - - if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) - debugl1(cs, __FUNCTION__); - - if (cs->rcvidx + count > MAX_DFRAME_LEN_L1) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "%s: incoming packet too large", __FUNCTION__); - cs->rcvidx = 0; - return; - } - p = cs->rcvbuf + cs->rcvidx; - cs->rcvidx += count; - cs->dc_hw_ops->read_fifo(cs, p, count); - - if (cs->debug & L1_DEB_ISAC_FIFO) { - char *t = cs->dlog; - - t += sprintf(t, "%s cnt %d", __FUNCTION__, count); - QuickHex(t, p, count); - debugl1(cs, cs->dlog); - } -} - -static inline void -recv_empty_fifo_b(struct BCState *bcs, int count) -{ - u8 *p; - struct IsdnCardState *cs = bcs->cs; - - if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) - debugl1(cs, __FUNCTION__); - - if (bcs->rcvidx + count > HSCX_BUFMAX) { - if (cs->debug & L1_DEB_WARN) - debugl1(cs, "%s: incoming packet too large", __FUNCTION__); - bcs->rcvidx = 0; - return; - } - p = bcs->rcvbuf + bcs->rcvidx; - bcs->rcvidx += count; - cs->bc_hw_ops->read_fifo(cs, bcs->unit, p, count); - - if (cs->debug & L1_DEB_HSCX_FIFO) { - char *t = bcs->blog; - - t += sprintf(t, "%s %c cnt %d", __FUNCTION__, - bcs->unit ? 'B' : 'A', count); - QuickHex(t, p, count); - debugl1(cs, bcs->blog); - } -} - -/* RME - receive message end */ -static inline void -recv_rme_d(struct IsdnCardState *cs) -{ - struct sk_buff *skb; - int count; - - count = cs->rcvidx - 1; - cs->rcvidx = 0; - if (count == 0) - return; - - skb = dev_alloc_skb(count); - if (!skb) { - printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__); - return; - } - memcpy(skb_put(skb, count), cs->rcvbuf, count); - skb_queue_tail(&cs->rq, skb); - sched_d_event(cs, D_RCVBUFREADY); -} - -static inline void -recv_rme_b(struct BCState *bcs) -{ - struct IsdnCardState *cs = bcs->cs; - struct sk_buff *skb; - int count; - - count = bcs->rcvidx - 1; - bcs->rcvidx = 0; - if (count == 0) - return; - - if (cs->debug & L1_DEB_HSCX_FIFO) - debugl1(cs, "HX Frame %d", count); - - skb = dev_alloc_skb(count); - if (!skb) { - printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__); - return; - } - memcpy(skb_put(skb, count), bcs->rcvbuf, count); - skb_queue_tail(&bcs->rqueue, skb); - sched_b_event(bcs, B_RCVBUFREADY); -} - -/* RPF - receive pull full */ -static inline void -recv_rpf_b(struct BCState *bcs) -{ - if (bcs->mode != L1_MODE_TRANS) - return; - - recv_rme_b(bcs); -} - -static inline int -bc_open(struct BCState *bcs) -{ - if (test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) - return 0; - - bcs->rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC); - if (!bcs->rcvbuf) - goto err; - - bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC); - if (!bcs->blog) - goto err_rcvbuf; - - skb_queue_head_init(&bcs->rqueue); - skb_queue_head_init(&bcs->squeue); - skb_queue_head_init(&bcs->cmpl_queue); - - clear_bit(BC_FLG_BUSY, &bcs->Flag); - bcs->tx_skb = NULL; - bcs->rcvidx = 0; - bcs->tx_cnt = 0; - bcs->event = 0; - - return 0; - - err_rcvbuf: - kfree(bcs->rcvbuf); - err: - clear_bit(BC_FLG_INIT, &bcs->Flag); - printk(KERN_WARNING "HiSax: %s: out of memory\n", __FUNCTION__); - return -ENOMEM;; -} - -static inline void -bc_close(struct BCState *bcs) -{ - if (!test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) - return; - - kfree(bcs->rcvbuf); - bcs->rcvbuf = NULL; - - kfree(bcs->blog); - bcs->blog = NULL; - - skb_queue_purge(&bcs->rqueue); - skb_queue_purge(&bcs->squeue); - skb_queue_purge(&bcs->cmpl_queue); - if (bcs->tx_skb) { - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; - clear_bit(BC_FLG_BUSY, &bcs->Flag); - } -} - #endif diff -Nru a/drivers/isdn/hisax/isdnl2.c b/drivers/isdn/hisax/isdnl2.c --- a/drivers/isdn/hisax/isdnl2.c Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/isdnl2.c Thu Feb 19 23:44:23 2004 @@ -1,4 +1,4 @@ -/* $Id: isdnl2.c,v 2.25.6.4 2001/09/23 22:24:49 kai Exp $ +/* $Id: isdnl2.c,v 2.30.2.4 2004/02/11 13:21:34 keil Exp $ * * Author Karsten Keil * based on the teles driver from Jan den Ouden @@ -19,21 +19,21 @@ #include "hisax.h" #include "isdnl2.h" -const char *l2_revision = "$Revision: 2.25.6.4 $"; -static spinlock_t isdnl2_lock = SPIN_LOCK_UNLOCKED; +const char *l2_revision = "$Revision: 2.30.2.4 $"; + static void l2m_debug(struct FsmInst *fi, char *fmt, ...); static struct Fsm l2fsm; enum { - ST_L2_1, /* TEI unassigned */ - ST_L2_2, /* Assign awaiting TEI */ - ST_L2_3, /* Establish awaiting TEI */ - ST_L2_4, /* TEI assigned */ - ST_L2_5, /* Awaiting establishment */ - ST_L2_6, /* Awaiting release */ - ST_L2_7, /* Multiple frame established */ - ST_L2_8, /* Timer recovery */ + ST_L2_1, + ST_L2_2, + ST_L2_3, + ST_L2_4, + ST_L2_5, + ST_L2_6, + ST_L2_7, + ST_L2_8, }; #define L2_STATE_COUNT (ST_L2_8+1) @@ -103,7 +103,7 @@ "EV_L2_FRAME_ERROR", }; -static u_int l2addrsize(struct Layer2 *l2); +static int l2addrsize(struct Layer2 *l2); static void set_peer_busy(struct Layer2 *l2) { @@ -178,23 +178,23 @@ clear_peer_busy(l2); } -inline u_int +inline int l2headersize(struct Layer2 *l2, int ui) { return (((test_bit(FLG_MOD128, &l2->flag) && (!ui)) ? 2 : 1) + (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1)); } -inline u_int +inline int l2addrsize(struct Layer2 *l2) { return (test_bit(FLG_LAPD, &l2->flag) ? 2 : 1); } static int -sethdraddr(struct Layer2 *l2, u8 * header, int rsp) +sethdraddr(struct Layer2 *l2, u_char * header, int rsp) { - u8 *ptr = header; + u_char *ptr = header; int crbit = rsp; if (test_bit(FLG_LAPD, &l2->flag)) { @@ -218,37 +218,37 @@ { if (test_bit(FLG_LAPB, &st->l2.flag)) st->l1.bcs->tx_cnt += skb->len; - L2L1(st, PH_DATA | REQUEST, skb); + st->l2.l2l1(st, PH_DATA | REQUEST, skb); } #define enqueue_ui(a, b) enqueue_super(a, b) inline int -IsUI(u8 * data) +IsUI(u_char * data) { return ((data[0] & 0xef) == UI); } inline int -IsUA(u8 * data) +IsUA(u_char * data) { return ((data[0] & 0xef) == UA); } inline int -IsDM(u8 * data) +IsDM(u_char * data) { return ((data[0] & 0xef) == DM); } inline int -IsDISC(u8 * data) +IsDISC(u_char * data) { return ((data[0] & 0xef) == DISC); } inline int -IsRR(u8 * data, struct PStack *st) +IsRR(u_char * data, struct PStack *st) { if (test_bit(FLG_MOD128, &st->l2.flag)) return (data[0] == RR); @@ -257,9 +257,9 @@ } inline int -IsSFrame(u8 * data, struct PStack *st) +IsSFrame(u_char * data, struct PStack *st) { - register u8 d = *data; + register u_char d = *data; if (!test_bit(FLG_MOD128, &st->l2.flag)) d &= 0xf; @@ -267,27 +267,27 @@ } inline int -IsSABME(u8 * data, struct PStack *st) +IsSABME(u_char * data, struct PStack *st) { - u8 d = data[0] & ~0x10; + u_char d = data[0] & ~0x10; return (test_bit(FLG_MOD128, &st->l2.flag) ? d == SABME : d == SABM); } inline int -IsREJ(u8 * data, struct PStack *st) +IsREJ(u_char * data, struct PStack *st) { return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == REJ : (data[0] & 0xf) == REJ); } inline int -IsFRMR(u8 * data) +IsFRMR(u_char * data) { return ((data[0] & 0xef) == FRMR); } inline int -IsRNR(u8 * data, struct PStack *st) +IsRNR(u_char * data, struct PStack *st) { return (test_bit(FLG_MOD128, &st->l2.flag) ? data[0] == RNR : (data[0] & 0xf) == RNR); } @@ -295,7 +295,7 @@ int iframe_error(struct PStack *st, struct sk_buff *skb) { - u_int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1); + int i = l2addrsize(&st->l2) + (test_bit(FLG_MOD128, &st->l2.flag) ? 2 : 1); int rsp = *skb->data & 0x2; if (test_bit(FLG_ORIG, &st->l2.flag)) @@ -360,8 +360,8 @@ int FRMR_error(struct PStack *st, struct sk_buff *skb) { - u_int headers = l2addrsize(&st->l2) + 1; - u8 *datap = skb->data + headers; + int headers = l2addrsize(&st->l2) + 1; + u_char *datap = skb->data + headers; int rsp = *skb->data & 0x2; if (test_bit(FLG_ORIG, &st->l2.flag)) @@ -403,27 +403,35 @@ setva(struct PStack *st, unsigned int nr) { struct Layer2 *l2 = &st->l2; - struct sk_buff *skb; + int len; + u_long flags; + spin_lock_irqsave(&l2->lock, flags); while (l2->va != nr) { (l2->va)++; if(test_bit(FLG_MOD128, &l2->flag)) l2->va %= 128; else l2->va %= 8; - skb = l2->windowar[l2->sow]; + len = l2->windowar[l2->sow]->len; + if (PACKET_NOACK == l2->windowar[l2->sow]->pkt_type) + len = -1; + dev_kfree_skb(l2->windowar[l2->sow]); l2->windowar[l2->sow] = NULL; l2->sow = (l2->sow + 1) % l2->window; - - L2L3(st, DL_DATA | CONFIRM, skb); + spin_unlock_irqrestore(&l2->lock, flags); + if (test_bit(FLG_LLI_L2WAKEUP, &st->lli.flag) && (len >=0)) + lli_writewakeup(st, len); + spin_lock_irqsave(&l2->lock, flags); } + spin_unlock_irqrestore(&l2->lock, flags); } static void -send_uframe(struct PStack *st, u8 cmd, u8 cr) +send_uframe(struct PStack *st, u_char cmd, u_char cr) { struct sk_buff *skb; - u8 tmp[MAX_HEADER_LEN]; + u_char tmp[MAX_HEADER_LEN]; int i; i = sethdraddr(&st->l2, tmp, cr); @@ -436,7 +444,7 @@ enqueue_super(st, skb); } -inline u8 +inline u_char get_PollFlag(struct PStack * st, struct sk_buff * skb) { return (skb->data[l2addrsize(&(st->l2))] & 0x10); @@ -449,10 +457,10 @@ } -inline u8 +inline u_char get_PollFlagFree(struct PStack *st, struct sk_buff *skb) { - u8 PF; + u_char PF; PF = get_PollFlag(st, skb); FreeSkb(skb); @@ -490,22 +498,22 @@ else pr = DL_RELEASE | INDICATION; - L2L3(st, pr, NULL); + st->l2.l2l3(st, pr, NULL); } inline void lapb_dl_release_l2l3(struct PStack *st, int f) { if (test_bit(FLG_LAPB, &st->l2.flag)) - L2L1(st, PH_DEACTIVATE | REQUEST, NULL); - L2L3(st, DL_RELEASE | f, NULL); + st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); + st->l2.l2l3(st, DL_RELEASE | f, NULL); } static void establishlink(struct FsmInst *fi) { struct PStack *st = fi->userdata; - u8 cmd; + u_char cmd; clear_exception(&st->l2); st->l2.rc = 0; @@ -599,7 +607,7 @@ tx_ui(struct PStack *st) { struct sk_buff *skb; - u8 header[MAX_HEADER_LEN]; + u_char header[MAX_HEADER_LEN]; int i; i = sethdraddr(&(st->l2), header, CMD); @@ -627,7 +635,7 @@ struct sk_buff *skb = arg; skb_pull(skb, l2headersize(&st->l2, 1)); - L2L3(st, DL_UNIT_DATA | INDICATION, skb); + st->l2.l2l3(st, DL_UNIT_DATA | INDICATION, skb); /* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * in states 1-3 for broadcast */ @@ -669,7 +677,7 @@ { struct PStack *st = fi->userdata; - L2L3(st, DL_RELEASE | CONFIRM, NULL); + st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); } static void @@ -710,7 +718,7 @@ FsmChangeState(fi, ST_L2_7); FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3); - L2L3(st, DL_ESTABLISH | INDICATION, NULL); + st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL); } static void @@ -759,11 +767,11 @@ FsmRestartTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 3); if (est) - L2L3(st, DL_ESTABLISH | INDICATION, NULL); + st->l2.l2l3(st, DL_ESTABLISH | INDICATION, NULL); if ((ST_L2_7==state) || (ST_L2_8 == state)) if (skb_queue_len(&st->l2.i_queue) && cansend(st)) - L2L1(st, PH_PULL | REQUEST, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } static void @@ -816,10 +824,10 @@ FsmAddTimer(&st->l2.t203, st->l2.T203, EV_L2_T203, NULL, 4); if (pr != -1) - L2L3(st, pr, NULL); + st->l2.l2l3(st, pr, NULL); if (skb_queue_len(&st->l2.i_queue) && cansend(st)) - L2L1(st, PH_PULL | REQUEST, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } static void @@ -862,7 +870,7 @@ if (!test_bit(FLG_L3_INIT, &st->l2.flag)) skb_queue_purge(&st->l2.i_queue); if (test_bit(FLG_LAPB, &st->l2.flag)) - L2L1(st, PH_DEACTIVATE | REQUEST, NULL); + st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); st5_dl_release_l2l3(st); FsmChangeState(fi, ST_L2_4); } @@ -882,11 +890,11 @@ } inline void -enquiry_cr(struct PStack *st, u8 typ, u8 cr, u8 pf) +enquiry_cr(struct PStack *st, u_char typ, u_char cr, u_char pf) { struct sk_buff *skb; struct Layer2 *l2; - u8 tmp[MAX_HEADER_LEN]; + u_char tmp[MAX_HEADER_LEN]; int i; l2 = &st->l2; @@ -940,8 +948,10 @@ invoke_retransmission(struct PStack *st, unsigned int nr) { struct Layer2 *l2 = &st->l2; - unsigned int p1; + u_int p1; + u_long flags; + spin_lock_irqsave(&l2->lock, flags); if (l2->vs != nr) { while (l2->vs != nr) { (l2->vs)--; @@ -958,8 +968,11 @@ skb_queue_head(&l2->i_queue, l2->windowar[p1]); l2->windowar[p1] = NULL; } - L2L1(st, PH_PULL | REQUEST, NULL); + spin_unlock_irqrestore(&l2->lock, flags); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); + return; } + spin_unlock_irqrestore(&l2->lock, flags); } static void @@ -1018,7 +1031,7 @@ restart_t200(st, 12); } if (skb_queue_len(&st->l2.i_queue) && (typ == RR)) - L2L1(st, PH_PULL | REQUEST, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } else nrerrorrecovery(fi); } @@ -1046,7 +1059,7 @@ if (test_bit(FLG_LAPB, &st->l2.flag)) st->l1.bcs->tx_cnt += skb->len + l2headersize(&st->l2, 0); skb_queue_tail(&st->l2.i_queue, skb); - L2L1(st, PH_PULL | REQUEST, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } static void @@ -1066,8 +1079,8 @@ struct PStack *st = fi->userdata; struct sk_buff *skb = arg; struct Layer2 *l2 = &(st->l2); - int PollFlag, i; - unsigned int nr, ns; + int PollFlag, ns, i; + unsigned int nr; i = l2addrsize(l2); if (test_bit(FLG_MOD128, &l2->flag)) { @@ -1095,7 +1108,7 @@ else test_and_set_bit(FLG_ACK_PEND, &l2->flag); skb_pull(skb, l2headersize(l2, 0)); - L2L3(st, DL_DATA | INDICATION, skb); + st->l2.l2l3(st, DL_DATA | INDICATION, skb); } else { /* n(s)!=v(r) */ FreeSkb(skb); @@ -1124,7 +1137,7 @@ } if (skb_queue_len(&st->l2.i_queue) && (fi->state == ST_L2_7)) - L2L1(st, PH_PULL | REQUEST, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); if (test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag)) enquiry_cr(st, RR, RSP, 0); } @@ -1159,7 +1172,7 @@ skb_queue_purge(&st->l2.i_queue); st->ma.layer(st, MDL_ERROR | INDICATION, (void *) 'G'); if (test_bit(FLG_LAPB, &st->l2.flag)) - L2L1(st, PH_DEACTIVATE | REQUEST, NULL); + st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); st5_dl_release_l2l3(st); } else { st->l2.rc++; @@ -1250,9 +1263,10 @@ struct PStack *st = fi->userdata; struct sk_buff *skb, *oskb; struct Layer2 *l2 = &st->l2; - u8 header[MAX_HEADER_LEN]; - int unsigned p1, i; - unsigned long flags; + u_char header[MAX_HEADER_LEN]; + int i; + int unsigned p1; + u_long flags; if (!cansend(st)) return; @@ -1261,7 +1275,7 @@ if (!skb) return; - spin_lock_irqsave(&isdnl2_lock, flags); + spin_lock_irqsave(&l2->lock, flags); if(test_bit(FLG_MOD128, &l2->flag)) p1 = (l2->vs - l2->va) % 128; else @@ -1284,8 +1298,7 @@ header[i++] = (l2->vr << 5) | (l2->vs << 1); l2->vs = (l2->vs + 1) % 8; } - spin_unlock_irqrestore(&isdnl2_lock, flags); - + spin_unlock_irqrestore(&l2->lock, flags); p1 = skb->data - skb->head; if (p1 >= i) memcpy(skb_push(skb, i), header, i); @@ -1298,14 +1311,14 @@ memcpy(skb_put(skb, oskb->len), oskb->data, oskb->len); FreeSkb(oskb); } - L2L1(st, PH_PULL | INDICATION, skb); + st->l2.l2l1(st, PH_PULL | INDICATION, skb); test_and_clear_bit(FLG_ACK_PEND, &st->l2.flag); if (!test_and_set_bit(FLG_T200_RUN, &st->l2.flag)) { FsmDelTimer(&st->l2.t203, 13); FsmAddTimer(&st->l2.t200, st->l2.T200, EV_L2_T200, NULL, 11); } if (skb_queue_len(&l2->i_queue) && cansend(st)) - L2L1(st, PH_PULL | REQUEST, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } static void @@ -1351,7 +1364,7 @@ invoke_retransmission(st, nr); FsmChangeState(fi, ST_L2_7); if (skb_queue_len(&l2->i_queue) && cansend(st)) - L2L1(st, PH_PULL | REQUEST, NULL); + st->l2.l2l1(st, PH_PULL | REQUEST, NULL); } else nrerrorrecovery(fi); } else { @@ -1398,7 +1411,7 @@ skb_queue_purge(&st->l2.ui_queue); st->l2.tei = -1; - L2L3(st, DL_RELEASE | INDICATION, NULL); + st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); FsmChangeState(fi, ST_L2_1); } @@ -1424,7 +1437,7 @@ skb_queue_purge(&st->l2.ui_queue); st->l2.tei = -1; stop_t200(st, 18); - L2L3(st, DL_RELEASE | CONFIRM, NULL); + st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); FsmChangeState(fi, ST_L2_1); } @@ -1439,23 +1452,23 @@ st->l2.tei = -1; stop_t200(st, 17); FsmDelTimer(&st->l2.t203, 19); - L2L3(st, DL_RELEASE | INDICATION, NULL); + st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); FsmChangeState(fi, ST_L2_1); } static void -l2_st14_persistent_da(struct FsmInst *fi, int event, void *arg) +l2_st14_persistant_da(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; skb_queue_purge(&st->l2.i_queue); skb_queue_purge(&st->l2.ui_queue); if (test_and_clear_bit(FLG_ESTAB_PEND, &st->l2.flag)) - L2L3(st, DL_RELEASE | INDICATION, NULL); + st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); } static void -l2_st5_persistent_da(struct FsmInst *fi, int event, void *arg) +l2_st5_persistant_da(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; @@ -1468,18 +1481,18 @@ } static void -l2_st6_persistent_da(struct FsmInst *fi, int event, void *arg) +l2_st6_persistant_da(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; skb_queue_purge(&st->l2.ui_queue); stop_t200(st, 20); - L2L3(st, DL_RELEASE | CONFIRM, NULL); + st->l2.l2l3(st, DL_RELEASE | CONFIRM, NULL); FsmChangeState(fi, ST_L2_4); } static void -l2_persistent_da(struct FsmInst *fi, int event, void *arg) +l2_persistant_da(struct FsmInst *fi, int event, void *arg) { struct PStack *st = fi->userdata; @@ -1488,7 +1501,7 @@ freewin(st); stop_t200(st, 19); FsmDelTimer(&st->l2.t203, 19); - L2L3(st, DL_RELEASE | INDICATION, NULL); + st->l2.l2l3(st, DL_RELEASE | INDICATION, NULL); FsmChangeState(fi, ST_L2_4); } @@ -1614,14 +1627,14 @@ {ST_L2_6, EV_L2_FRAME_ERROR, l2_frame_error}, {ST_L2_7, EV_L2_FRAME_ERROR, l2_frame_error_reest}, {ST_L2_8, EV_L2_FRAME_ERROR, l2_frame_error_reest}, - {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistent_da}, + {ST_L2_1, EV_L1_DEACTIVATE, l2_st14_persistant_da}, {ST_L2_2, EV_L1_DEACTIVATE, l2_st24_tei_remove}, {ST_L2_3, EV_L1_DEACTIVATE, l2_st3_tei_remove}, - {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistent_da}, - {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistent_da}, - {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistent_da}, - {ST_L2_7, EV_L1_DEACTIVATE, l2_persistent_da}, - {ST_L2_8, EV_L1_DEACTIVATE, l2_persistent_da}, + {ST_L2_4, EV_L1_DEACTIVATE, l2_st14_persistant_da}, + {ST_L2_5, EV_L1_DEACTIVATE, l2_st5_persistant_da}, + {ST_L2_6, EV_L1_DEACTIVATE, l2_st6_persistant_da}, + {ST_L2_7, EV_L1_DEACTIVATE, l2_persistant_da}, + {ST_L2_8, EV_L1_DEACTIVATE, l2_persistant_da}, }; #define L2_FN_COUNT (sizeof(L2FnList)/sizeof(struct FsmNode)) @@ -1630,8 +1643,8 @@ isdnl2_l1l2(struct PStack *st, int pr, void *arg) { struct sk_buff *skb = arg; - u8 *datap; - u_int ret = 1, len; + u_char *datap; + int ret = 1, len; int c = 0; switch (pr) { @@ -1682,9 +1695,6 @@ if (ret) FreeSkb(skb); break; - case (PH_DATA | CONFIRM): - dev_kfree_skb(skb); - break; case (PH_PULL | CONFIRM): FsmEvent(&st->l2.l2m, EV_L2_ACK_PULL, arg); break; @@ -1736,12 +1746,12 @@ test_bit(FLG_ORIG, &st->l2.flag)) { test_and_set_bit(FLG_ESTAB_PEND, &st->l2.flag); } - L2L1(st, PH_ACTIVATE, NULL); + st->l2.l2l1(st, PH_ACTIVATE, NULL); } break; case (DL_RELEASE | REQUEST): if (test_bit(FLG_LAPB, &st->l2.flag)) { - L2L1(st, PH_DEACTIVATE, NULL); + st->l2.l2l1(st, PH_DEACTIVATE, NULL); } FsmEvent(&st->l2.l2m, EV_L2_DL_RELEASE_REQ, arg); break; @@ -1781,8 +1791,9 @@ void setstack_isdnl2(struct PStack *st, char *debug_id) { - st->l2.l1l2 = isdnl2_l1l2; - st->l2.l3l2 = isdnl2_l3l2; + spin_lock_init(&st->l2.lock); + st->l1.l1l2 = isdnl2_l1l2; + st->l3.l3l2 = isdnl2_l3l2; skb_queue_head_init(&st->l2.i_queue); skb_queue_head_init(&st->l2.ui_queue); @@ -1810,13 +1821,13 @@ switch (pr) { case (DL_DATA | REQUEST): case (DL_UNIT_DATA | REQUEST): - L2L1(st, PH_DATA | REQUEST, arg); + st->l2.l2l1(st, PH_DATA | REQUEST, arg); break; case (DL_ESTABLISH | REQUEST): - L2L1(st, PH_ACTIVATE | REQUEST, NULL); + st->l2.l2l1(st, PH_ACTIVATE | REQUEST, NULL); break; case (DL_RELEASE | REQUEST): - L2L1(st, PH_DEACTIVATE | REQUEST, NULL); + st->l2.l2l1(st, PH_DEACTIVATE | REQUEST, NULL); break; } } @@ -1824,7 +1835,7 @@ void setstack_transl2(struct PStack *st) { - st->l2.l3l2 = transl2_l3l2; + st->l3.l3l2 = transl2_l3l2; } void diff -Nru a/drivers/isdn/hisax/isdnl3.c b/drivers/isdn/hisax/isdnl3.c --- a/drivers/isdn/hisax/isdnl3.c Thu Feb 19 23:44:25 2004 +++ b/drivers/isdn/hisax/isdnl3.c Thu Feb 19 23:44:25 2004 @@ -1,4 +1,4 @@ -/* $Id: isdnl3.c,v 2.17.6.5 2001/09/23 22:24:49 kai Exp $ +/* $Id: isdnl3.c,v 2.22.2.3 2004/01/13 14:31:25 keil Exp $ * * Author Karsten Keil * based on the teles driver from Jan den Ouden @@ -20,7 +20,7 @@ #include "isdnl3.h" #include -const char *l3_revision = "$Revision: 2.17.6.5 $"; +const char *l3_revision = "$Revision: 2.22.2.3 $"; static struct Fsm l3fsm; @@ -77,11 +77,11 @@ va_end(args); } -u8 * -findie(u8 * p, int size, u8 ie, int wanted_set) +u_char * +findie(u_char * p, int size, u_char ie, int wanted_set) { int l, codeset, maincodeset; - u8 *pend = p + size; + u_char *pend = p + size; /* skip protocol discriminator, callref and message type */ p++; @@ -123,7 +123,7 @@ } int -getcallref(u8 * p) +getcallref(u_char * p) { int l, cr = 0; @@ -162,7 +162,7 @@ static void L3ExpireTimer(struct L3Timer *t) { - t->pc->st->l3.l4l3(t->pc->st, t->event, t->pc); + t->pc->st->lli.l4l3(t->pc->st, t->event, t->pc); } void @@ -354,7 +354,7 @@ st->l3.l3m.printdebug = l3m_debug; FsmInitTimer(&st->l3.l3m, &st->l3.l3m_timer); strcpy(st->l3.debug_id, "L3DC "); - st->l3.l4l3_proto = no_l3_proto_spec; + st->lli.l4l3_proto = no_l3_proto_spec; #ifdef CONFIG_HISAX_EURO if (st->protocol == ISDN_PTYPE_EURO) { @@ -372,13 +372,13 @@ } else #endif if (st->protocol == ISDN_PTYPE_LEASED) { - st->l3.l4l3 = no_l3_proto; - st->l3.l2l3 = no_l3_proto; + st->lli.l4l3 = no_l3_proto; + st->l2.l2l3 = no_l3_proto; st->l3.l3ml3 = no_l3_proto; printk(KERN_INFO "HiSax: Leased line mode\n"); } else { - st->l3.l4l3 = no_l3_proto; - st->l3.l2l3 = no_l3_proto; + st->lli.l4l3 = no_l3_proto; + st->l2.l2l3 = no_l3_proto; st->l3.l3ml3 = no_l3_proto; sprintf(tmp, "protocol %s not supported", (st->protocol == ISDN_PTYPE_1TR6) ? "1tr6" : @@ -392,7 +392,7 @@ void isdnl3_trans(struct PStack *st, int pr, void *arg) { - L3L2(st, pr, arg); + st->l3.l3l2(st, pr, arg); } void @@ -423,7 +423,7 @@ st->l3.l3m.userint = 0; st->l3.l3m.printdebug = l3m_debug; strcpy(st->l3.debug_id, "L3BC "); - st->l3.l4l3 = isdnl3_trans; + st->lli.l4l3 = isdnl3_trans; } #define DREL_TIMER_VALUE 40000 @@ -434,7 +434,7 @@ struct PStack *st = fi->userdata; FsmChangeState(fi, ST_L3_LC_ESTAB_WAIT); - L3L2(st, DL_ESTABLISH | REQUEST, NULL); + st->l3.l3l2(st, DL_ESTABLISH | REQUEST, NULL); } static void @@ -446,7 +446,7 @@ FsmChangeState(fi, ST_L3_LC_ESTAB); while ((skb = skb_dequeue(&st->l3.squeue))) { - L3L2(st, DL_DATA | REQUEST, skb); + st->l3.l3l2(st, DL_DATA | REQUEST, skb); dequeued++; } if ((!st->l3.proc) && dequeued) { @@ -467,7 +467,7 @@ FsmDelTimer(&st->l3.l3m_timer, 51); FsmChangeState(fi, ST_L3_LC_ESTAB); while ((skb = skb_dequeue(&st->l3.squeue))) { - L3L2(st, DL_DATA | REQUEST, skb); + st->l3.l3l2(st, DL_DATA | REQUEST, skb); dequeued++; } if ((!st->l3.proc) && dequeued) { @@ -511,7 +511,7 @@ FsmAddTimer(&st->l3.l3m_timer, DREL_TIMER_VALUE, EV_TIMEOUT, NULL, 51); } else { FsmChangeState(fi, ST_L3_LC_REL_WAIT); - L3L2(st, DL_RELEASE | REQUEST, NULL); + st->l3.l3l2(st, DL_RELEASE | REQUEST, NULL); } } @@ -564,7 +564,7 @@ switch (pr) { case (DL_DATA | REQUEST): if (st->l3.l3m.state == ST_L3_LC_ESTAB) { - L3L2(st, pr, arg); + st->l3.l3l2(st, pr, arg); } else { struct sk_buff *skb = arg; diff -Nru a/drivers/isdn/hisax/isurf.c b/drivers/isdn/hisax/isurf.c --- a/drivers/isdn/hisax/isurf.c Thu Feb 19 23:44:25 2004 +++ b/drivers/isdn/hisax/isurf.c Thu Feb 19 23:44:25 2004 @@ -1,4 +1,4 @@ -/* $Id: isurf.c,v 1.10.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: isurf.c,v 1.12.2.4 2004/01/13 21:46:03 keil Exp $ * * low level stuff for Siemens I-Surf/I-Talk cards * @@ -19,7 +19,7 @@ extern const char *CardType[]; -static const char *ISurf_revision = "$Revision: 1.10.6.2 $"; +static const char *ISurf_revision = "$Revision: 1.12.2.4 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -35,20 +35,20 @@ #define ISURF_IOMEM_SIZE 0x400 /* Interface functions */ -static u8 -ReadISAC(struct IsdnCardState *cs, u8 offset) +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { return (readb(cs->hw.isurf.isac + offset)); } static void -WriteISAC(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { writeb(value, cs->hw.isurf.isac + offset); mb(); } static void -ReadISACfifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { register int i; for (i = 0; i < size; i++) @@ -56,7 +56,7 @@ } static void -WriteISACfifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { register int i; for (i = 0; i < size; i++){ @@ -64,44 +64,33 @@ } } -static struct dc_hw_ops isac_ops = { - .read_reg = ReadISAC, - .write_reg = WriteISAC, - .read_fifo = ReadISACfifo, - .write_fifo = WriteISACfifo, -}; - /* ISAR access routines * mode = 0 access with IRQ on * mode = 1 access with IRQ off * mode = 2 access with IRQ off and using last offset */ -static u8 -ReadISAR(struct IsdnCardState *cs, int mode, u8 offset) +static u_char +ReadISAR(struct IsdnCardState *cs, int mode, u_char offset) { return(readb(cs->hw.isurf.isar + offset)); } static void -WriteISAR(struct IsdnCardState *cs, int mode, u8 offset, u8 value) +WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value) { writeb(value, cs->hw.isurf.isar + offset);mb(); } -static struct bc_hw_ops isar_ops = { - .read_reg = ReadISAR, - .write_reg = WriteISAR, -}; - static irqreturn_t isurf_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; + u_char val; int cnt = 5; + u_long flags; - spin_lock(&cs->lock); + spin_lock_irqsave(&cs->lock, flags); val = readb(cs->hw.isurf.isar + ISAR_IRQBIT); Start_ISAR: if (val & ISAR_IRQSTA) @@ -129,151 +118,190 @@ writeb(0xFF, cs->hw.isurf.isac + ISAC_MASK);mb(); writeb(0, cs->hw.isurf.isac + ISAC_MASK);mb(); writeb(ISAR_IRQMSK, cs->hw.isurf.isar + ISAR_IRQBIT); mb(); - spin_unlock(&cs->lock); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } +void +release_io_isurf(struct IsdnCardState *cs) +{ + release_region(cs->hw.isurf.reset, 1); + iounmap((unsigned char *)cs->hw.isurf.isar); + release_mem_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE); +} + static void -reset_isurf(struct IsdnCardState *cs, u8 chips) +reset_isurf(struct IsdnCardState *cs, u_char chips) { printk(KERN_INFO "ISurf: resetting card\n"); byteout(cs->hw.isurf.reset, chips); /* Reset On */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); byteout(cs->hw.isurf.reset, ISURF_ISAR_EA); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); +} + +static int +ISurf_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + u_long flags; + + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_isurf(cs, ISURF_RESET); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_isurf(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + reset_isurf(cs, ISURF_RESET); + clear_pending_isac_ints(cs); + writeb(0, cs->hw.isurf.isar+ISAR_IRQBIT);mb(); + initisac(cs); + initisar(cs); + /* Reenable ISAC IRQ */ + cs->writeisac(cs, ISAC_MASK, 0); + /* RESET Receiver and Transmitter */ + cs->writeisac(cs, ISAC_CMDR, 0x41); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); } static int isurf_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic) { int ret; + u_long flags; if ((ic->command == ISDN_CMD_IOCTL) && (ic->arg == 9)) { ret = isar_auxcmd(cs, ic); + spin_lock_irqsave(&cs->lock, flags); if (!ret) { reset_isurf(cs, ISURF_ISAR_EA | ISURF_ISAC_RESET | ISURF_ARCOFI_RESET); initisac(cs); + cs->writeisac(cs, ISAC_MASK, 0); + cs->writeisac(cs, ISAC_CMDR, 0x41); } + spin_unlock_irqrestore(&cs->lock, flags); return(ret); } return(isar_auxcmd(cs, ic)); } -static void -isurf_init(struct IsdnCardState *cs) -{ - writeb(0, cs->hw.isurf.isar + ISAR_IRQBIT); - initisac(cs); - initisar(cs); -} - -static int -isurf_reset(struct IsdnCardState *cs) -{ - reset_isurf(cs, ISURF_RESET); - return 0; -} - -static struct card_ops isurf_ops = { - .init = isurf_init, - .reset = isurf_reset, - .release = hisax_release_resources, - .irq_func = isurf_interrupt, -}; - #ifdef __ISAPNP__ -static struct pnp_card *pnp_surf __devinitdata = NULL; +static struct pnp_card *pnp_c __initdata = NULL; #endif -static int __init -isurf_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - unsigned long phymem; - - phymem = card->para[2]; - cs->hw.isurf.reset = card->para[1]; - cs->irq = card->para[0]; - - if (!request_io(&cs->rs, cs->hw.isurf.reset, 1, "isurf isdn")) - goto err; - - cs->hw.isurf.isar = request_mmio(&cs->rs, phymem, ISURF_IOMEM_SIZE, - "isurf iomem"); - if (!cs->hw.isurf.isar) - goto err; - - cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET; - printk(KERN_INFO "ISurf: defined at 0x%x 0x%lx IRQ %d\n", - cs->hw.isurf.reset, phymem, cs->irq); - - cs->auxcmd = &isurf_auxcmd; - cs->card_ops = &isurf_ops; - cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r; - cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r; - reset_isurf(cs, ISURF_RESET); - __set_bit(HW_ISAR, &cs->HW_Flags); - isac_setup(cs, &isac_ops); - if (isar_setup(cs, &isar_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - int __init setup_isurf(struct IsdnCard *card) { + int ver; + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, ISurf_revision); printk(KERN_INFO "HiSax: ISurf driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_ISURF) + return(0); + if (card->para[1] && card->para[2]) { + cs->hw.isurf.reset = card->para[1]; + cs->hw.isurf.phymem = card->para[2]; + cs->irq = card->para[0]; + } else { #ifdef __ISAPNP__ - if (!card->para[1] || !card->para[2]) { - struct pnp_card *pb; - struct pnp_dev *pd; - - card->cs->subtyp = 0; - if ((pb = pnp_find_card( - ISAPNP_VENDOR('S', 'I', 'E'), - ISAPNP_FUNCTION(0x0010), pnp_surf))) { - pnp_surf = pb; - pd = NULL; - if (!(pd = pnp_find_dev(pnp_surf, - ISAPNP_VENDOR('S', 'I', 'E'), - ISAPNP_FUNCTION(0x0010), pd))) { - printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n"); - return (0); - } - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "ISurfPnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "ISurfPnP: activate failed\n"); - pnp_device_detach(pd); - return 0; - } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) { - printk(KERN_ERR "ISurfPnP:some resources are missing %ld/%lx/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1)); - pnp_device_detach(pd); + if (isapnp_present()) { + struct pnp_dev *pnp_d = NULL; + int err; + + cs->subtyp = 0; + if ((pnp_c = pnp_find_card( + ISAPNP_VENDOR('S', 'I', 'E'), + ISAPNP_FUNCTION(0x0010), pnp_c))) { + if (!(pnp_d = pnp_find_dev(pnp_c, + ISAPNP_VENDOR('S', 'I', 'E'), + ISAPNP_FUNCTION(0x0010), pnp_d))) { + printk(KERN_ERR "ISurfPnP: PnP error card found, no device\n"); + return (0); + } + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + cs->hw.isurf.reset = pnp_port_start(pnp_d, 0); + cs->hw.isurf.phymem = pnp_mem_start(pnp_d, 1); + cs->irq = pnp_irq(pnp_d, 0); + if (!cs->irq || !cs->hw.isurf.reset || !cs->hw.isurf.phymem) { + printk(KERN_ERR "ISurfPnP:some resources are missing %d/%x/%lx\n", + cs->irq, cs->hw.isurf.reset, cs->hw.isurf.phymem); + pnp_disable_dev(pnp_d); + return(0); + } + } else { + printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n"); return(0); } - card->para[1] = pnp_port_start(pd, 0); - card->para[2] = pnp_port_start(pd, 1); - card->para[0] = pnp_irq(pd, 0); } else { - printk(KERN_INFO "ISurfPnP: no ISAPnP card found\n"); - return 0; + printk(KERN_INFO "ISurfPnP: no ISAPnP bus found\n"); + return(0); } - } +#else + printk(KERN_WARNING "HiSax: %s port/mem not set\n", + CardType[card->typ]); + return (0); #endif - if (isurf_probe(card->cs, card) < 0) - return 0; - return 1; + } + if (!request_region(cs->hw.isurf.reset, 1, "isurf isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %x already in use\n", + CardType[card->typ], + cs->hw.isurf.reset); + return (0); + } + if (!request_region(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE, "isurf iomem")) { + printk(KERN_WARNING + "HiSax: %s memory region %lx-%lx already in use\n", + CardType[card->typ], + cs->hw.isurf.phymem, + cs->hw.isurf.phymem + ISURF_IOMEM_SIZE); + release_region(cs->hw.isurf.reset, 1); + return (0); + } + cs->hw.isurf.isar = + (unsigned long) ioremap(cs->hw.isurf.phymem, ISURF_IOMEM_SIZE); + cs->hw.isurf.isac = cs->hw.isurf.isar + ISURF_ISAC_OFFSET; + printk(KERN_INFO + "ISurf: defined at 0x%x 0x%lx IRQ %d\n", + cs->hw.isurf.reset, + cs->hw.isurf.phymem, + cs->irq); + + setup_isac(cs); + cs->cardmsg = &ISurf_card_msg; + cs->irq_func = &isurf_interrupt; + cs->auxcmd = &isurf_auxcmd; + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->bcs[0].hw.isar.reg = &cs->hw.isurf.isar_r; + cs->bcs[1].hw.isar.reg = &cs->hw.isurf.isar_r; + test_and_set_bit(HW_ISAR, &cs->HW_Flags); + ISACVersion(cs, "ISurf:"); + cs->BC_Read_Reg = &ReadISAR; + cs->BC_Write_Reg = &WriteISAR; + cs->BC_Send_Data = &isar_fill_fifo; + ver = ISARVersion(cs, "ISurf:"); + if (ver < 0) { + printk(KERN_WARNING + "ISurf: wrong ISAR version (ret = %d)\n", ver); + release_io_isurf(cs); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/ix1_micro.c b/drivers/isdn/hisax/ix1_micro.c --- a/drivers/isdn/hisax/ix1_micro.c Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/hisax/ix1_micro.c Thu Feb 19 23:44:28 2004 @@ -1,4 +1,4 @@ -/* $Id: ix1_micro.c,v 2.10.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: ix1_micro.c,v 2.12.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for ITK ix1-micro Rev.2 isdn cards * derived from the original file teles3.c from Karsten Keil @@ -25,8 +25,7 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *ix1_revision = "$Revision: 2.10.6.2 $"; -static spinlock_t ix1_micro_lock = SPIN_LOCK_UNLOCKED; +const char *ix1_revision = "$Revision: 2.12.2.4 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -40,107 +39,137 @@ #define TIMEOUT 50 -static inline u8 -readreg(struct IsdnCardState *cs, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&ix1_micro_lock, flags); - byteout(cs->hw.ix1.isac_ale, off); + byteout(ale, off); ret = bytein(adr); - spin_unlock_irqrestore(&ix1_micro_lock, flags); return (ret); } static inline void -writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; - - spin_lock_irqsave(&ix1_micro_lock, flags); - byteout(cs->hw.ix1.isac_ale, off); - byteout(adr, data); - spin_unlock_irqrestore(&ix1_micro_lock, flags); + byteout(ale, off); + insb(adr, data, size); } + static inline void -readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { - byteout(cs->hw.ix1.isac_ale, off); - insb(adr, data, size); + byteout(ale, off); + byteout(adr, data); } static inline void -writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - byteout(cs->hw.ix1.isac_ale, off); + byteout(ale, off); outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.ix1.isac, offset); + return (readreg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.ix1.isac, offset, value); + writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - readfifo(cs, cs->hw.ix1.isac, 0, data, size); + readfifo(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, 0, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs, cs->hw.ix1.isac, 0, data, size); + writefifo(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - return readreg(cs, cs->hw.ix1.hscx, offset + (hscx ? 0x40 : 0)); + return (readreg(cs->hw.ix1.hscx_ale, + cs->hw.ix1.hscx, offset + (hscx ? 0x40 : 0))); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - writereg(cs, cs->hw.ix1.hscx, offset + (hscx ? 0x40 : 0), value); + writereg(cs->hw.ix1.hscx_ale, + cs->hw.ix1.hscx, offset + (hscx ? 0x40 : 0), value); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - readfifo(cs, cs->hw.ix1.hscx, hscx ? 0x40 : 0, data, size); +#define READHSCX(cs, nr, reg) readreg(cs->hw.ix1.hscx_ale, \ + cs->hw.ix1.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.ix1.hscx_ale, \ + cs->hw.ix1.hscx, reg + (nr ? 0x40 : 0), data) + +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.ix1.hscx_ale, \ + cs->hw.ix1.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.ix1.hscx_ale, \ + cs->hw.ix1.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" + +static irqreturn_t +ix1micro_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + val = readreg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_ISTA + 0x40); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = readreg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_ISTA + 0x40); + if (val) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_ISTA); + if (val) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.ix1.isac_ale, cs->hw.ix1.isac, ISAC_MASK, 0); + writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK, 0); + writereg(cs->hw.ix1.hscx_ale, cs->hw.ix1.hscx, HSCX_MASK + 0x40, 0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; } -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +void +release_io_ix1micro(struct IsdnCardState *cs) { - writefifo(cs, cs->hw.ix1.hscx, hscx ? 0x40 : 0, data, size); + if (cs->hw.ix1.cfg_reg) + release_region(cs->hw.ix1.cfg_reg, 4); } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static int +static void ix1_reset(struct IsdnCardState *cs) { int cnt; @@ -152,37 +181,32 @@ HZDELAY(1); /* wait >=10 ms */ } byteout(cs->hw.ix1.cfg_reg + SPECIAL_PORT_OFFSET, 0); - return 0; } -static struct card_ops ix1_ops = { - .init = inithscxisac, - .reset = ix1_reset, - .release = hisax_release_resources, - .irq_func = hscxisac_irq, -}; - -static int __init -ix1_probe(struct IsdnCardState *cs, struct IsdnCard *card) +static int +ix1_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - cs->irq = card->para[0]; - cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET; - cs->hw.ix1.isac = card->para[1] + ISAC_DATA_OFFSET; - cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET; - cs->hw.ix1.cfg_reg = card->para[1]; - if (!request_io(&cs->rs, cs->hw.ix1.cfg_reg, 4, "ix1micro cfg")) - goto err; - - printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n", - CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg); - ix1_reset(cs); - cs->card_ops = &ix1_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + u_long flags; + + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + ix1_reset(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_ix1micro(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + ix1_reset(cs); + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); } #ifdef __ISAPNP__ @@ -196,7 +220,7 @@ { 0, } }; -static struct isapnp_device_id *idev = &itk_ids[0]; +static struct isapnp_device_id *ipid __initdata = &itk_ids[0]; static struct pnp_card *pnp_c __devinitdata = NULL; #endif @@ -204,64 +228,91 @@ int __init setup_ix1micro(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, ix1_revision); printk(KERN_INFO "HiSax: ITK IX1 driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_IX1MICROR2) + return (0); - if (card->para[1]) { - if (ix1_probe(card->cs, card)) - return 0; - return 1; - } #ifdef __ISAPNP__ - if (isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; - - while(idev->card_vendor) { - if ((pb = pnp_find_card(idev->card_vendor, - idev->card_device, - pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - idev->vendor, - idev->function, - pd))) { + if (!card->para[1] && isapnp_present()) { + struct pnp_dev *pnp_d; + while(ipid->card_vendor) { + if ((pnp_c = pnp_find_card(ipid->card_vendor, + ipid->card_device, pnp_c))) { + pnp_d = NULL; + if ((pnp_d = pnp_find_dev(pnp_c, + ipid->vendor, ipid->function, pnp_d))) { + int err; + printk(KERN_INFO "HiSax: %s detected\n", - (char *)idev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "ITK PnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "ITK PnP: activate failed\n"); - pnp_device_detach(pd); - return 0; + (char *)ipid->driver_data); + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); } - if (!pnp_port_valid(pd, 0) || !pnp_irq_valid(pd, 0)) { + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[0] = pnp_irq(pnp_d, 0); + if (!card->para[0] || !card->para[1]) { printk(KERN_ERR "ITK PnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); + card->para[0], card->para[1]); + pnp_disable_dev(pnp_d); return(0); } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); - if (ix1_probe(card->cs, card)) - return 0; - return 1; + break; } else { printk(KERN_ERR "ITK PnP: PnP error card found, no device\n"); } } - idev++; - pnp_c=NULL; + ipid++; + pnp_c = NULL; } - if (!idev->card_vendor) { + if (!ipid->card_vendor) { printk(KERN_INFO "ITK PnP: no ISAPnP card found\n"); + return(0); } } #endif - return 0; + /* IO-Ports */ + cs->hw.ix1.isac_ale = card->para[1] + ISAC_COMMAND_OFFSET; + cs->hw.ix1.hscx_ale = card->para[1] + HSCX_COMMAND_OFFSET; + cs->hw.ix1.isac = card->para[1] + ISAC_DATA_OFFSET; + cs->hw.ix1.hscx = card->para[1] + HSCX_DATA_OFFSET; + cs->hw.ix1.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + if (cs->hw.ix1.cfg_reg) { + if (!request_region(cs->hw.ix1.cfg_reg, 4, "ix1micro cfg")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.ix1.cfg_reg, + cs->hw.ix1.cfg_reg + 4); + return (0); + } + } + printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n", + CardType[cs->typ], cs->irq, cs->hw.ix1.cfg_reg); + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &ix1_card_msg; + cs->irq_func = &ix1micro_interrupt; + ISACVersion(cs, "ix1-Micro:"); + if (HscxVersion(cs, "ix1-Micro:")) { + printk(KERN_WARNING + "ix1-Micro: wrong HSCX versions check IO address\n"); + release_io_ix1micro(cs); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/jade.c b/drivers/isdn/hisax/jade.c --- a/drivers/isdn/hisax/jade.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hisax/jade.c Thu Feb 19 23:44:24 2004 @@ -1,4 +1,4 @@ -/* $Id: jade.c,v 1.6.6.3 2001/09/23 22:24:49 kai Exp $ +/* $Id: jade.c,v 1.9.2.4 2004/01/14 16:04:48 keil Exp $ * * JADE stuff (derived from original hscx.c) * @@ -18,38 +18,17 @@ #include "isdnl1.h" #include -static spinlock_t jade_lock = SPIN_LOCK_UNLOCKED; -static inline u8 -jade_read_reg(struct IsdnCardState *cs, int jade, u8 addr) -{ - return cs->bc_hw_ops->read_reg(cs, jade, addr); -} - -static inline void -jade_write_reg(struct IsdnCardState *cs, int jade, u8 addr, u8 val) -{ - cs->bc_hw_ops->write_reg(cs, jade, addr, val); -} - -static inline void -jade_write_fifo(struct BCState *bcs, u8 *p, int len) -{ - struct IsdnCardState *cs = bcs->cs; - - cs->bc_hw_ops->write_fifo(cs, bcs->unit, p, len); -} - -static int +int __init JadeVersion(struct IsdnCardState *cs, char *s) { int ver,i; int to = 50; - jade_write_reg(cs, -1, 0x50, 0x19); + cs->BC_Write_Reg(cs, -1, 0x50, 0x19); i=0; while (to) { udelay(1); - ver = jade_read_reg(cs, -1, 0x60); + ver = cs->BC_Read_Reg(cs, -1, 0x60); to--; if (ver) break; @@ -61,39 +40,36 @@ /* Wait for the JADE */ udelay(10); /* Read version */ - ver = jade_read_reg(cs, -1, 0x60); + ver = cs->BC_Read_Reg(cs, -1, 0x60); printk(KERN_INFO "%s JADE version: %d\n", s, ver); return (1); } /* Write to indirect accessible jade register set */ static void -jade_write_indirect(struct IsdnCardState *cs, u8 reg, u8 value) +jade_write_indirect(struct IsdnCardState *cs, u_char reg, u_char value) { int to = 50; - unsigned long flags; - u8 ret; - spin_lock_irqsave(&jade_lock, flags); + u_char ret; + /* Write the data */ - jade_write_reg(cs, -1, COMM_JADE+1, value); + cs->BC_Write_Reg(cs, -1, COMM_JADE+1, value); /* Say JADE we wanna write indirect reg 'reg' */ - jade_write_reg(cs, -1, COMM_JADE, reg); + cs->BC_Write_Reg(cs, -1, COMM_JADE, reg); to = 50; /* Wait for RDY goes high */ while (to) { udelay(1); - ret = jade_read_reg(cs, -1, COMM_JADE); + ret = cs->BC_Read_Reg(cs, -1, COMM_JADE); to--; if (ret & 1) /* Got acknowledge */ break; if (!to) { - spin_unlock_irqrestore(&jade_lock, flags); printk(KERN_INFO "Can not see ready bit from JADE DSP (reg=0x%X, value=0x%X)\n", reg, value); return; } } - spin_unlock_irqrestore(&jade_lock, flags); } @@ -102,7 +78,7 @@ modejade(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - int jade = bcs->unit; + int jade = bcs->hw.hscx.hscx; if (cs->debug & L1_DEB_HSCX) { char tmp[40]; @@ -113,75 +89,103 @@ bcs->mode = mode; bcs->channel = bc; - jade_write_reg(cs, jade, jade_HDLC_MODE, (mode == L1_MODE_TRANS ? jadeMODE_TMO:0x00)); - jade_write_reg(cs, jade, jade_HDLC_CCR0, (jadeCCR0_PU|jadeCCR0_ITF)); - jade_write_reg(cs, jade, jade_HDLC_CCR1, 0x00); + cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (mode == L1_MODE_TRANS ? jadeMODE_TMO:0x00)); + cs->BC_Write_Reg(cs, jade, jade_HDLC_CCR0, (jadeCCR0_PU|jadeCCR0_ITF)); + cs->BC_Write_Reg(cs, jade, jade_HDLC_CCR1, 0x00); jade_write_indirect(cs, jade_HDLC1SERRXPATH, 0x08); jade_write_indirect(cs, jade_HDLC2SERRXPATH, 0x08); jade_write_indirect(cs, jade_HDLC1SERTXPATH, 0x00); jade_write_indirect(cs, jade_HDLC2SERTXPATH, 0x00); - jade_write_reg(cs, jade, jade_HDLC_XCCR, 0x07); - jade_write_reg(cs, jade, jade_HDLC_RCCR, 0x07); + cs->BC_Write_Reg(cs, jade, jade_HDLC_XCCR, 0x07); + cs->BC_Write_Reg(cs, jade, jade_HDLC_RCCR, 0x07); if (bc == 0) { - jade_write_reg(cs, jade, jade_HDLC_TSAX, 0x00); - jade_write_reg(cs, jade, jade_HDLC_TSAR, 0x00); + cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAX, 0x00); + cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAR, 0x00); } else { - jade_write_reg(cs, jade, jade_HDLC_TSAX, 0x04); - jade_write_reg(cs, jade, jade_HDLC_TSAR, 0x04); + cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAX, 0x04); + cs->BC_Write_Reg(cs, jade, jade_HDLC_TSAR, 0x04); } switch (mode) { case (L1_MODE_NULL): - jade_write_reg(cs, jade, jade_HDLC_MODE, jadeMODE_TMO); + cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, jadeMODE_TMO); break; case (L1_MODE_TRANS): - jade_write_reg(cs, jade, jade_HDLC_MODE, (jadeMODE_TMO|jadeMODE_RAC|jadeMODE_XAC)); + cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (jadeMODE_TMO|jadeMODE_RAC|jadeMODE_XAC)); break; case (L1_MODE_HDLC): - jade_write_reg(cs, jade, jade_HDLC_MODE, (jadeMODE_RAC|jadeMODE_XAC)); + cs->BC_Write_Reg(cs, jade, jade_HDLC_MODE, (jadeMODE_RAC|jadeMODE_XAC)); break; } if (mode) { - jade_write_reg(cs, jade, jade_HDLC_RCMD, (jadeRCMD_RRES|jadeRCMD_RMC)); - jade_write_reg(cs, jade, jade_HDLC_XCMD, jadeXCMD_XRES); + cs->BC_Write_Reg(cs, jade, jade_HDLC_RCMD, (jadeRCMD_RRES|jadeRCMD_RMC)); + cs->BC_Write_Reg(cs, jade, jade_HDLC_XCMD, jadeXCMD_XRES); /* Unmask ints */ - jade_write_reg(cs, jade, jade_HDLC_IMR, 0xF8); + cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0xF8); } else /* Mask ints */ - jade_write_reg(cs, jade, jade_HDLC_IMR, 0x00); + cs->BC_Write_Reg(cs, jade, jade_HDLC_IMR, 0x00); } static void jade_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->hw.hscx.count = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "jade_l2l1: this shouldn't happen\n"); + } else { + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->hw.hscx.count = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - modejade(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + modejade(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - modejade(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + modejade(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -189,14 +193,53 @@ void close_jadestate(struct BCState *bcs) { - modejade(bcs, 0, bcs->channel); - bc_close(bcs); + modejade(bcs, 0, bcs->channel); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.hscx.rcvbuf) { + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + } + if (bcs->blog) { + kfree(bcs->blog); + bcs->blog = NULL; + } + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); + if (bcs->tx_skb) { + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } } static int open_jadestate(struct IsdnCardState *cs, struct BCState *bcs) { - return bc_open(bcs);; + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + if (!(bcs->hw.hscx.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for hscx.rcvbuf\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + return (1); + } + if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for bcs->blog\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + kfree(bcs->hw.hscx.rcvbuf); + bcs->hw.hscx.rcvbuf = NULL; + return (2); + } + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->event = 0; + bcs->hw.hscx.rcvidx = 0; + bcs->tx_cnt = 0; + return (0); } @@ -207,74 +250,69 @@ if (open_jadestate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = jade_l2l1; + st->l2.l2l1 = jade_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); return (0); } -static void jade_fill_fifo(struct BCState *bcs); - -static struct bc_l1_ops jade_l1_ops = { - .fill_fifo = jade_fill_fifo, - .open = setstack_jade, - .close = close_jadestate, -}; - void __init -initjade(struct IsdnCardState *cs) +clear_pending_jade_ints(struct IsdnCardState *cs) { int val; + char tmp[64]; - cs->bc_l1_ops = &jade_l1_ops; - cs->bcs[0].unit = 0; - cs->bcs[1].unit = 1; - - jade_write_reg(cs, 0, jade_HDLC_IMR, 0x00); - jade_write_reg(cs, 1, jade_HDLC_IMR, 0x00); - - val = jade_read_reg(cs, 1, jade_HDLC_ISR); - debugl1(cs, "jade B ISTA %x", val); - val = jade_read_reg(cs, 0, jade_HDLC_ISR); - debugl1(cs, "jade A ISTA %x", val); - val = jade_read_reg(cs, 1, jade_HDLC_STAR); - debugl1(cs, "jade B STAR %x", val); - val = jade_read_reg(cs, 0, jade_HDLC_STAR); - debugl1(cs, "jade A STAR %x", val); + cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0x00); + cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00); + val = cs->BC_Read_Reg(cs, 1, jade_HDLC_ISR); + sprintf(tmp, "jade B ISTA %x", val); + debugl1(cs, tmp); + val = cs->BC_Read_Reg(cs, 0, jade_HDLC_ISR); + sprintf(tmp, "jade A ISTA %x", val); + debugl1(cs, tmp); + val = cs->BC_Read_Reg(cs, 1, jade_HDLC_STAR); + sprintf(tmp, "jade B STAR %x", val); + debugl1(cs, tmp); + val = cs->BC_Read_Reg(cs, 0, jade_HDLC_STAR); + sprintf(tmp, "jade A STAR %x", val); + debugl1(cs, tmp); /* Unmask ints */ - jade_write_reg(cs, 0, jade_HDLC_IMR, 0xF8); - jade_write_reg(cs, 1, jade_HDLC_IMR, 0xF8); + cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0xF8); + cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0xF8); +} + +void __init +initjade(struct IsdnCardState *cs) +{ + cs->bcs[0].BC_SetStack = setstack_jade; + cs->bcs[1].BC_SetStack = setstack_jade; + cs->bcs[0].BC_Close = close_jadestate; + cs->bcs[1].BC_Close = close_jadestate; + cs->bcs[0].hw.hscx.hscx = 0; + cs->bcs[1].hw.hscx.hscx = 1; /* Stop DSP audio tx/rx */ jade_write_indirect(cs, 0x11, 0x0f); jade_write_indirect(cs, 0x17, 0x2f); /* Transparent Mode, RxTx inactive, No Test, No RFS/TFS */ - jade_write_reg(cs, 0, jade_HDLC_MODE, jadeMODE_TMO); - jade_write_reg(cs, 1, jade_HDLC_MODE, jadeMODE_TMO); + cs->BC_Write_Reg(cs, 0, jade_HDLC_MODE, jadeMODE_TMO); + cs->BC_Write_Reg(cs, 1, jade_HDLC_MODE, jadeMODE_TMO); /* Power down, 1-Idle, RxTx least significant bit first */ - jade_write_reg(cs, 0, jade_HDLC_CCR0, 0x00); - jade_write_reg(cs, 1, jade_HDLC_CCR0, 0x00); + cs->BC_Write_Reg(cs, 0, jade_HDLC_CCR0, 0x00); + cs->BC_Write_Reg(cs, 1, jade_HDLC_CCR0, 0x00); /* Mask all interrupts */ - jade_write_reg(cs, 0, jade_HDLC_IMR, 0x00); - jade_write_reg(cs, 1, jade_HDLC_IMR, 0x00); + cs->BC_Write_Reg(cs, 0, jade_HDLC_IMR, 0x00); + cs->BC_Write_Reg(cs, 1, jade_HDLC_IMR, 0x00); /* Setup host access to hdlc controller */ jade_write_indirect(cs, jade_HDLCCNTRACCESS, (jadeINDIRECT_HAH1|jadeINDIRECT_HAH2)); /* Unmask HDLC int (don´t forget DSP int later on)*/ - jade_write_reg(cs, -1,jade_INT, (jadeINT_HDLC1|jadeINT_HDLC2)); + cs->BC_Write_Reg(cs, -1,jade_INT, (jadeINT_HDLC1|jadeINT_HDLC2)); /* once again TRANSPARENT */ modejade(cs->bcs, 0, 0); modejade(cs->bcs + 1, 0, 0); } -int -jade_setup(struct IsdnCardState *cs, struct bc_hw_ops *jade_ops) -{ - cs->bc_hw_ops = jade_ops; - return JadeVersion(cs, "HiSax:"); -} - -#include "jade_irq.c" diff -Nru a/drivers/isdn/hisax/jade.h b/drivers/isdn/hisax/jade.h --- a/drivers/isdn/hisax/jade.h Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/jade.h Thu Feb 19 23:44:23 2004 @@ -1,4 +1,4 @@ -/* $Id: jade.h,v 1.3.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: jade.h,v 1.5.2.3 2004/01/14 16:04:48 keil Exp $ * * JADE specific defines * @@ -127,10 +127,9 @@ #define jade_TXAUDIOCH1CFG 0x17 #define jade_TXAUDIOCH2CFG 0x1A -extern void jade_sched_event(struct BCState *bcs, int event); +extern int JadeVersion(struct IsdnCardState *cs, char *s); extern void modejade(struct BCState *bcs, int mode, int bc); +extern void clear_pending_jade_ints(struct IsdnCardState *cs); extern void initjade(struct IsdnCardState *cs); -extern void jade_int_main(struct IsdnCardState *cs, u8 val, int jade); -extern int jade_setup(struct IsdnCardState *cs, struct bc_hw_ops *jade_ops); #endif /* __JADE_H__ */ diff -Nru a/drivers/isdn/hisax/jade_irq.c b/drivers/isdn/hisax/jade_irq.c --- a/drivers/isdn/hisax/jade_irq.c Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/jade_irq.c Thu Feb 19 23:44:23 2004 @@ -1,4 +1,4 @@ -/* $Id: jade_irq.c,v 1.5.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: jade_irq.c,v 1.7.2.4 2004/02/11 13:21:34 keil Exp $ * * Low level JADE IRQ stuff (derived from original hscx_irq.c) * @@ -15,7 +15,7 @@ { int to = 50; int mask = (reg == jade_HDLC_XCMD ? jadeSTAR_XCEC : jadeSTAR_RCEC); - while ((jade_read_reg(cs, jade, jade_HDLC_STAR) & mask) && to) { + while ((READJADE(cs, jade, jade_HDLC_STAR) & mask) && to) { udelay(1); to--; } @@ -25,17 +25,16 @@ static inline void -waitforXFW(struct BCState *bcs) +waitforXFW(struct IsdnCardState *cs, int jade) { + /* Does not work on older jade versions, don't care */ } static inline void -WriteJADECMDR(struct BCState *bcs, int reg, u8 data) +WriteJADECMDR(struct IsdnCardState *cs, int jade, int reg, u_char data) { - int jade = bcs->unit; - - waitforCEC(bcs->cs, jade, reg); - jade_write_reg(bcs->cs, jade, reg, data); + waitforCEC(cs, jade, reg); + WRITEJADE(cs, jade, reg, data); } @@ -43,33 +42,80 @@ static void jade_empty_fifo(struct BCState *bcs, int count) { - recv_empty_fifo_b(bcs, count); - WriteJADECMDR(bcs, jade_HDLC_RCMD, jadeRCMD_RMC); + u_char *ptr; + struct IsdnCardState *cs = bcs->cs; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "jade_empty_fifo"); + + if (bcs->hw.hscx.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "jade_empty_fifo: incoming packet too large"); + WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC); + bcs->hw.hscx.rcvidx = 0; + return; + } + ptr = bcs->hw.hscx.rcvbuf + bcs->hw.hscx.rcvidx; + bcs->hw.hscx.rcvidx += count; + READJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count); + WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_RCMD, jadeRCMD_RMC); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "jade_empty_fifo %c cnt %d", + bcs->hw.hscx.hscx ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } static void jade_fill_fifo(struct BCState *bcs) { + struct IsdnCardState *cs = bcs->cs; int more, count; int fifo_size = 32; - unsigned char *p; + u_char *ptr; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "jade_fill_fifo"); - p = xmit_fill_fifo_b(bcs, fifo_size, &count, &more); - if (!p) + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) return; - waitforXFW(bcs); - jade_write_fifo(bcs, p, count); - WriteJADECMDR(bcs, jade_HDLC_XCMD, - more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME)); + more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; + if (bcs->tx_skb->len > fifo_size) { + more = !0; + count = fifo_size; + } else + count = bcs->tx_skb->len; + + waitforXFW(cs, bcs->hw.hscx.hscx); + ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.hscx.count += count; + WRITEJADEFIFO(cs, bcs->hw.hscx.hscx, ptr, count); + WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, more ? jadeXCMD_XF : (jadeXCMD_XF|jadeXCMD_XME)); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "jade_fill_fifo %c cnt %d", + bcs->hw.hscx.hscx ? 'B' : 'A', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } static inline void -jade_interrupt(struct IsdnCardState *cs, u8 val, u8 jade) +jade_interrupt(struct IsdnCardState *cs, u_char val, u_char jade) { - u8 r; + u_char r; struct BCState *bcs = cs->bcs + jade; + struct sk_buff *skb; int fifo_size = 32; int count; int i_jade = (int) jade; /* To satisfy the compiler */ @@ -78,7 +124,7 @@ return; if (val & 0x80) { /* RME */ - r = jade_read_reg(cs, i_jade, jade_HDLC_RSTA); + r = READJADE(cs, i_jade, jade_HDLC_RSTA); if ((r & 0xf0) != 0xa0) { if (!(r & 0x80)) if (cs->debug & L1_DEB_WARN) @@ -89,34 +135,72 @@ if (!(r & 0x20)) if (cs->debug & L1_DEB_WARN) debugl1(cs, "JADE %c CRC error", 'A'+jade); - WriteJADECMDR(bcs, jade_HDLC_RCMD, jadeRCMD_RMC); - bcs->rcvidx = 0; + WriteJADECMDR(cs, jade, jade_HDLC_RCMD, jadeRCMD_RMC); } else { - count = jade_read_reg(cs, i_jade, jade_HDLC_RBCL) & 0x1F; + count = READJADE(cs, i_jade, jade_HDLC_RBCL) & 0x1F; if (count == 0) count = fifo_size; - jade_empty_fifo(bcs, count); - recv_rme_b(bcs); + if ((count = bcs->hw.hscx.rcvidx - 1) > 0) { + if (cs->debug & L1_DEB_HSCX_FIFO) + debugl1(cs, "HX Frame %d", count); + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "JADE %s receive out of memory\n", (jade ? "B":"A")); + else { + memcpy(skb_put(skb, count), bcs->hw.hscx.rcvbuf, count); + skb_queue_tail(&bcs->rqueue, skb); + } + } } + bcs->hw.hscx.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); } if (val & 0x40) { /* RPF */ jade_empty_fifo(bcs, fifo_size); - recv_rpf_b(bcs); + if (bcs->mode == L1_MODE_TRANS) { + /* receive audio data */ + if (!(skb = dev_alloc_skb(fifo_size))) + printk(KERN_WARNING "HiSax: receive out of memory\n"); + else { + memcpy(skb_put(skb, fifo_size), bcs->hw.hscx.rcvbuf, fifo_size); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.hscx.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); + } } if (val & 0x10) { /* XPR */ - xmit_xpr_b(bcs); + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + jade_fill_fifo(bcs); + return; + } else { + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.hscx.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_irq(bcs->tx_skb); + bcs->hw.hscx.count = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.hscx.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + jade_fill_fifo(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + schedule_event(bcs, B_XMTBUFREADY); + } } } -static void -reset_xmit(struct BCState *bcs) -{ - WriteJADECMDR(bcs, jade_HDLC_XCMD, jadeXCMD_XRES); -} - -void -jade_int_main(struct IsdnCardState *cs, u8 val, int jade) +static inline void +jade_int_main(struct IsdnCardState *cs, u_char val, int jade) { struct BCState *bcs; bcs = cs->bcs + jade; @@ -126,7 +210,23 @@ val &= ~jadeISR_RFO; } if (val & jadeISR_XDU) { - xmit_xdu_b(bcs, reset_xmit); + /* relevant in HDLC mode only */ + /* don't reset XPR here */ + if (bcs->mode == 1) + jade_fill_fifo(bcs); + else { + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.hscx.count); + bcs->tx_cnt += bcs->hw.hscx.count; + bcs->hw.hscx.count = 0; + } + WriteJADECMDR(cs, bcs->hw.hscx.hscx, jade_HDLC_XCMD, jadeXCMD_XRES); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "JADE %c EXIR %x Lost TX", 'A'+jade, val); + } } if (val & (jadeISR_RME|jadeISR_RPF|jadeISR_XPR)) { if (cs->debug & L1_DEB_HSCX) diff -Nru a/drivers/isdn/hisax/l3_1tr6.c b/drivers/isdn/hisax/l3_1tr6.c --- a/drivers/isdn/hisax/l3_1tr6.c Thu Feb 19 23:44:26 2004 +++ b/drivers/isdn/hisax/l3_1tr6.c Thu Feb 19 23:44:26 2004 @@ -1,4 +1,4 @@ -/* $Id: l3_1tr6.c,v 2.13.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: l3_1tr6.c,v 2.15.2.3 2004/01/13 14:31:25 keil Exp $ * * German 1TR6 D-channel protocol * @@ -19,7 +19,7 @@ #include extern char *HiSax_getrev(const char *revision); -const char *l3_1tr6_revision = "$Revision: 2.13.6.2 $"; +const char *l3_1tr6_revision = "$Revision: 2.15.2.3 $"; #define MsgHead(ptr, cref, mty, dis) \ *ptr++ = dis; \ @@ -28,10 +28,10 @@ *ptr++ = mty static void -l3_1TR6_message(struct l3_process *pc, u8 mt, u8 pd) +l3_1TR6_message(struct l3_process *pc, u_char mt, u_char pd) { struct sk_buff *skb; - u8 *p; + u_char *p; if (!(skb = l3_alloc_skb(4))) return; @@ -41,7 +41,7 @@ } static void -l3_1tr6_release_req(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_release_req(struct l3_process *pc, u_char pr, void *arg) { StopAllL3Timer(pc); newl3state(pc, 19); @@ -50,7 +50,7 @@ } static void -l3_1tr6_invalid(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_invalid(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; @@ -59,7 +59,7 @@ } static void -l3_1tr6_error(struct l3_process *pc, u8 *msg, struct sk_buff *skb) +l3_1tr6_error(struct l3_process *pc, u_char *msg, struct sk_buff *skb) { dev_kfree_skb(skb); if (pc->st->l3.debug & L3_DEB_WARN) @@ -68,14 +68,14 @@ } static void -l3_1tr6_setup_req(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_setup_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[128]; - u8 *p = tmp; - u8 *teln; - u8 *eaz; - u8 channel = 0; + u_char tmp[128]; + u_char *p = tmp; + u_char *teln; + u_char *eaz; + u_char channel = 0; int l; MsgHead(p, pc->callref, MT_N1_SETUP, PROTO_DIS_N1); @@ -157,9 +157,9 @@ } static void -l3_1tr6_setup(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_setup(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; int bcfound = 0; char tmp[80]; struct sk_buff *skb = arg; @@ -222,15 +222,15 @@ l3_debug(pc->st, tmp); } newl3state(pc, 6); - L3L4(pc->st, CC_SETUP | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc); } else release_l3_process(pc); } static void -l3_1tr6_setup_ack(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_setup_ack(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; struct sk_buff *skb = arg; L3DelTimer(&pc->timer); @@ -252,13 +252,13 @@ } dev_kfree_skb(skb); L3AddTimer(&pc->timer, T304, CC_T304); - L3L4(pc->st, CC_MORE_INFO | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); } static void -l3_1tr6_call_sent(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_call_sent(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; struct sk_buff *skb = arg; L3DelTimer(&pc->timer); @@ -284,26 +284,25 @@ dev_kfree_skb(skb); L3AddTimer(&pc->timer, T310, CC_T310); newl3state(pc, 3); - L3L4(pc->st, CC_PROCEEDING | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc); } static void -l3_1tr6_alert(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_alert(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; dev_kfree_skb(skb); L3DelTimer(&pc->timer); /* T304 */ newl3state(pc, 4); - L3L4(pc->st, CC_ALERTING | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc); } static void -l3_1tr6_info(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_info(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; - u_int i; - int tmpcharge = 0; + u_char *p; + int i, tmpcharge = 0; char a_charge[8], tmp[32]; struct sk_buff *skb = arg; @@ -316,7 +315,7 @@ } if (tmpcharge > pc->para.chargeinfo) { pc->para.chargeinfo = tmpcharge; - L3L4(pc->st, CC_CHARGE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc); } if (pc->st->l3.debug & L3_DEB_CHARGE) { sprintf(tmp, "charging info %d", pc->para.chargeinfo); @@ -329,7 +328,7 @@ } static void -l3_1tr6_info_s2(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_info_s2(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; @@ -337,7 +336,7 @@ } static void -l3_1tr6_connect(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_connect(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; @@ -349,14 +348,14 @@ newl3state(pc, 10); dev_kfree_skb(skb); pc->para.chargeinfo = 0; - L3L4(pc->st, CC_SETUP | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc); } static void -l3_1tr6_rel(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_rel(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - u8 *p; + u_char *p; p = skb->data; if ((p = findie(p, skb->len, WE0_cause, 0))) { @@ -379,12 +378,12 @@ StopAllL3Timer(pc); newl3state(pc, 0); l3_1TR6_message(pc, MT_N1_REL_ACK, PROTO_DIS_N1); - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); release_l3_process(pc); } static void -l3_1tr6_rel_ack(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_rel_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; @@ -392,17 +391,16 @@ StopAllL3Timer(pc); newl3state(pc, 0); pc->para.cause = NO_CAUSE; - L3L4(pc->st, CC_RELEASE | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc); release_l3_process(pc); } static void -l3_1tr6_disc(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_disc(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - u8 *p; - u_int i; - int tmpcharge = 0; + u_char *p; + int i, tmpcharge = 0; char a_charge[8], tmp[32]; StopAllL3Timer(pc); @@ -415,7 +413,7 @@ } if (tmpcharge > pc->para.chargeinfo) { pc->para.chargeinfo = tmpcharge; - L3L4(pc->st, CC_CHARGE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_CHARGE | INDICATION, pc); } if (pc->st->l3.debug & L3_DEB_CHARGE) { sprintf(tmp, "charging info %d", pc->para.chargeinfo); @@ -448,12 +446,12 @@ } dev_kfree_skb(skb); newl3state(pc, 12); - L3L4(pc->st, CC_DISCONNECT | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc); } static void -l3_1tr6_connect_ack(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_connect_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; @@ -465,22 +463,22 @@ newl3state(pc, 10); pc->para.chargeinfo = 0; L3DelTimer(&pc->timer); - L3L4(pc->st, CC_SETUP_COMPL | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc); } static void -l3_1tr6_alert_req(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_alert_req(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 7); l3_1TR6_message(pc, MT_N1_ALERT, PROTO_DIS_N1); } static void -l3_1tr6_setup_rsp(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_setup_rsp(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[24]; - u8 *p = tmp; + u_char tmp[24]; + u_char *p = tmp; int l; MsgHead(p, pc->callref, MT_N1_CONN, PROTO_DIS_N1); @@ -510,20 +508,20 @@ } static void -l3_1tr6_reset(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_reset(struct l3_process *pc, u_char pr, void *arg) { release_l3_process(pc); } static void -l3_1tr6_disconnect_req(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_disconnect_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; - u8 cause = 0x10; - u8 clen = 1; + u_char cause = 0x10; + u_char clen = 1; if (pc->para.cause > 0) cause = pc->para.cause; @@ -555,7 +553,7 @@ } static void -l3_1tr6_t303(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_t303(struct l3_process *pc, u_char pr, void *arg) { if (pc->N303 > 0) { pc->N303--; @@ -569,23 +567,23 @@ } static void -l3_1tr6_t304(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_t304(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.cause = 0xE6; l3_1tr6_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3_1tr6_t305(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_t305(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; - u8 cause = 0x90; - u8 clen = 1; + u_char cause = 0x90; + u_char clen = 1; L3DelTimer(&pc->timer); if (pc->para.cause != NO_CAUSE) @@ -614,25 +612,25 @@ } static void -l3_1tr6_t310(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_t310(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.cause = 0xE6; l3_1tr6_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3_1tr6_t313(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_t313(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.cause = 0xE6; l3_1tr6_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_CONNECT_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc); } static void -l3_1tr6_t308_1(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_t308_1(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); l3_1TR6_message(pc, MT_N1_REL, PROTO_DIS_N1); @@ -641,28 +639,28 @@ } static void -l3_1tr6_t308_2(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_t308_2(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RELEASE_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc); release_l3_process(pc); } static void -l3_1tr6_dl_reset(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_dl_reset(struct l3_process *pc, u_char pr, void *arg) { pc->para.cause = CAUSE_LocalProcErr; l3_1tr6_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3_1tr6_dl_release(struct l3_process *pc, u8 pr, void *arg) +l3_1tr6_dl_release(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 0); pc->para.cause = 0x1b; /* Destination out of order */ pc->para.loc = 0; - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); release_l3_process(pc); } @@ -755,8 +753,7 @@ static void up1tr6(struct PStack *st, int pr, void *arg) { - u_int i; - int mt, cr; + int i, mt, cr; struct l3_process *proc; struct sk_buff *skb = arg; char tmp[80]; @@ -871,8 +868,7 @@ static void down1tr6(struct PStack *st, int pr, void *arg) { - u_int i; - int cr; + int i, cr; struct l3_process *proc; struct Channel *chan; char tmp[80]; @@ -919,7 +915,7 @@ static void man1tr6(struct PStack *st, int pr, void *arg) { - u_int i; + int i; struct l3_process *proc = arg; if (!proc) { @@ -949,8 +945,8 @@ { char tmp[64]; - st->l3.l4l3 = down1tr6; - st->l3.l2l3 = up1tr6; + st->lli.l4l3 = down1tr6; + st->l2.l2l3 = up1tr6; st->l3.l3ml3 = man1tr6; st->l3.N303 = 0; diff -Nru a/drivers/isdn/hisax/l3dss1.c b/drivers/isdn/hisax/l3dss1.c --- a/drivers/isdn/hisax/l3dss1.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hisax/l3dss1.c Thu Feb 19 23:44:24 2004 @@ -1,4 +1,4 @@ -/* $Id: l3dss1.c,v 2.30.6.2 2001/09/23 22:24:49 kai Exp $ +/* $Id: l3dss1.c,v 2.32.2.3 2004/01/13 14:31:25 keil Exp $ * * EURO/DSS1 D-channel protocol * @@ -26,8 +26,7 @@ #include extern char *HiSax_getrev(const char *revision); -const char *dss1_revision = "$Revision: 2.30.6.2 $"; -static spinlock_t l3dss1_lock = SPIN_LOCK_UNLOCKED; +const char *dss1_revision = "$Revision: 2.32.2.3 $"; #define EXT_BEARER_CAPS 1 @@ -49,13 +48,10 @@ static unsigned char new_invoke_id(struct PStack *p) { unsigned char retval; - unsigned long flags; int i; i = 32; /* maximum search depth */ - spin_lock_irqsave(&l3dss1_lock, flags); - retval = p->prot.dss1.last_invoke_id + 1; /* try new id */ while ((i) && (p->prot.dss1.invoke_used[retval >> 3] == 0xFF)) { p->prot.dss1.last_invoke_id = (retval & 0xF8) + 8; @@ -68,8 +64,6 @@ retval = 0; p->prot.dss1.last_invoke_id = retval; p->prot.dss1.invoke_used[retval >> 3] |= (1 << (retval & 7)); - spin_unlock_irqrestore(&l3dss1_lock, flags); - return(retval); } /* new_invoke_id */ @@ -77,13 +71,11 @@ /* free a used invoke id */ /*************************/ static void free_invoke_id(struct PStack *p, unsigned char id) -{ unsigned long flags; +{ if (!id) return; /* 0 = invalid value */ - spin_lock_irqsave(&l3dss1_lock, flags); p->prot.dss1.invoke_used[id >> 3] &= ~(1 << (id & 7)); - spin_unlock_irqrestore(&l3dss1_lock, flags); } /* free_invoke_id */ @@ -136,7 +128,7 @@ /* and a return result is delivered. id specifies the invoke id. */ /*******************************************************************/ static void -l3dss1_dummy_return_result(struct PStack *st, int id, u8 *p, u8 nlen) +l3dss1_dummy_return_result(struct PStack *st, int id, u_char *p, u_char nlen) { isdn_ctrl ic; struct IsdnCardState *cs; struct l3_process *pc = NULL; @@ -203,7 +195,7 @@ /*******************************************************************/ static void l3dss1_dummy_invoke(struct PStack *st, int cr, int id, - int ident, u8 *p, u8 nlen) + int ident, u_char *p, u_char nlen) { isdn_ctrl ic; struct IsdnCardState *cs; @@ -227,7 +219,7 @@ static void l3dss1_parse_facility(struct PStack *st, struct l3_process *pc, - int cr, u8 * p) + int cr, u_char * p) { int qd_len = 0; unsigned char nlen = 0, ilen, cp_tag; @@ -447,7 +439,7 @@ pc->prot.dss1.remote_result = 0; /* success */ pc->prot.dss1.invoke_id = 0; pc->redir_result = pc->prot.dss1.remote_result; - L3L4(st, CC_REDIR | INDICATION, pc); } /* Diversion successful */ + st->l3.l3l4(st, CC_REDIR | INDICATION, pc); } /* Diversion successful */ else l3_debug(st,"return error unknown identifier"); break; @@ -492,7 +484,7 @@ pc->prot.dss1.remote_result = err_ret; /* result */ pc->prot.dss1.invoke_id = 0; pc->redir_result = pc->prot.dss1.remote_result; - L3L4(st, CC_REDIR | INDICATION, pc); + st->l3.l3l4(st, CC_REDIR | INDICATION, pc); } /* Deflection error */ else l3_debug(st,"return result unknown identifier"); @@ -504,10 +496,10 @@ } static void -l3dss1_message(struct l3_process *pc, u8 mt) +l3dss1_message(struct l3_process *pc, u_char mt) { struct sk_buff *skb; - u8 *p; + u_char *p; if (!(skb = l3_alloc_skb(4))) return; @@ -517,11 +509,11 @@ } static void -l3dss1_message_cause(struct l3_process *pc, u8 mt, u8 cause) +l3dss1_message_cause(struct l3_process *pc, u_char mt, u_char cause) { struct sk_buff *skb; - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; MsgHead(p, pc->callref, mt); @@ -538,10 +530,10 @@ } static void -l3dss1_status_send(struct l3_process *pc, u8 pr, void *arg) +l3dss1_status_send(struct l3_process *pc, u_char pr, void *arg) { - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; struct sk_buff *skb; @@ -564,14 +556,14 @@ } static void -l3dss1_msg_without_setup(struct l3_process *pc, u8 pr, void *arg) +l3dss1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg) { /* This routine is called if here was no SETUP made (checks in dss1up and in * l3dss1_setup) and a RELEASE_COMPLETE have to be sent with an error code * MT_STATUS_ENQUIRE in the NULL state is handled too */ - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; struct sk_buff *skb; @@ -690,7 +682,7 @@ }; static int -getmax_ie_len(u8 ie) { +getmax_ie_len(u_char ie) { int i = 0; while (max_ie_len[i].ie != -1) { if (max_ie_len[i].ie == ie) @@ -701,7 +693,7 @@ } static int -ie_in_set(struct l3_process *pc, u8 ie, int *checklist) { +ie_in_set(struct l3_process *pc, u_char ie, int *checklist) { int ret = 1; while (*checklist != -1) { @@ -721,13 +713,13 @@ check_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist) { int *cl = checklist; - u8 mt; - u8 *p, ie; + u_char mt; + u_char *p, ie; int l, newpos, oldpos; int err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0; - u8 codeset = 0; - u8 old_codeset = 0; - u8 codelock = 1; + u_char codeset = 0; + u_char old_codeset = 0; + u_char codelock = 1; p = skb->data; /* skip cr */ @@ -736,7 +728,7 @@ p += l; mt = *p++; oldpos = 0; - while ((p - skb->data) < (int)skb->len) { + while ((p - skb->data) < skb->len) { if ((*p & 0xf0) == 0x90) { /* shift codeset */ old_codeset = codeset; codeset = *p & 7; @@ -870,7 +862,7 @@ static int l3dss1_get_channel_id(struct l3_process *pc, struct sk_buff *skb) { - u8 *p; + u_char *p; p = skb->data; if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) { @@ -893,8 +885,8 @@ static int l3dss1_get_cause(struct l3_process *pc, struct sk_buff *skb) { - u8 l, i=0; - u8 *p; + u_char l, i=0; + u_char *p; p = skb->data; pc->para.cause = 31; @@ -931,11 +923,11 @@ } static void -l3dss1_msg_with_uus(struct l3_process *pc, u8 cmd) +l3dss1_msg_with_uus(struct l3_process *pc, u_char cmd) { struct sk_buff *skb; - u8 tmp[16+40]; - u8 *p = tmp; + u_char tmp[16+40]; + u_char *p = tmp; int l; MsgHead(p, pc->callref, cmd); @@ -957,7 +949,7 @@ } /* l3dss1_msg_with_uus */ static void -l3dss1_release_req(struct l3_process *pc, u8 pr, void *arg) +l3dss1_release_req(struct l3_process *pc, u_char pr, void *arg) { StopAllL3Timer(pc); newl3state(pc, 19); @@ -969,7 +961,7 @@ } static void -l3dss1_release_cmpl(struct l3_process *pc, u8 pr, void *arg) +l3dss1_release_cmpl(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -981,14 +973,14 @@ pc->para.cause = NO_CAUSE; StopAllL3Timer(pc); newl3state(pc, 0); - L3L4(pc->st, CC_RELEASE | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc); dss1_release_l3_process(pc); } #if EXT_BEARER_CAPS -static u8 * -EncodeASyncParams(u8 * p, u8 si2) +static u_char * +EncodeASyncParams(u_char * p, u_char si2) { // 7c 06 88 90 21 42 00 bb p[0] = 0; @@ -1052,8 +1044,8 @@ return p + 3; } -static u8 -EncodeSyncParams(u8 si2, u8 ai) +static u_char +EncodeSyncParams(u_char si2, u_char ai) { switch (si2) { @@ -1097,10 +1089,10 @@ } -static u8 -DecodeASyncParams(u8 si2, u8 * p) +static u_char +DecodeASyncParams(u_char si2, u_char * p) { - u8 info; + u_char info; switch (p[5]) { case 66: // 1200 bit/s @@ -1154,8 +1146,8 @@ } -static u8 -DecodeSyncParams(u8 si2, u8 info) +static u_char +DecodeSyncParams(u_char si2, u_char info) { info &= 0x7f; switch (info) { @@ -1195,10 +1187,10 @@ } } -static u8 +static u_char DecodeSI2(struct sk_buff *skb) { - u8 *p; //, *pend=skb->data + skb->len; + u_char *p; //, *pend=skb->data + skb->len; if ((p = findie(skb->data, skb->len, 0x7c, 0))) { switch (p[4] & 0x0f) { @@ -1225,20 +1217,20 @@ static void -l3dss1_setup_req(struct l3_process *pc, u8 pr, +l3dss1_setup_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[128]; - u8 *p = tmp; - u8 channel = 0; - - u8 send_keypad; - u8 screen = 0x80; - u8 *teln; - u8 *msn; - u8 *sub; - u8 *sp; + u_char tmp[128]; + u_char *p = tmp; + u_char channel = 0; + + u_char send_keypad; + u_char screen = 0x80; + u_char *teln; + u_char *msn; + u_char *sub; + u_char *sp; int l; MsgHead(p, pc->callref, MT_SETUP); @@ -1436,7 +1428,7 @@ } static void -l3dss1_call_proc(struct l3_process *pc, u8 pr, void *arg) +l3dss1_call_proc(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int id, ret; @@ -1471,11 +1463,11 @@ L3AddTimer(&pc->timer, T310, CC_T310); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3dss1_std_ie_err(pc, ret); - L3L4(pc->st, CC_PROCEEDING | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc); } static void -l3dss1_setup_ack(struct l3_process *pc, u8 pr, void *arg) +l3dss1_setup_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int id, ret; @@ -1510,16 +1502,16 @@ L3AddTimer(&pc->timer, T304, CC_T304); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3dss1_std_ie_err(pc, ret); - L3L4(pc->st, CC_MORE_INFO | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); } static void -l3dss1_disconnect(struct l3_process *pc, u8 pr, void *arg) +l3dss1_disconnect(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - u8 *p; + u_char *p; int ret; - u8 cause = 0; + u_char cause = 0; StopAllL3Timer(pc); if ((ret = l3dss1_get_cause(pc, skb))) { @@ -1542,7 +1534,7 @@ if (cause) newl3state(pc, 19); if (11 != ret) - L3L4(pc->st, CC_DISCONNECT | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc); else if (!cause) l3dss1_release_req(pc, pr, NULL); if (cause) { @@ -1552,7 +1544,7 @@ } static void -l3dss1_connect(struct l3_process *pc, u8 pr, void *arg) +l3dss1_connect(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -1568,11 +1560,11 @@ /* here should inserted COLP handling KKe */ if (ret) l3dss1_std_ie_err(pc, ret); - L3L4(pc->st, CC_SETUP | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc); } static void -l3dss1_alerting(struct l3_process *pc, u8 pr, void *arg) +l3dss1_alerting(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -1586,13 +1578,13 @@ newl3state(pc, 4); if (ret) l3dss1_std_ie_err(pc, ret); - L3L4(pc->st, CC_ALERTING | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc); } static void -l3dss1_setup(struct l3_process *pc, u8 pr, void *arg) +l3dss1_setup(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; int bcfound = 0; char tmp[80]; struct sk_buff *skb = arg; @@ -1603,7 +1595,7 @@ * Bearer Capabilities */ p = skb->data; - /* only the first occurrence 'll be detected ! */ + /* only the first occurence 'll be detected ! */ if ((p = findie(p, skb->len, 0x04, 0))) { if ((p[1] < 2) || (p[1] > 11)) err = 1; @@ -1752,23 +1744,23 @@ newl3state(pc, 6); if (err) /* STATUS for none mandatory IE errors after actions are taken */ l3dss1_std_ie_err(pc, err); - L3L4(pc->st, CC_SETUP | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc); } static void -l3dss1_reset(struct l3_process *pc, u8 pr, void *arg) +l3dss1_reset(struct l3_process *pc, u_char pr, void *arg) { dss1_release_l3_process(pc); } static void -l3dss1_disconnect_req(struct l3_process *pc, u8 pr, void *arg) +l3dss1_disconnect_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[16+40]; - u8 *p = tmp; + u_char tmp[16+40]; + u_char *p = tmp; int l; - u8 cause = 16; + u_char cause = 16; if (pc->para.cause != NO_CAUSE) cause = pc->para.cause; @@ -1801,7 +1793,7 @@ } static void -l3dss1_setup_rsp(struct l3_process *pc, u8 pr, +l3dss1_setup_rsp(struct l3_process *pc, u_char pr, void *arg) { if (!pc->para.bchannel) @@ -1817,7 +1809,7 @@ } static void -l3dss1_connect_ack(struct l3_process *pc, u8 pr, void *arg) +l3dss1_connect_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -1831,17 +1823,17 @@ L3DelTimer(&pc->timer); if (ret) l3dss1_std_ie_err(pc, ret); - L3L4(pc->st, CC_SETUP_COMPL | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc); } static void -l3dss1_reject_req(struct l3_process *pc, u8 pr, void *arg) +l3dss1_reject_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; - u8 cause = 21; + u_char cause = 21; if (pc->para.cause != NO_CAUSE) cause = pc->para.cause; @@ -1858,16 +1850,16 @@ return; memcpy(skb_put(skb, l), tmp, l); l3_msg(pc->st, DL_DATA | REQUEST, skb); - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); dss1_release_l3_process(pc); } static void -l3dss1_release(struct l3_process *pc, u8 pr, void *arg) +l3dss1_release(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - u8 *p; + u_char *p; int ret, cause=0; StopAllL3Timer(pc); @@ -1892,13 +1884,13 @@ l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, cause); else l3dss1_message(pc, MT_RELEASE_COMPLETE); - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); dss1_release_l3_process(pc); } static void -l3dss1_alert_req(struct l3_process *pc, u8 pr, +l3dss1_alert_req(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 7); @@ -1909,16 +1901,16 @@ } static void -l3dss1_proceed_req(struct l3_process *pc, u8 pr, +l3dss1_proceed_req(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 9); l3dss1_message(pc, MT_CALL_PROCEEDING); - L3L4(pc->st, CC_PROCEED_SEND | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_PROCEED_SEND | INDICATION, pc); } static void -l3dss1_setup_ack_req(struct l3_process *pc, u8 pr, +l3dss1_setup_ack_req(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 25); @@ -1931,8 +1923,8 @@ /* deliver a incoming display message to HL */ /********************************************/ static void -l3dss1_deliver_display(struct l3_process *pc, int pr, u8 *infp) -{ u8 len; +l3dss1_deliver_display(struct l3_process *pc, int pr, u_char *infp) +{ u_char len; isdn_ctrl ic; struct IsdnCardState *cs; char *p; @@ -1954,11 +1946,11 @@ static void -l3dss1_progress(struct l3_process *pc, u8 pr, void *arg) +l3dss1_progress(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int err = 0; - u8 *p; + u_char *p; if ((p = findie(skb->data, skb->len, IE_PROGRESS, 0))) { if (p[1] != 2) { @@ -2007,15 +1999,15 @@ if (err) l3dss1_std_ie_err(pc, err); if (ERR_IE_COMPREHENSION != err) - L3L4(pc->st, CC_PROGRESS | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_PROGRESS | INDICATION, pc); } static void -l3dss1_notify(struct l3_process *pc, u8 pr, void *arg) +l3dss1_notify(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int err = 0; - u8 *p; + u_char *p; if ((p = findie(skb->data, skb->len, IE_NOTIFY, 0))) { if (p[1] != 1) { @@ -2048,11 +2040,11 @@ if (err) l3dss1_std_ie_err(pc, err); if (ERR_IE_COMPREHENSION != err) - L3L4(pc->st, CC_NOTIFY | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_NOTIFY | INDICATION, pc); } static void -l3dss1_status_enq(struct l3_process *pc, u8 pr, void *arg) +l3dss1_status_enq(struct l3_process *pc, u_char pr, void *arg) { int ret; struct sk_buff *skb = arg; @@ -2064,11 +2056,11 @@ } static void -l3dss1_information(struct l3_process *pc, u8 pr, void *arg) +l3dss1_information(struct l3_process *pc, u_char pr, void *arg) { int ret; struct sk_buff *skb = arg; - u8 *p; + u_char *p; char tmp[32]; ret = check_infoelements(pc, skb, ie_INFORMATION); @@ -2080,7 +2072,7 @@ if ((p = findie(p, skb->len, 0x70, 0))) { iecpy(tmp, p, 1); strcat(pc->para.setup.eazmsn, tmp); - L3L4(pc->st, CC_MORE_INFO | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); } L3AddTimer(&pc->timer, T302, CC_T302); } @@ -2089,14 +2081,14 @@ /******************************/ /* handle deflection requests */ /******************************/ -static void l3dss1_redir_req(struct l3_process *pc, u8 pr, void *arg) +static void l3dss1_redir_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[128]; - u8 *p = tmp; - u8 *subp; - u8 len_phone = 0; - u8 len_sub = 0; + u_char tmp[128]; + u_char *p = tmp; + u_char *subp; + u_char len_phone = 0; + u_char len_sub = 0; int l; @@ -2161,7 +2153,7 @@ /********************************************/ /* handle deflection request in early state */ /********************************************/ -static void l3dss1_redir_req_early(struct l3_process *pc, u8 pr, void *arg) +static void l3dss1_redir_req_early(struct l3_process *pc, u_char pr, void *arg) { l3dss1_proceed_req(pc,pr,arg); l3dss1_redir_req(pc,pr,arg); @@ -2169,13 +2161,13 @@ /***********************************************/ /* handle special commands for this protocol. */ -/* Examples are call independent services like */ +/* Examples are call independant services like */ /* remote operations with dummy callref. */ /***********************************************/ static int l3dss1_cmd_global(struct PStack *st, isdn_ctrl *ic) -{ u8 id; - u8 temp[265]; - u8 *p = temp; +{ u_char id; + u_char temp[265]; + u_char *p = temp; int i, l, proc_len; struct sk_buff *skb; struct l3_process *pc = NULL; @@ -2279,9 +2271,9 @@ } /* l3dss1_io_timer */ static void -l3dss1_release_ind(struct l3_process *pc, u8 pr, void *arg) +l3dss1_release_ind(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; struct sk_buff *skb = arg; int callState = 0; p = skb->data; @@ -2295,31 +2287,31 @@ /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1 * set down layer 3 without sending any message */ - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); dss1_release_l3_process(pc); } else { - L3L4(pc->st, CC_IGNORE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc); } } static void -l3dss1_dummy(struct l3_process *pc, u8 pr, void *arg) +l3dss1_dummy(struct l3_process *pc, u_char pr, void *arg) { } static void -l3dss1_t302(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t302(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 28; /* invalid number */ l3dss1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3dss1_t303(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t303(struct l3_process *pc, u_char pr, void *arg) { if (pc->N303 > 0) { pc->N303--; @@ -2328,30 +2320,30 @@ } else { L3DelTimer(&pc->timer); l3dss1_message_cause(pc, MT_RELEASE_COMPLETE, 102); - L3L4(pc->st, CC_NOSETUP_RSP, pc); + pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc); dss1_release_l3_process(pc); } } static void -l3dss1_t304(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t304(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3dss1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3dss1_t305(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t305(struct l3_process *pc, u_char pr, void *arg) { - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; struct sk_buff *skb; - u8 cause = 16; + u_char cause = 16; L3DelTimer(&pc->timer); if (pc->para.cause != NO_CAUSE) @@ -2374,27 +2366,27 @@ } static void -l3dss1_t310(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t310(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3dss1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3dss1_t313(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t313(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3dss1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_CONNECT_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc); } static void -l3dss1_t308_1(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t308_1(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 19); L3DelTimer(&pc->timer); @@ -2403,50 +2395,50 @@ } static void -l3dss1_t308_2(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t308_2(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RELEASE_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc); dss1_release_l3_process(pc); } static void -l3dss1_t318(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t318(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.cause = 102; /* Timer expiry */ pc->para.loc = 0; /* local */ - L3L4(pc->st, CC_RESUME_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc); newl3state(pc, 19); l3dss1_message(pc, MT_RELEASE); L3AddTimer(&pc->timer, T308, CC_T308_1); } static void -l3dss1_t319(struct l3_process *pc, u8 pr, void *arg) +l3dss1_t319(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.cause = 102; /* Timer expiry */ pc->para.loc = 0; /* local */ - L3L4(pc->st, CC_SUSPEND_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc); newl3state(pc, 10); } static void -l3dss1_restart(struct l3_process *pc, u8 pr, void *arg) +l3dss1_restart(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); dss1_release_l3_process(pc); } static void -l3dss1_status(struct l3_process *pc, u8 pr, void *arg) +l3dss1_status(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; struct sk_buff *skb = arg; int ret; - u8 cause = 0, callState = 0; + u_char cause = 0, callState = 0; if ((ret = l3dss1_get_cause(pc, skb))) { if (pc->debug & L3_DEB_WARN) @@ -2474,7 +2466,7 @@ cause = 99; } if (cause) { - u8 tmp; + u_char tmp; if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "STATUS error(%d/%d)",ret,cause); @@ -2492,14 +2484,14 @@ * if received MT_STATUS with cause == 111 and call * state == 0, then we must set down layer 3 */ - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); dss1_release_l3_process(pc); } } static void -l3dss1_facility(struct l3_process *pc, u8 pr, void *arg) +l3dss1_facility(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -2507,20 +2499,20 @@ ret = check_infoelements(pc, skb, ie_FACILITY); l3dss1_std_ie_err(pc, ret); { - u8 *p; + u_char *p; if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) l3dss1_parse_facility(pc->st, pc, pc->callref, p); } } static void -l3dss1_suspend_req(struct l3_process *pc, u8 pr, void *arg) +l3dss1_suspend_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[32]; - u8 *p = tmp; - u8 i, l; - u8 *msg = pc->chan->setup.phone; + u_char tmp[32]; + u_char *p = tmp; + u_char i, l; + u_char *msg = pc->chan->setup.phone; MsgHead(p, pc->callref, MT_SUSPEND); l = *msg++; @@ -2543,7 +2535,7 @@ } static void -l3dss1_suspend_ack(struct l3_process *pc, u8 pr, void *arg) +l3dss1_suspend_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -2551,7 +2543,7 @@ L3DelTimer(&pc->timer); newl3state(pc, 0); pc->para.cause = NO_CAUSE; - L3L4(pc->st, CC_SUSPEND | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc); /* We don't handle suspend_ack for IE errors now */ if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE))) if (pc->debug & L3_DEB_WARN) @@ -2560,7 +2552,7 @@ } static void -l3dss1_suspend_rej(struct l3_process *pc, u8 pr, void *arg) +l3dss1_suspend_rej(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -2581,20 +2573,20 @@ return; } L3DelTimer(&pc->timer); - L3L4(pc->st, CC_SUSPEND_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc); newl3state(pc, 10); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3dss1_std_ie_err(pc, ret); } static void -l3dss1_resume_req(struct l3_process *pc, u8 pr, void *arg) +l3dss1_resume_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[32]; - u8 *p = tmp; - u8 i, l; - u8 *msg = pc->para.setup.phone; + u_char tmp[32]; + u_char *p = tmp; + u_char i, l; + u_char *msg = pc->para.setup.phone; MsgHead(p, pc->callref, MT_RESUME); @@ -2618,7 +2610,7 @@ } static void -l3dss1_resume_ack(struct l3_process *pc, u8 pr, void *arg) +l3dss1_resume_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int id, ret; @@ -2645,14 +2637,14 @@ return; } L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RESUME | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc); newl3state(pc, 10); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3dss1_std_ie_err(pc, ret); } static void -l3dss1_resume_rej(struct l3_process *pc, u8 pr, void *arg) +l3dss1_resume_rej(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -2673,7 +2665,7 @@ return; } L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RESUME_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc); newl3state(pc, 0); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3dss1_std_ie_err(pc, ret); @@ -2681,11 +2673,11 @@ } static void -l3dss1_global_restart(struct l3_process *pc, u8 pr, void *arg) +l3dss1_global_restart(struct l3_process *pc, u_char pr, void *arg) { - u8 tmp[32]; - u8 *p; - u8 ri, ch = 0, chan = 0; + u_char tmp[32]; + u_char *p; + u_char ri, ch = 0, chan = 0; int l; struct sk_buff *skb = arg; struct l3_process *up; @@ -2711,9 +2703,9 @@ up = pc->st->l3.proc; while (up) { if ((ri & 7) == 7) - L4L3(up->st, CC_RESTART | REQUEST, up); + up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up); else if (up->para.bchannel == chan) - L4L3(up->st, CC_RESTART | REQUEST, up); + up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up); up = up->next; } p = tmp; @@ -2735,26 +2727,26 @@ } static void -l3dss1_dl_reset(struct l3_process *pc, u8 pr, void *arg) +l3dss1_dl_reset(struct l3_process *pc, u_char pr, void *arg) { pc->para.cause = 0x29; /* Temporary failure */ pc->para.loc = 0; l3dss1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3dss1_dl_release(struct l3_process *pc, u8 pr, void *arg) +l3dss1_dl_release(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 0); pc->para.cause = 0x1b; /* Destination out of order */ pc->para.loc = 0; - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); release_l3_process(pc); } static void -l3dss1_dl_reestablish(struct l3_process *pc, u8 pr, void *arg) +l3dss1_dl_reestablish(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T309, CC_T309); @@ -2762,7 +2754,7 @@ } static void -l3dss1_dl_reest_status(struct l3_process *pc, u8 pr, void *arg) +l3dss1_dl_reest_status(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); @@ -2920,10 +2912,10 @@ static void global_handler(struct PStack *st, int mt, struct sk_buff *skb) { - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; - u_int i; + int i; struct l3_process *proc = st->l3.global; proc->callref = skb->data[2]; /* cr flag */ @@ -2961,10 +2953,9 @@ static void dss1up(struct PStack *st, int pr, void *arg) { - u_int i; - int mt, cr, cause, callState; + int i, mt, cr, cause, callState; char *ptr; - u8 *p; + u_char *p; struct sk_buff *skb = arg; struct l3_process *proc; @@ -2999,7 +2990,7 @@ return; } cr = getcallref(skb->data); - if (skb->len < (u_int)((skb->data[1] & 0x0f) + 3)) { + if (skb->len < ((skb->data[1] & 0x0f) + 3)) { l3_debug(st, "dss1up frame too short(%d)", skb->len); dev_kfree_skb(skb); return; @@ -3136,8 +3127,7 @@ static void dss1down(struct PStack *st, int pr, void *arg) { - u_int i; - int cr; + int i, cr; struct l3_process *proc; struct Channel *chan; @@ -3188,29 +3178,29 @@ static void dss1man(struct PStack *st, int pr, void *arg) { - u_int i; - struct l3_process *proc = arg; - - if (!proc) { - printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr); - return; - } - for (i = 0; i < MANSLLEN; i++) + int i; + struct l3_process *proc = arg; + + if (!proc) { + printk(KERN_ERR "HiSax dss1man without proc pr=%04x\n", pr); + return; + } + for (i = 0; i < MANSLLEN; i++) if ((pr == manstatelist[i].primitive) && - ((1 << proc->state) & manstatelist[i].state)) - break; - if (i == MANSLLEN) { - if (st->l3.debug & L3_DEB_STATE) { - l3_debug(st, "cr %d dss1man state %d prim %#x unhandled", - proc->callref & 0x7f, proc->state, pr); - } - } else { - if (st->l3.debug & L3_DEB_STATE) { - l3_debug(st, "cr %d dss1man state %d prim %#x", - proc->callref & 0x7f, proc->state, pr); - } - manstatelist[i].rout(proc, pr, arg); - } + ((1 << proc->state) & manstatelist[i].state)) + break; + if (i == MANSLLEN) { + if (st->l3.debug & L3_DEB_STATE) { + l3_debug(st, "cr %d dss1man state %d prim %#x unhandled", + proc->callref & 0x7f, proc->state, pr); + } + } else { + if (st->l3.debug & L3_DEB_STATE) { + l3_debug(st, "cr %d dss1man state %d prim %#x", + proc->callref & 0x7f, proc->state, pr); + } + manstatelist[i].rout(proc, pr, arg); + } } void @@ -3219,9 +3209,9 @@ char tmp[64]; int i; - st->l3.l4l3 = dss1down; - st->l3.l4l3_proto = l3dss1_cmd_global; - st->l3.l2l3 = dss1up; + st->lli.l4l3 = dss1down; + st->lli.l4l3_proto = l3dss1_cmd_global; + st->l2.l2l3 = dss1up; st->l3.l3ml3 = dss1man; st->l3.N303 = 1; st->prot.dss1.last_invoke_id = 0; diff -Nru a/drivers/isdn/hisax/l3ni1.c b/drivers/isdn/hisax/l3ni1.c --- a/drivers/isdn/hisax/l3ni1.c Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/l3ni1.c Thu Feb 19 23:44:23 2004 @@ -1,4 +1,4 @@ -/* $Id: l3ni1.c,v 2.5.6.3 2001/09/23 22:24:50 kai Exp $ +/* $Id: l3ni1.c,v 2.8.2.3 2004/01/13 14:31:25 keil Exp $ * * NI1 D-channel protocol * @@ -24,8 +24,7 @@ #include extern char *HiSax_getrev(const char *revision); -const char *ni1_revision = "$Revision: 2.5.6.3 $"; -static spinlock_t l3ni1_lock = SPIN_LOCK_UNLOCKED; +const char *ni1_revision = "$Revision: 2.8.2.3 $"; #define EXT_BEARER_CAPS 1 @@ -47,13 +46,10 @@ static unsigned char new_invoke_id(struct PStack *p) { unsigned char retval; - unsigned long flags; int i; i = 32; /* maximum search depth */ - spin_lock_irqsave(&l3ni1_lock, flags); - retval = p->prot.ni1.last_invoke_id + 1; /* try new id */ while ((i) && (p->prot.ni1.invoke_used[retval >> 3] == 0xFF)) { p->prot.ni1.last_invoke_id = (retval & 0xF8) + 8; @@ -66,8 +62,6 @@ retval = 0; p->prot.ni1.last_invoke_id = retval; p->prot.ni1.invoke_used[retval >> 3] |= (1 << (retval & 7)); - spin_unlock_irqrestore(&l3ni1_lock, flags); - return(retval); } /* new_invoke_id */ @@ -75,13 +69,11 @@ /* free a used invoke id */ /*************************/ static void free_invoke_id(struct PStack *p, unsigned char id) -{ unsigned long flags; +{ if (!id) return; /* 0 = invalid value */ - spin_lock_irqsave(&l3ni1_lock, flags); p->prot.ni1.invoke_used[id >> 3] &= ~(1 << (id & 7)); - spin_unlock_irqrestore(&l3ni1_lock, flags); } /* free_invoke_id */ @@ -134,7 +126,7 @@ /* and a return result is delivered. id specifies the invoke id. */ /*******************************************************************/ static void -l3ni1_dummy_return_result(struct PStack *st, int id, u8 *p, u8 nlen) +l3ni1_dummy_return_result(struct PStack *st, int id, u_char *p, u_char nlen) { isdn_ctrl ic; struct IsdnCardState *cs; struct l3_process *pc = NULL; @@ -201,7 +193,7 @@ /*******************************************************************/ static void l3ni1_dummy_invoke(struct PStack *st, int cr, int id, - int ident, u8 *p, u8 nlen) + int ident, u_char *p, u_char nlen) { isdn_ctrl ic; struct IsdnCardState *cs; @@ -225,7 +217,7 @@ static void l3ni1_parse_facility(struct PStack *st, struct l3_process *pc, - int cr, u8 * p) + int cr, u_char * p) { int qd_len = 0; unsigned char nlen = 0, ilen, cp_tag; @@ -375,7 +367,7 @@ pc->prot.ni1.remote_result = 0; /* success */ pc->prot.ni1.invoke_id = 0; pc->redir_result = pc->prot.ni1.remote_result; - L3L4(st, CC_REDIR | INDICATION, pc); } /* Diversion successful */ + st->l3.l3l4(st, CC_REDIR | INDICATION, pc); } /* Diversion successful */ else l3_debug(st,"return error unknown identifier"); break; @@ -420,7 +412,7 @@ pc->prot.ni1.remote_result = err_ret; /* result */ pc->prot.ni1.invoke_id = 0; pc->redir_result = pc->prot.ni1.remote_result; - L3L4(st, CC_REDIR | INDICATION, pc); + st->l3.l3l4(st, CC_REDIR | INDICATION, pc); } /* Deflection error */ else l3_debug(st,"return result unknown identifier"); @@ -432,10 +424,10 @@ } static void -l3ni1_message(struct l3_process *pc, u8 mt) +l3ni1_message(struct l3_process *pc, u_char mt) { struct sk_buff *skb; - u8 *p; + u_char *p; if (!(skb = l3_alloc_skb(4))) return; @@ -445,15 +437,15 @@ } static void -l3ni1_message_plus_chid(struct l3_process *pc, u8 mt) +l3ni1_message_plus_chid(struct l3_process *pc, u_char mt) /* sends an l3 messages plus channel id - added GE 05/09/00 */ { struct sk_buff *skb; - u8 tmp[16]; - u8 *p = tmp; - u8 chid; + u_char tmp[16]; + u_char *p = tmp; + u_char chid; - chid = (u8)(pc->para.bchannel & 0x03) | 0x88; + chid = (u_char)(pc->para.bchannel & 0x03) | 0x88; MsgHead(p, pc->callref, mt); *p++ = IE_CHANNEL_ID; *p++ = 0x01; @@ -466,11 +458,11 @@ } static void -l3ni1_message_cause(struct l3_process *pc, u8 mt, u8 cause) +l3ni1_message_cause(struct l3_process *pc, u_char mt, u_char cause) { struct sk_buff *skb; - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; MsgHead(p, pc->callref, mt); @@ -487,10 +479,10 @@ } static void -l3ni1_status_send(struct l3_process *pc, u8 pr, void *arg) +l3ni1_status_send(struct l3_process *pc, u_char pr, void *arg) { - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; struct sk_buff *skb; @@ -513,14 +505,14 @@ } static void -l3ni1_msg_without_setup(struct l3_process *pc, u8 pr, void *arg) +l3ni1_msg_without_setup(struct l3_process *pc, u_char pr, void *arg) { /* This routine is called if here was no SETUP made (checks in ni1up and in * l3ni1_setup) and a RELEASE_COMPLETE have to be sent with an error code * MT_STATUS_ENQUIRE in the NULL state is handled too */ - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; struct sk_buff *skb; @@ -639,7 +631,7 @@ }; static int -getmax_ie_len(u8 ie) { +getmax_ie_len(u_char ie) { int i = 0; while (max_ie_len[i].ie != -1) { if (max_ie_len[i].ie == ie) @@ -650,7 +642,7 @@ } static int -ie_in_set(struct l3_process *pc, u8 ie, int *checklist) { +ie_in_set(struct l3_process *pc, u_char ie, int *checklist) { int ret = 1; while (*checklist != -1) { @@ -670,13 +662,13 @@ check_infoelements(struct l3_process *pc, struct sk_buff *skb, int *checklist) { int *cl = checklist; - u8 mt; - u8 *p, ie; + u_char mt; + u_char *p, ie; int l, newpos, oldpos; int err_seq = 0, err_len = 0, err_compr = 0, err_ureg = 0; - u8 codeset = 0; - u8 old_codeset = 0; - u8 codelock = 1; + u_char codeset = 0; + u_char old_codeset = 0; + u_char codelock = 1; p = skb->data; /* skip cr */ @@ -685,7 +677,7 @@ p += l; mt = *p++; oldpos = 0; - while ((u_int)(p - skb->data) < skb->len) { + while ((p - skb->data) < skb->len) { if ((*p & 0xf0) == 0x90) { /* shift codeset */ old_codeset = codeset; codeset = *p & 7; @@ -819,7 +811,7 @@ static int l3ni1_get_channel_id(struct l3_process *pc, struct sk_buff *skb) { - u8 *p; + u_char *p; p = skb->data; if ((p = findie(p, skb->len, IE_CHANNEL_ID, 0))) { @@ -842,8 +834,8 @@ static int l3ni1_get_cause(struct l3_process *pc, struct sk_buff *skb) { - u8 l, i=0; - u8 *p; + u_char l, i=0; + u_char *p; p = skb->data; pc->para.cause = 31; @@ -880,11 +872,11 @@ } static void -l3ni1_msg_with_uus(struct l3_process *pc, u8 cmd) +l3ni1_msg_with_uus(struct l3_process *pc, u_char cmd) { struct sk_buff *skb; - u8 tmp[16+40]; - u8 *p = tmp; + u_char tmp[16+40]; + u_char *p = tmp; int l; MsgHead(p, pc->callref, cmd); @@ -906,7 +898,7 @@ } /* l3ni1_msg_with_uus */ static void -l3ni1_release_req(struct l3_process *pc, u8 pr, void *arg) +l3ni1_release_req(struct l3_process *pc, u_char pr, void *arg) { StopAllL3Timer(pc); newl3state(pc, 19); @@ -918,7 +910,7 @@ } static void -l3ni1_release_cmpl(struct l3_process *pc, u8 pr, void *arg) +l3ni1_release_cmpl(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -930,14 +922,14 @@ pc->para.cause = NO_CAUSE; StopAllL3Timer(pc); newl3state(pc, 0); - L3L4(pc->st, CC_RELEASE | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | CONFIRM, pc); ni1_release_l3_process(pc); } #if EXT_BEARER_CAPS -static u8 * -EncodeASyncParams(u8 * p, u8 si2) +static u_char * +EncodeASyncParams(u_char * p, u_char si2) { // 7c 06 88 90 21 42 00 bb p[0] = 0; @@ -1001,8 +993,8 @@ return p + 3; } -static u8 -EncodeSyncParams(u8 si2, u8 ai) +static u_char +EncodeSyncParams(u_char si2, u_char ai) { switch (si2) { @@ -1046,10 +1038,10 @@ } -static u8 -DecodeASyncParams(u8 si2, u8 * p) +static u_char +DecodeASyncParams(u_char si2, u_char * p) { - u8 info; + u_char info; switch (p[5]) { case 66: // 1200 bit/s @@ -1103,8 +1095,8 @@ } -static u8 -DecodeSyncParams(u8 si2, u8 info) +static u_char +DecodeSyncParams(u_char si2, u_char info) { info &= 0x7f; switch (info) { @@ -1144,10 +1136,10 @@ } } -static u8 +static u_char DecodeSI2(struct sk_buff *skb) { - u8 *p; //, *pend=skb->data + skb->len; + u_char *p; //, *pend=skb->data + skb->len; if ((p = findie(skb->data, skb->len, 0x7c, 0))) { switch (p[4] & 0x0f) { @@ -1174,16 +1166,16 @@ static void -l3ni1_setup_req(struct l3_process *pc, u8 pr, +l3ni1_setup_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[128]; - u8 *p = tmp; + u_char tmp[128]; + u_char *p = tmp; - u8 *teln; - u8 *sub; - u8 *sp; + u_char *teln; + u_char *sub; + u_char *sp; int l; MsgHead(p, pc->callref, MT_SETUP); @@ -1289,7 +1281,7 @@ } static void -l3ni1_call_proc(struct l3_process *pc, u8 pr, void *arg) +l3ni1_call_proc(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int id, ret; @@ -1324,11 +1316,11 @@ L3AddTimer(&pc->timer, T310, CC_T310); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, ret); - L3L4(pc->st, CC_PROCEEDING | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_PROCEEDING | INDICATION, pc); } static void -l3ni1_setup_ack(struct l3_process *pc, u8 pr, void *arg) +l3ni1_setup_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int id, ret; @@ -1363,16 +1355,16 @@ L3AddTimer(&pc->timer, T304, CC_T304); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, ret); - L3L4(pc->st, CC_MORE_INFO | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); } static void -l3ni1_disconnect(struct l3_process *pc, u8 pr, void *arg) +l3ni1_disconnect(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - u8 *p; + u_char *p; int ret; - u8 cause = 0; + u_char cause = 0; StopAllL3Timer(pc); if ((ret = l3ni1_get_cause(pc, skb))) { @@ -1395,7 +1387,7 @@ if (cause) newl3state(pc, 19); if (11 != ret) - L3L4(pc->st, CC_DISCONNECT | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_DISCONNECT | INDICATION, pc); else if (!cause) l3ni1_release_req(pc, pr, NULL); if (cause) { @@ -1405,7 +1397,7 @@ } static void -l3ni1_connect(struct l3_process *pc, u8 pr, void *arg) +l3ni1_connect(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -1421,11 +1413,11 @@ /* here should inserted COLP handling KKe */ if (ret) l3ni1_std_ie_err(pc, ret); - L3L4(pc->st, CC_SETUP | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP | CONFIRM, pc); } static void -l3ni1_alerting(struct l3_process *pc, u8 pr, void *arg) +l3ni1_alerting(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -1439,13 +1431,13 @@ newl3state(pc, 4); if (ret) l3ni1_std_ie_err(pc, ret); - L3L4(pc->st, CC_ALERTING | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_ALERTING | INDICATION, pc); } static void -l3ni1_setup(struct l3_process *pc, u8 pr, void *arg) +l3ni1_setup(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; int bcfound = 0; char tmp[80]; struct sk_buff *skb = arg; @@ -1456,7 +1448,7 @@ * Bearer Capabilities */ p = skb->data; - /* only the first occurrence 'll be detected ! */ + /* only the first occurence 'll be detected ! */ if ((p = findie(p, skb->len, 0x04, 0))) { if ((p[1] < 2) || (p[1] > 11)) err = 1; @@ -1605,23 +1597,23 @@ newl3state(pc, 6); if (err) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, err); - L3L4(pc->st, CC_SETUP | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP | INDICATION, pc); } static void -l3ni1_reset(struct l3_process *pc, u8 pr, void *arg) +l3ni1_reset(struct l3_process *pc, u_char pr, void *arg) { ni1_release_l3_process(pc); } static void -l3ni1_disconnect_req(struct l3_process *pc, u8 pr, void *arg) +l3ni1_disconnect_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[16+40]; - u8 *p = tmp; + u_char tmp[16+40]; + u_char *p = tmp; int l; - u8 cause = 16; + u_char cause = 16; if (pc->para.cause != NO_CAUSE) cause = pc->para.cause; @@ -1654,7 +1646,7 @@ } static void -l3ni1_setup_rsp(struct l3_process *pc, u8 pr, +l3ni1_setup_rsp(struct l3_process *pc, u_char pr, void *arg) { if (!pc->para.bchannel) @@ -1672,7 +1664,7 @@ } static void -l3ni1_connect_ack(struct l3_process *pc, u8 pr, void *arg) +l3ni1_connect_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -1686,17 +1678,17 @@ L3DelTimer(&pc->timer); if (ret) l3ni1_std_ie_err(pc, ret); - L3L4(pc->st, CC_SETUP_COMPL | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_COMPL | INDICATION, pc); } static void -l3ni1_reject_req(struct l3_process *pc, u8 pr, void *arg) +l3ni1_reject_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; - u8 cause = 21; + u_char cause = 21; if (pc->para.cause != NO_CAUSE) cause = pc->para.cause; @@ -1713,16 +1705,16 @@ return; memcpy(skb_put(skb, l), tmp, l); l3_msg(pc->st, DL_DATA | REQUEST, skb); - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); ni1_release_l3_process(pc); } static void -l3ni1_release(struct l3_process *pc, u8 pr, void *arg) +l3ni1_release(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; - u8 *p; + u_char *p; int ret, cause=0; StopAllL3Timer(pc); @@ -1747,13 +1739,13 @@ l3ni1_message_cause(pc, MT_RELEASE_COMPLETE, cause); else l3ni1_message(pc, MT_RELEASE_COMPLETE); - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); ni1_release_l3_process(pc); } static void -l3ni1_alert_req(struct l3_process *pc, u8 pr, +l3ni1_alert_req(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 7); @@ -1764,16 +1756,16 @@ } static void -l3ni1_proceed_req(struct l3_process *pc, u8 pr, +l3ni1_proceed_req(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 9); l3ni1_message(pc, MT_CALL_PROCEEDING); - L3L4(pc->st, CC_PROCEED_SEND | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_PROCEED_SEND | INDICATION, pc); } static void -l3ni1_setup_ack_req(struct l3_process *pc, u8 pr, +l3ni1_setup_ack_req(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 25); @@ -1786,8 +1778,8 @@ /* deliver a incoming display message to HL */ /********************************************/ static void -l3ni1_deliver_display(struct l3_process *pc, int pr, u8 *infp) -{ u8 len; +l3ni1_deliver_display(struct l3_process *pc, int pr, u_char *infp) +{ u_char len; isdn_ctrl ic; struct IsdnCardState *cs; char *p; @@ -1809,11 +1801,11 @@ static void -l3ni1_progress(struct l3_process *pc, u8 pr, void *arg) +l3ni1_progress(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int err = 0; - u8 *p; + u_char *p; if ((p = findie(skb->data, skb->len, IE_PROGRESS, 0))) { if (p[1] != 2) { @@ -1862,15 +1854,15 @@ if (err) l3ni1_std_ie_err(pc, err); if (ERR_IE_COMPREHENSION != err) - L3L4(pc->st, CC_PROGRESS | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_PROGRESS | INDICATION, pc); } static void -l3ni1_notify(struct l3_process *pc, u8 pr, void *arg) +l3ni1_notify(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int err = 0; - u8 *p; + u_char *p; if ((p = findie(skb->data, skb->len, IE_NOTIFY, 0))) { if (p[1] != 1) { @@ -1903,11 +1895,11 @@ if (err) l3ni1_std_ie_err(pc, err); if (ERR_IE_COMPREHENSION != err) - L3L4(pc->st, CC_NOTIFY | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_NOTIFY | INDICATION, pc); } static void -l3ni1_status_enq(struct l3_process *pc, u8 pr, void *arg) +l3ni1_status_enq(struct l3_process *pc, u_char pr, void *arg) { int ret; struct sk_buff *skb = arg; @@ -1919,11 +1911,11 @@ } static void -l3ni1_information(struct l3_process *pc, u8 pr, void *arg) +l3ni1_information(struct l3_process *pc, u_char pr, void *arg) { int ret; struct sk_buff *skb = arg; - u8 *p; + u_char *p; char tmp[32]; ret = check_infoelements(pc, skb, ie_INFORMATION); @@ -1935,7 +1927,7 @@ if ((p = findie(p, skb->len, 0x70, 0))) { iecpy(tmp, p, 1); strcat(pc->para.setup.eazmsn, tmp); - L3L4(pc->st, CC_MORE_INFO | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_MORE_INFO | INDICATION, pc); } L3AddTimer(&pc->timer, T302, CC_T302); } @@ -1944,14 +1936,14 @@ /******************************/ /* handle deflection requests */ /******************************/ -static void l3ni1_redir_req(struct l3_process *pc, u8 pr, void *arg) +static void l3ni1_redir_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[128]; - u8 *p = tmp; - u8 *subp; - u8 len_phone = 0; - u8 len_sub = 0; + u_char tmp[128]; + u_char *p = tmp; + u_char *subp; + u_char len_phone = 0; + u_char len_sub = 0; int l; @@ -2016,7 +2008,7 @@ /********************************************/ /* handle deflection request in early state */ /********************************************/ -static void l3ni1_redir_req_early(struct l3_process *pc, u8 pr, void *arg) +static void l3ni1_redir_req_early(struct l3_process *pc, u_char pr, void *arg) { l3ni1_proceed_req(pc,pr,arg); l3ni1_redir_req(pc,pr,arg); @@ -2024,13 +2016,13 @@ /***********************************************/ /* handle special commands for this protocol. */ -/* Examples are call independent services like */ +/* Examples are call independant services like */ /* remote operations with dummy callref. */ /***********************************************/ static int l3ni1_cmd_global(struct PStack *st, isdn_ctrl *ic) -{ u8 id; - u8 temp[265]; - u8 *p = temp; +{ u_char id; + u_char temp[265]; + u_char *p = temp; int i, l, proc_len; struct sk_buff *skb; struct l3_process *pc = NULL; @@ -2134,9 +2126,9 @@ } /* l3ni1_io_timer */ static void -l3ni1_release_ind(struct l3_process *pc, u8 pr, void *arg) +l3ni1_release_ind(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; struct sk_buff *skb = arg; int callState = 0; p = skb->data; @@ -2150,31 +2142,31 @@ /* ETS 300-104 7.6.1, 8.6.1, 10.6.1... and 16.1 * set down layer 3 without sending any message */ - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); ni1_release_l3_process(pc); } else { - L3L4(pc->st, CC_IGNORE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_IGNORE | INDICATION, pc); } } static void -l3ni1_dummy(struct l3_process *pc, u8 pr, void *arg) +l3ni1_dummy(struct l3_process *pc, u_char pr, void *arg) { } static void -l3ni1_t302(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t302(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 28; /* invalid number */ l3ni1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3ni1_t303(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t303(struct l3_process *pc, u_char pr, void *arg) { if (pc->N303 > 0) { pc->N303--; @@ -2183,30 +2175,30 @@ } else { L3DelTimer(&pc->timer); l3ni1_message_cause(pc, MT_RELEASE_COMPLETE, 102); - L3L4(pc->st, CC_NOSETUP_RSP, pc); + pc->st->l3.l3l4(pc->st, CC_NOSETUP_RSP, pc); ni1_release_l3_process(pc); } } static void -l3ni1_t304(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t304(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3ni1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3ni1_t305(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t305(struct l3_process *pc, u_char pr, void *arg) { - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; struct sk_buff *skb; - u8 cause = 16; + u_char cause = 16; L3DelTimer(&pc->timer); if (pc->para.cause != NO_CAUSE) @@ -2229,27 +2221,27 @@ } static void -l3ni1_t310(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t310(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3ni1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3ni1_t313(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t313(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.loc = 0; pc->para.cause = 102; l3ni1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_CONNECT_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_CONNECT_ERR, pc); } static void -l3ni1_t308_1(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t308_1(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 19); L3DelTimer(&pc->timer); @@ -2258,50 +2250,50 @@ } static void -l3ni1_t308_2(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t308_2(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RELEASE_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE_ERR, pc); ni1_release_l3_process(pc); } static void -l3ni1_t318(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t318(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.cause = 102; /* Timer expiry */ pc->para.loc = 0; /* local */ - L3L4(pc->st, CC_RESUME_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc); newl3state(pc, 19); l3ni1_message(pc, MT_RELEASE); L3AddTimer(&pc->timer, T308, CC_T308_1); } static void -l3ni1_t319(struct l3_process *pc, u8 pr, void *arg) +l3ni1_t319(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); pc->para.cause = 102; /* Timer expiry */ pc->para.loc = 0; /* local */ - L3L4(pc->st, CC_SUSPEND_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc); newl3state(pc, 10); } static void -l3ni1_restart(struct l3_process *pc, u8 pr, void *arg) +l3ni1_restart(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); ni1_release_l3_process(pc); } static void -l3ni1_status(struct l3_process *pc, u8 pr, void *arg) +l3ni1_status(struct l3_process *pc, u_char pr, void *arg) { - u8 *p; + u_char *p; struct sk_buff *skb = arg; int ret; - u8 cause = 0, callState = 0; + u_char cause = 0, callState = 0; if ((ret = l3ni1_get_cause(pc, skb))) { if (pc->debug & L3_DEB_WARN) @@ -2329,7 +2321,7 @@ cause = 99; } if (cause) { - u8 tmp; + u_char tmp; if (pc->debug & L3_DEB_WARN) l3_debug(pc->st, "STATUS error(%d/%d)",ret,cause); @@ -2347,14 +2339,14 @@ * if received MT_STATUS with cause == 111 and call * state == 0, then we must set down layer 3 */ - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); newl3state(pc, 0); ni1_release_l3_process(pc); } } static void -l3ni1_facility(struct l3_process *pc, u8 pr, void *arg) +l3ni1_facility(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -2362,20 +2354,20 @@ ret = check_infoelements(pc, skb, ie_FACILITY); l3ni1_std_ie_err(pc, ret); { - u8 *p; + u_char *p; if ((p = findie(skb->data, skb->len, IE_FACILITY, 0))) l3ni1_parse_facility(pc->st, pc, pc->callref, p); } } static void -l3ni1_suspend_req(struct l3_process *pc, u8 pr, void *arg) +l3ni1_suspend_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[32]; - u8 *p = tmp; - u8 i, l; - u8 *msg = pc->chan->setup.phone; + u_char tmp[32]; + u_char *p = tmp; + u_char i, l; + u_char *msg = pc->chan->setup.phone; MsgHead(p, pc->callref, MT_SUSPEND); l = *msg++; @@ -2398,7 +2390,7 @@ } static void -l3ni1_suspend_ack(struct l3_process *pc, u8 pr, void *arg) +l3ni1_suspend_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -2406,7 +2398,7 @@ L3DelTimer(&pc->timer); newl3state(pc, 0); pc->para.cause = NO_CAUSE; - L3L4(pc->st, CC_SUSPEND | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_SUSPEND | CONFIRM, pc); /* We don't handle suspend_ack for IE errors now */ if ((ret = check_infoelements(pc, skb, ie_SUSPEND_ACKNOWLEDGE))) if (pc->debug & L3_DEB_WARN) @@ -2415,7 +2407,7 @@ } static void -l3ni1_suspend_rej(struct l3_process *pc, u8 pr, void *arg) +l3ni1_suspend_rej(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -2436,20 +2428,20 @@ return; } L3DelTimer(&pc->timer); - L3L4(pc->st, CC_SUSPEND_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SUSPEND_ERR, pc); newl3state(pc, 10); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, ret); } static void -l3ni1_resume_req(struct l3_process *pc, u8 pr, void *arg) +l3ni1_resume_req(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb; - u8 tmp[32]; - u8 *p = tmp; - u8 i, l; - u8 *msg = pc->para.setup.phone; + u_char tmp[32]; + u_char *p = tmp; + u_char i, l; + u_char *msg = pc->para.setup.phone; MsgHead(p, pc->callref, MT_RESUME); @@ -2473,7 +2465,7 @@ } static void -l3ni1_resume_ack(struct l3_process *pc, u8 pr, void *arg) +l3ni1_resume_ack(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int id, ret; @@ -2500,14 +2492,14 @@ return; } L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RESUME | CONFIRM, pc); + pc->st->l3.l3l4(pc->st, CC_RESUME | CONFIRM, pc); newl3state(pc, 10); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, ret); } static void -l3ni1_resume_rej(struct l3_process *pc, u8 pr, void *arg) +l3ni1_resume_rej(struct l3_process *pc, u_char pr, void *arg) { struct sk_buff *skb = arg; int ret; @@ -2528,7 +2520,7 @@ return; } L3DelTimer(&pc->timer); - L3L4(pc->st, CC_RESUME_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_RESUME_ERR, pc); newl3state(pc, 0); if (ret) /* STATUS for none mandatory IE errors after actions are taken */ l3ni1_std_ie_err(pc, ret); @@ -2536,11 +2528,11 @@ } static void -l3ni1_global_restart(struct l3_process *pc, u8 pr, void *arg) +l3ni1_global_restart(struct l3_process *pc, u_char pr, void *arg) { - u8 tmp[32]; - u8 *p; - u8 ri, ch = 0, chan = 0; + u_char tmp[32]; + u_char *p; + u_char ri, ch = 0, chan = 0; int l; struct sk_buff *skb = arg; struct l3_process *up; @@ -2566,9 +2558,9 @@ up = pc->st->l3.proc; while (up) { if ((ri & 7) == 7) - L4L3(up->st, CC_RESTART | REQUEST, up); + up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up); else if (up->para.bchannel == chan) - L4L3(up->st, CC_RESTART | REQUEST, up); + up->st->lli.l4l3(up->st, CC_RESTART | REQUEST, up); up = up->next; } @@ -2591,26 +2583,26 @@ } static void -l3ni1_dl_reset(struct l3_process *pc, u8 pr, void *arg) +l3ni1_dl_reset(struct l3_process *pc, u_char pr, void *arg) { pc->para.cause = 0x29; /* Temporary failure */ pc->para.loc = 0; l3ni1_disconnect_req(pc, pr, NULL); - L3L4(pc->st, CC_SETUP_ERR, pc); + pc->st->l3.l3l4(pc->st, CC_SETUP_ERR, pc); } static void -l3ni1_dl_release(struct l3_process *pc, u8 pr, void *arg) +l3ni1_dl_release(struct l3_process *pc, u_char pr, void *arg) { newl3state(pc, 0); pc->para.cause = 0x1b; /* Destination out of order */ pc->para.loc = 0; - L3L4(pc->st, CC_RELEASE | INDICATION, pc); + pc->st->l3.l3l4(pc->st, CC_RELEASE | INDICATION, pc); release_l3_process(pc); } static void -l3ni1_dl_reestablish(struct l3_process *pc, u8 pr, void *arg) +l3ni1_dl_reestablish(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); L3AddTimer(&pc->timer, T309, CC_T309); @@ -2618,7 +2610,7 @@ } static void -l3ni1_dl_reest_status(struct l3_process *pc, u8 pr, void *arg) +l3ni1_dl_reest_status(struct l3_process *pc, u_char pr, void *arg) { L3DelTimer(&pc->timer); @@ -2626,9 +2618,9 @@ l3ni1_status_send(pc, 0, NULL); } -static void l3ni1_SendSpid( struct l3_process *pc, u8 pr, struct sk_buff *skb, int iNewState ) +static void l3ni1_SendSpid( struct l3_process *pc, u_char pr, struct sk_buff *skb, int iNewState ) { - u8 * p; + u_char * p; char * pSPID; struct Channel * pChan = pc->st->lli.userdata; int l; @@ -2640,7 +2632,7 @@ { printk( KERN_ERR "SPID not supplied in EAZMSN %s\n", pChan->setup.eazmsn ); newl3state( pc, 0 ); - L3L2( pc->st, DL_RELEASE | REQUEST, NULL ); + pc->st->l3.l3l2( pc->st, DL_RELEASE | REQUEST, NULL ); return; } @@ -2665,15 +2657,15 @@ L3DelTimer( &pc->timer ); L3AddTimer( &pc->timer, TSPID, CC_TSPID ); - L3L2( pc->st, DL_DATA | REQUEST, skb ); + pc->st->l3.l3l2( pc->st, DL_DATA | REQUEST, skb ); } -static void l3ni1_spid_send( struct l3_process *pc, u8 pr, void *arg ) +static void l3ni1_spid_send( struct l3_process *pc, u_char pr, void *arg ) { l3ni1_SendSpid( pc, pr, arg, 20 ); } -void l3ni1_spid_epid( struct l3_process *pc, u8 pr, void *arg ) +void l3ni1_spid_epid( struct l3_process *pc, u_char pr, void *arg ) { struct sk_buff *skb = arg; @@ -2687,7 +2679,7 @@ dev_kfree_skb( skb); } -static void l3ni1_spid_tout( struct l3_process *pc, u8 pr, void *arg ) +static void l3ni1_spid_tout( struct l3_process *pc, u_char pr, void *arg ) { if ( pc->state < 22 ) l3ni1_SendSpid( pc, pr, arg, pc->state+1 ); @@ -2698,7 +2690,7 @@ printk( KERN_ERR "SPID not accepted\n" ); newl3state( pc, 0 ); - L3L2( pc->st, DL_RELEASE | REQUEST, NULL ); + pc->st->l3.l3l2( pc->st, DL_RELEASE | REQUEST, NULL ); } } @@ -2856,10 +2848,10 @@ static void global_handler(struct PStack *st, int mt, struct sk_buff *skb) { - u8 tmp[16]; - u8 *p = tmp; + u_char tmp[16]; + u_char *p = tmp; int l; - u_int i; + int i; struct l3_process *proc = st->l3.global; if ( skb ) @@ -2900,10 +2892,9 @@ static void ni1up(struct PStack *st, int pr, void *arg) { - u_int i; - int mt, cr, cause, callState; + int i, mt, cr, cause, callState; char *ptr; - u8 *p; + u_char *p; struct sk_buff *skb = arg; struct l3_process *proc; @@ -2942,7 +2933,7 @@ return; } cr = getcallref(skb->data); - if (skb->len < (u_int)((skb->data[1] & 0x0f) + 3)) { + if (skb->len < ((skb->data[1] & 0x0f) + 3)) { l3_debug(st, "ni1up frame too short(%d)", skb->len); dev_kfree_skb(skb); return; @@ -3087,8 +3078,7 @@ static void ni1down(struct PStack *st, int pr, void *arg) { - u_int i; - int cr; + int i, cr; struct l3_process *proc; struct Channel *chan; @@ -3139,7 +3129,7 @@ static void ni1man(struct PStack *st, int pr, void *arg) { - u_int i; + int i; struct l3_process *proc = arg; if (!proc) { @@ -3170,9 +3160,9 @@ char tmp[64]; int i; - st->l3.l4l3 = ni1down; - st->l3.l4l3_proto = l3ni1_cmd_global; - st->l3.l2l3 = ni1up; + st->lli.l4l3 = ni1down; + st->lli.l4l3_proto = l3ni1_cmd_global; + st->l2.l2l3 = ni1up; st->l3.l3ml3 = ni1man; st->l3.N303 = 1; st->prot.ni1.last_invoke_id = 0; diff -Nru a/drivers/isdn/hisax/md5sums.asc b/drivers/isdn/hisax/md5sums.asc --- a/drivers/isdn/hisax/md5sums.asc Thu Feb 19 23:44:24 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,22 +0,0 @@ -# This are valid md5sums for certificated HiSax driver. -# The certification is valid only if the md5sums of all files match. -# The certification is valid only for ELSA Microlink PCI, -# Eicon Technology Diva 2.01 PCI, Sedlbauer SpeedFax+, -# HFC-S PCI A based cards and HFC-S USB based isdn tas -# in the moment. -# Read ../../../Documentation/isdn/HiSax.cert for more informations. -# -d08b59f56fb9ed1fbd17713342c75081 isac.c -e81e6e96f307e55f8b9777aca2b356d9 isdnl1.c -cfd2527d9fb01885484cba74bfc67121 isdnl2.c -8c6829f11459f9d044b5768803fb646d isdnl3.c -d40f88dff4191d2660240749cbdcb688 tei.c -3bd3bd05ee4cb25ffe046200b569a83a callc.c -d518f52402ebc3f1be84e09af375313c cert.c -c425de1f8be86e84006de63c9bb3cc5f l3dss1.c -4c411e29d4103ba60e9af4e3e1234a99 l3_1tr6.c -68c6cc2784f208e3247a5a555918d014 elsa.c -8d63a85d7222cf7b40e663e543191d8f diva.c -8c8cb4ce621fb84d8e337a696e75b0df sedlbauer.c -ebe5613d535748409407568435b2be97 hfc_pci.c -# end of md5sums diff -Nru a/drivers/isdn/hisax/mic.c b/drivers/isdn/hisax/mic.c --- a/drivers/isdn/hisax/mic.c Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/hisax/mic.c Thu Feb 19 23:44:27 2004 @@ -1,4 +1,4 @@ -/* $Id: mic.c,v 1.10.6.2 2001/09/23 22:24:50 kai Exp $ +/* $Id: mic.c,v 1.12.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for mic cards * @@ -18,8 +18,7 @@ extern const char *CardType[]; -const char *mic_revision = "$Revision: 1.10.6.2 $"; -static spinlock_t mic_lock = SPIN_LOCK_UNLOCKED; +const char *mic_revision = "$Revision: 1.12.2.4 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -31,146 +30,210 @@ /* CARD_ADR (Write) */ #define MIC_RESET 0x3 /* same as DOS driver */ -static inline u8 -readreg(struct IsdnCardState *cs, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&mic_lock, flags); - byteout(cs->hw.mic.adr, off); + byteout(ale, off); ret = bytein(adr); - spin_unlock_irqrestore(&mic_lock, flags); - return (ret); } static inline void -writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; - - spin_lock_irqsave(&mic_lock, flags); - byteout(cs->hw.mic.adr, off); - byteout(adr, data); - spin_unlock_irqrestore(&mic_lock, flags); + byteout(ale, off); + insb(adr, data, size); } + static inline void -readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { - byteout(cs->hw.mic.adr, off); - insb(adr, data, size); + byteout(ale, off); + byteout(adr, data); } static inline void -writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - byteout(cs->hw.mic.adr, off); + byteout(ale, off); outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) -{ - return readreg(cs, cs->hw.mic.isac, offset); -} +/* Interface functions */ -static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - writereg(cs, cs->hw.mic.isac, offset, value); + return (readreg(cs->hw.mic.adr, cs->hw.mic.isac, offset)); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - readfifo(cs, cs->hw.mic.isac, 0, data, size); + writereg(cs->hw.mic.adr, cs->hw.mic.isac, offset, value); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) -{ - writefifo(cs, cs->hw.mic.isac, 0, data, size); -} - -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - return readreg(cs, cs->hw.mic.hscx, offset + (hscx ? 0x40 : 0)); + readfifo(cs->hw.mic.adr, cs->hw.mic.isac, 0, data, size); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - writereg(cs, cs->hw.mic.hscx, offset + (hscx ? 0x40 : 0), value); + writefifo(cs->hw.mic.adr, cs->hw.mic.isac, 0, data, size); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - readfifo(cs, cs->hw.mic.hscx, hscx ? 0x40 : 0, data, size); + return (readreg(cs->hw.mic.adr, + cs->hw.mic.hscx, offset + (hscx ? 0x40 : 0))); } static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - writefifo(cs, cs->hw.mic.hscx, hscx ? 0x40 : 0, data, size); + writereg(cs->hw.mic.adr, + cs->hw.mic.hscx, offset + (hscx ? 0x40 : 0), value); } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static struct card_ops mic_ops = { - .init = inithscxisac, - .release = hisax_release_resources, - .irq_func = hscxisac_irq, -}; - -static int __init -mic_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->irq = card->para[0]; - cs->hw.mic.cfg_reg = card->para[1]; - cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR; - cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC; - cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX; - - if (!request_io(&cs->rs, cs->hw.mic.cfg_reg, 8, "mic isdn")) - goto err; - - printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n", - cs->hw.mic.cfg_reg, cs->irq); +/* + * fast interrupt HSCX stuff goes here + */ - cs->card_ops = &mic_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; +#define READHSCX(cs, nr, reg) readreg(cs->hw.mic.adr, \ + cs->hw.mic.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.mic.adr, \ + cs->hw.mic.hscx, reg + (nr ? 0x40 : 0), data) + +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.mic.adr, \ + cs->hw.mic.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.mic.adr, \ + cs->hw.mic.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" + +static irqreturn_t +mic_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + val = readreg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = readreg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_ISTA + 0x40); + if (val) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_ISTA); + if (val) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.mic.adr, cs->hw.mic.isac, ISAC_MASK, 0x0); + writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK, 0x0); + writereg(cs->hw.mic.adr, cs->hw.mic.hscx, HSCX_MASK + 0x40, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} + +void +release_io_mic(struct IsdnCardState *cs) +{ + int bytecnt = 8; + + if (cs->hw.mic.cfg_reg) + release_region(cs->hw.mic.cfg_reg, bytecnt); +} + +static int +mic_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + u_long flags; + + switch (mt) { + case CARD_RESET: + return(0); + case CARD_RELEASE: + release_io_mic(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithscx(cs); /* /RTSA := ISAC RST */ + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); } int __init setup_mic(struct IsdnCard *card) { + int bytecnt; + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, mic_revision); printk(KERN_INFO "HiSax: mic driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_MIC) + return (0); + + bytecnt = 8; + cs->hw.mic.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + cs->hw.mic.adr = cs->hw.mic.cfg_reg + MIC_ADR; + cs->hw.mic.isac = cs->hw.mic.cfg_reg + MIC_ISAC; + cs->hw.mic.hscx = cs->hw.mic.cfg_reg + MIC_HSCX; - if (mic_probe(card->cs, card) < 0) - return 0; - return 1; + if (!request_region(cs->hw.mic.cfg_reg, bytecnt, "mic isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.mic.cfg_reg, + cs->hw.mic.cfg_reg + bytecnt); + return (0); + } + printk(KERN_INFO "mic: defined at 0x%x IRQ %d\n", + cs->hw.mic.cfg_reg, cs->irq); + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &mic_card_msg; + cs->irq_func = &mic_interrupt; + ISACVersion(cs, "mic:"); + if (HscxVersion(cs, "mic:")) { + printk(KERN_WARNING + "mic: wrong HSCX versions check IO address\n"); + release_io_mic(cs); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/netjet.c b/drivers/isdn/hisax/netjet.c --- a/drivers/isdn/hisax/netjet.c Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/netjet.c Thu Feb 19 23:44:23 2004 @@ -1,4 +1,4 @@ -/* $Id: netjet.c,v 1.24.6.6 2001/09/23 22:24:50 kai Exp $ +/* $Id: netjet.c,v 1.29.2.4 2004/02/11 13:21:34 keil Exp $ * * low level stuff for Traverse Technologie NETJet ISDN cards * @@ -25,63 +25,40 @@ #include #include "netjet.h" -const char *NETjet_revision = "$Revision: 1.24.6.6 $"; -static spinlock_t netjet_lock = SPIN_LOCK_UNLOCKED; +const char *NETjet_revision = "$Revision: 1.29.2.4 $"; /* Interface functions */ -u8 -NETjet_ReadIC(struct IsdnCardState *cs, u8 offset) +u_char +NETjet_ReadIC(struct IsdnCardState *cs, u_char offset) { - unsigned long flags; - u8 ret; + u_char ret; - spin_lock_irqsave(&netjet_lock, flags); cs->hw.njet.auxd &= 0xfc; cs->hw.njet.auxd |= (offset>>4) & 3; byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); ret = bytein(cs->hw.njet.isac + ((offset & 0xf)<<2)); - spin_unlock_irqrestore(&netjet_lock, flags); return(ret); } void -NETjet_WriteIC(struct IsdnCardState *cs, u8 offset, u8 value) +NETjet_WriteIC(struct IsdnCardState *cs, u_char offset, u_char value) { - unsigned long flags; - - spin_lock_irqsave(&netjet_lock, flags); cs->hw.njet.auxd &= 0xfc; cs->hw.njet.auxd |= (offset>>4) & 3; byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); byteout(cs->hw.njet.isac + ((offset & 0xf)<<2), value); - spin_unlock_irqrestore(&netjet_lock, flags); } void -NETjet_ReadICfifo(struct IsdnCardState *cs, u8 *data, int size) +NETjet_ReadICfifo(struct IsdnCardState *cs, u_char *data, int size) { cs->hw.njet.auxd &= 0xfc; byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); insb(cs->hw.njet.isac, data, size); } -void -NETjet_WriteICfifo(struct IsdnCardState *cs, u8 *data, int size) -{ - cs->hw.njet.auxd &= 0xfc; - byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); - outsb(cs->hw.njet.isac, data, size); -} - -struct dc_hw_ops netjet_dc_ops = { - .read_reg = NETjet_ReadIC, - .write_reg = NETjet_WriteIC, - .read_fifo = NETjet_ReadICfifo, - .write_fifo = NETjet_WriteICfifo, -}; - -static u16 fcstab[256] = +__u16 fcstab[256] = { 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, @@ -117,7 +94,15 @@ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 }; -void fill_mem(struct BCState *bcs, u_int *pos, u_int cnt, int chan, u8 fill) +void +NETjet_WriteICfifo(struct IsdnCardState *cs, u_char *data, int size) +{ + cs->hw.njet.auxd &= 0xfc; + byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); + outsb(cs->hw.njet.isac, data, size); +} + +void fill_mem(struct BCState *bcs, u_int *pos, u_int cnt, int chan, u_char fill) { u_int mask=0x000000ff, val = 0, *p=pos; u_int i; @@ -140,7 +125,7 @@ mode_tiger(struct BCState *bcs, int mode, int bc) { struct IsdnCardState *cs = bcs->cs; - u8 led; + u_char led; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "Tiger mode %d bchan %d/%d", @@ -216,11 +201,11 @@ bytein(cs->hw.njet.base + NETJET_PULSE_CNT)); } -static void printframe(struct IsdnCardState *cs, u8 *buf, int count, char *s) { +static void printframe(struct IsdnCardState *cs, u_char *buf, int count, char *s) { char tmp[128]; char *t = tmp; int i=count,j; - u8 *p = buf; + u_char *p = buf; t += sprintf(t, "tiger %s(%4d)", s, count); while (i>0) { @@ -269,11 +254,11 @@ static int make_raw_data(struct BCState *bcs) { // this make_raw is for 64k register u_int i,s_cnt=0; - register u8 j; - register u8 val; - register u8 s_one = 0; - register u8 s_val = 0; - register u8 bitcnt = 0; + register u_char j; + register u_char val; + register u_char s_one = 0; + register u_char s_val = 0; + register u_char bitcnt = 0; u_int fcs; if (!bcs->tx_skb) { @@ -359,11 +344,11 @@ static int make_raw_data_56k(struct BCState *bcs) { // this make_raw is for 56k register u_int i,s_cnt=0; - register u8 j; - register u8 val; - register u8 s_one = 0; - register u8 s_val = 0; - register u8 bitcnt = 0; + register u_char j; + register u_char val; + register u_char s_one = 0; + register u_char s_val = 0; + register u_char bitcnt = 0; u_int fcs; if (!bcs->tx_skb) { @@ -439,7 +424,8 @@ memcpy(skb_put(skb, count), bcs->hw.tiger.rcvbuf, count); skb_queue_tail(&bcs->rqueue, skb); } - sched_b_event(bcs, B_RCVBUFREADY); + test_and_set_bit(B_RCVBUFREADY, &bcs->event); + schedule_work(&bcs->tqueue); if (bcs->cs->debug & L1_DEB_RECEIVE_FRAME) printframe(bcs->cs, bcs->hw.tiger.rcvbuf, count, "rec"); @@ -449,16 +435,16 @@ static void read_raw(struct BCState *bcs, u_int *buf, int cnt){ int i; - register u8 j; - register u8 val; + register u_char j; + register u_char val; u_int *pend = bcs->hw.tiger.rec +NETJET_DMA_RXSIZE -1; - register u8 state = bcs->hw.tiger.r_state; - register u8 r_one = bcs->hw.tiger.r_one; - register u8 r_val = bcs->hw.tiger.r_val; + register u_char state = bcs->hw.tiger.r_state; + register u_char r_one = bcs->hw.tiger.r_one; + register u_char r_val = bcs->hw.tiger.r_val; register u_int bitcnt = bcs->hw.tiger.r_bitcnt; u_int *p = buf; int bits; - u8 mask; + u_char mask; if (bcs->mode == L1_MODE_HDLC) { // it's 64k mask = 0xff; @@ -682,9 +668,7 @@ if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) { write_raw(bcs, bcs->hw.tiger.sendp, bcs->hw.tiger.free); } else if (test_and_clear_bit(BC_FLG_HALF, &bcs->Flag)) { - p = inl(bcs->cs->hw.njet.base + NETJET_DMA_READ_ADR) - - bcs->hw.tiger.send_dma - + bcs->hw.tiger.send; + p = bus_to_virt(inl(bcs->cs->hw.njet.base + NETJET_DMA_READ_ADR)); sp = bcs->hw.tiger.sendp; if (p == bcs->hw.tiger.s_end) p = bcs->hw.tiger.send -1; @@ -705,9 +689,7 @@ write_raw(bcs, p, bcs->hw.tiger.free - cnt); } } else if (test_and_clear_bit(BC_FLG_EMPTY, &bcs->Flag)) { - p = inl(bcs->cs->hw.njet.base + NETJET_DMA_READ_ADR) - - bcs->hw.tiger.send_dma - + bcs->hw.tiger.send; + p = bus_to_virt(inl(bcs->cs->hw.njet.base + NETJET_DMA_READ_ADR)); cnt = bcs->hw.tiger.s_end - p; if (cnt < 2) { p = bcs->hw.tiger.send + 1; @@ -729,7 +711,7 @@ static void write_raw(struct BCState *bcs, u_int *buf, int cnt) { u_int mask, val, *p=buf; - int i, s_cnt; + u_int i, s_cnt; if (cnt <= 0) return; @@ -766,7 +748,16 @@ if (!bcs->tx_skb) { debugl1(bcs->cs,"tiger write_raw: NULL skb s_cnt %d", s_cnt); } else { - xmit_complete_b(bcs); + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->tx_skb->len; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; } test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); bcs->hw.tiger.free = cnt - s_cnt; @@ -790,7 +781,8 @@ debugl1(bcs->cs, "tiger write_raw: fill rest %d", cnt - s_cnt); } - sched_b_event(bcs, B_XMTBUFREADY); + test_and_set_bit(B_XMTBUFREADY, &bcs->event); + schedule_work(&bcs->tqueue); } } } else if (test_and_clear_bit(BC_FLG_NOFRAME, &bcs->Flag)) { @@ -838,36 +830,59 @@ static void tiger_l2l1(struct PStack *st, int pr, void *arg) { + struct BCState *bcs = st->l1.bcs; struct sk_buff *skb = arg; - struct IsdnCardState *cs = st->l1.bcs->cs; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + printk(KERN_WARNING "tiger_l2l1: this shouldn't happen\n"); + } else { + bcs->tx_skb = skb; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - mode_tiger(st->l1.bcs, st->l1.mode, st->l1.bc); - if (cs->hw.njet.bc_activate) - (cs->hw.njet.bc_activate)(cs, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + mode_tiger(bcs, st->l1.mode, st->l1.bc); + /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */ + spin_unlock_irqrestore(&bcs->cs->lock, flags); + bcs->cs->cardmsg(bcs->cs, MDL_BC_ASSIGN, (void *)(&st->l1.bc)); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): - if (cs->hw.njet.bc_deactivate) - (cs->hw.njet.bc_deactivate)(cs, st->l1.bc); + /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG */ + bcs->cs->cardmsg(bcs->cs, MDL_BC_RELEASE, (void *)(&st->l1.bc)); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - mode_tiger(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + mode_tiger(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -928,7 +943,7 @@ if (open_tigerstate(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = tiger_l2l1; + st->l2.l2l1 = tiger_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); @@ -936,47 +951,32 @@ } -static struct bc_l1_ops netjet_l1_ops = { - .fill_fifo = netjet_fill_dma, - .open = setstack_tiger, - .close = close_tigerstate, -}; - void __init inittiger(struct IsdnCardState *cs) { - cs->bc_l1_ops = &netjet_l1_ops; - - cs->bcs[0].hw.tiger.send = - pci_alloc_consistent(cs->hw.njet.pdev, - NETJET_DMA_TXSIZE * sizeof(unsigned int), - &cs->bcs[0].hw.tiger.send_dma); - if (!cs->bcs[0].hw.tiger.send) { + if (!(cs->bcs[0].hw.tiger.send = kmalloc(NETJET_DMA_TXSIZE * sizeof(unsigned int), + GFP_KERNEL | GFP_DMA))) { printk(KERN_WARNING "HiSax: No memory for tiger.send\n"); return; } - cs->bcs[0].hw.tiger.s_end = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1; - - cs->bcs[1].hw.tiger.send = cs->bcs[0].hw.tiger.send; - cs->bcs[1].hw.tiger.send_dma = cs->bcs[0].hw.tiger.send_dma; - cs->bcs[1].hw.tiger.s_end = cs->bcs[0].hw.tiger.s_end; + cs->bcs[0].hw.tiger.s_irq = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE/2 - 1; + cs->bcs[0].hw.tiger.s_end = cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1; + cs->bcs[1].hw.tiger.send = cs->bcs[0].hw.tiger.send; + cs->bcs[1].hw.tiger.s_irq = cs->bcs[0].hw.tiger.s_irq; + cs->bcs[1].hw.tiger.s_end = cs->bcs[0].hw.tiger.s_end; memset(cs->bcs[0].hw.tiger.send, 0xff, NETJET_DMA_TXSIZE * sizeof(unsigned int)); debugl1(cs, "tiger: send buf %x - %x", (u_int)cs->bcs[0].hw.tiger.send, (u_int)(cs->bcs[0].hw.tiger.send + NETJET_DMA_TXSIZE - 1)); - outl(cs->bcs[0].hw.tiger.send_dma, + outl(virt_to_bus(cs->bcs[0].hw.tiger.send), cs->hw.njet.base + NETJET_DMA_READ_START); - outl(cs->bcs[0].hw.tiger.send_dma + NETJET_DMA_TXSIZE/2 - 1, + outl(virt_to_bus(cs->bcs[0].hw.tiger.s_irq), cs->hw.njet.base + NETJET_DMA_READ_IRQ); - outl(cs->bcs[0].hw.tiger.send_dma + NETJET_DMA_TXSIZE - 1, + outl(virt_to_bus(cs->bcs[0].hw.tiger.s_end), cs->hw.njet.base + NETJET_DMA_READ_END); - - cs->bcs[0].hw.tiger.rec = - pci_alloc_consistent(cs->hw.njet.pdev, - NETJET_DMA_RXSIZE * sizeof(unsigned int), - &cs->bcs[0].hw.tiger.rec_dma); - if (!cs->bcs[0].hw.tiger.rec) { + if (!(cs->bcs[0].hw.tiger.rec = kmalloc(NETJET_DMA_RXSIZE * sizeof(unsigned int), + GFP_KERNEL | GFP_DMA))) { printk(KERN_WARNING "HiSax: No memory for tiger.rec\n"); return; @@ -984,39 +984,36 @@ debugl1(cs, "tiger: rec buf %x - %x", (u_int)cs->bcs[0].hw.tiger.rec, (u_int)(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1)); cs->bcs[1].hw.tiger.rec = cs->bcs[0].hw.tiger.rec; - cs->bcs[1].hw.tiger.rec_dma = cs->bcs[0].hw.tiger.rec_dma; memset(cs->bcs[0].hw.tiger.rec, 0xff, NETJET_DMA_RXSIZE * sizeof(unsigned int)); - outl(cs->bcs[0].hw.tiger.rec_dma, + outl(virt_to_bus(cs->bcs[0].hw.tiger.rec), cs->hw.njet.base + NETJET_DMA_WRITE_START); - outl(cs->bcs[0].hw.tiger.rec_dma + NETJET_DMA_RXSIZE/2 - 1, + outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE/2 - 1), cs->hw.njet.base + NETJET_DMA_WRITE_IRQ); - outl(cs->bcs[0].hw.tiger.rec_dma + NETJET_DMA_RXSIZE - 1, + outl(virt_to_bus(cs->bcs[0].hw.tiger.rec + NETJET_DMA_RXSIZE - 1), cs->hw.njet.base + NETJET_DMA_WRITE_END); debugl1(cs, "tiger: dmacfg %x/%x pulse=%d", inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR), inl(cs->hw.njet.base + NETJET_DMA_READ_ADR), bytein(cs->hw.njet.base + NETJET_PULSE_CNT)); cs->hw.njet.last_is0 = 0; + cs->bcs[0].BC_SetStack = setstack_tiger; + cs->bcs[1].BC_SetStack = setstack_tiger; + cs->bcs[0].BC_Close = close_tigerstate; + cs->bcs[1].BC_Close = close_tigerstate; } -static void +void releasetiger(struct IsdnCardState *cs) { if (cs->bcs[0].hw.tiger.send) { - pci_free_consistent(cs->hw.njet.pdev, - NETJET_DMA_TXSIZE * sizeof(unsigned int), - cs->bcs[0].hw.tiger.send, - cs->bcs[0].hw.tiger.send_dma); + kfree(cs->bcs[0].hw.tiger.send); cs->bcs[0].hw.tiger.send = NULL; } if (cs->bcs[1].hw.tiger.send) { cs->bcs[1].hw.tiger.send = NULL; } if (cs->bcs[0].hw.tiger.rec) { - pci_free_consistent(cs->hw.njet.pdev, - NETJET_DMA_RXSIZE * sizeof(unsigned int), - cs->bcs[0].hw.tiger.rec, - cs->bcs[0].hw.tiger.rec_dma); + kfree(cs->bcs[0].hw.tiger.rec); cs->bcs[0].hw.tiger.rec = NULL; } if (cs->bcs[1].hw.tiger.rec) { @@ -1025,11 +1022,11 @@ } void -netjet_release(struct IsdnCardState *cs) +release_io_netjet(struct IsdnCardState *cs) { byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0); byteout(cs->hw.njet.base + NETJET_IRQMASK1, 0); releasetiger(cs); - hisax_release_resources(cs); + release_region(cs->hw.njet.base, 256); } diff -Nru a/drivers/isdn/hisax/netjet.h b/drivers/isdn/hisax/netjet.h --- a/drivers/isdn/hisax/netjet.h Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/hisax/netjet.h Thu Feb 19 23:44:27 2004 @@ -1,4 +1,4 @@ -/* $Id: netjet.h,v 2.5.6.3 2001/09/23 22:24:50 kai Exp $ +/* $Id: netjet.h,v 2.8.2.2 2004/01/12 22:52:28 keil Exp $ * * NETjet common header file * @@ -57,12 +57,10 @@ #define HDLC_FLAG_VALUE 0x7e -extern struct dc_hw_ops netjet_dc_ops; - -u8 NETjet_ReadIC(struct IsdnCardState *cs, u8 offset); -void NETjet_WriteIC(struct IsdnCardState *cs, u8 offset, u8 value); -void NETjet_ReadICfifo(struct IsdnCardState *cs, u8 *data, int size); -void NETjet_WriteICfifo(struct IsdnCardState *cs, u8 *data, int size); +u_char NETjet_ReadIC(struct IsdnCardState *cs, u_char offset); +void NETjet_WriteIC(struct IsdnCardState *cs, u_char offset, u_char value); +void NETjet_ReadICfifo(struct IsdnCardState *cs, u_char *data, int size); +void NETjet_WriteICfifo(struct IsdnCardState *cs, u_char *data, int size); void read_tiger(struct IsdnCardState *cs); void write_tiger(struct IsdnCardState *cs); @@ -70,5 +68,5 @@ void netjet_fill_dma(struct BCState *bcs); void netjet_interrupt(int intno, void *dev_id, struct pt_regs *regs); void inittiger(struct IsdnCardState *cs); -void netjet_release(struct IsdnCardState *cs); +void release_io_netjet(struct IsdnCardState *cs); diff -Nru a/drivers/isdn/hisax/niccy.c b/drivers/isdn/hisax/niccy.c --- a/drivers/isdn/hisax/niccy.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hisax/niccy.c Thu Feb 19 23:44:24 2004 @@ -1,4 +1,4 @@ -/* $Id: niccy.c,v 1.15.6.6 2001/10/20 22:08:24 kai Exp $ +/* $Id: niccy.c,v 1.21.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for Dr. Neuhaus NICCY PnP and NICCY PCI and * compatible (SAGEM cybermodem) @@ -24,8 +24,7 @@ #include extern const char *CardType[]; -const char *niccy_revision = "$Revision: 1.15.6.6 $"; -static spinlock_t niccy_lock = SPIN_LOCK_UNLOCKED; +const char *niccy_revision = "$Revision: 1.21.2.4 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -47,127 +46,140 @@ #define PCI_IRQ_DISABLE 0xff0000 #define PCI_IRQ_ASSERT 0x800000 -static inline u8 -readreg(unsigned int ale, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&niccy_lock, flags); byteout(ale, off); ret = bytein(adr); - spin_unlock_irqrestore(&niccy_lock, flags); - return ret; + return (ret); } static inline void -writereg(unsigned int ale, unsigned int adr, u8 off, u8 data) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; - - spin_lock_irqsave(&niccy_lock, flags); byteout(ale, off); - byteout(adr, data); - spin_unlock_irqrestore(&niccy_lock, flags); + insb(adr, data, size); } + static inline void -readfifo(unsigned int ale, unsigned int adr, u8 off, u8 * data, int size) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { byteout(ale, off); - insb(adr, data, size); + byteout(adr, data); } static inline void -writefifo(unsigned int ale, unsigned int adr, u8 off, u8 * data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { byteout(ale, off); outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, offset); + return (readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { readfifo(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, 0, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { writefifo(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - return readreg(cs->hw.niccy.hscx_ale, - cs->hw.niccy.hscx, offset + (hscx ? 0x40 : 0)); + return (readreg(cs->hw.niccy.hscx_ale, + cs->hw.niccy.hscx, offset + (hscx ? 0x40 : 0))); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, offset + (hscx ? 0x40 : 0), value); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - readfifo(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, - hscx ? 0x40 : 0, data, size); -} +#define READHSCX(cs, nr, reg) readreg(cs->hw.niccy.hscx_ale, \ + cs->hw.niccy.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.niccy.hscx_ale, \ + cs->hw.niccy.hscx, reg + (nr ? 0x40 : 0), data) -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - writefifo(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, - hscx ? 0x40 : 0, data, size); -} +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.niccy.hscx_ale, \ + cs->hw.niccy.hscx, (nr ? 0x40 : 0), ptr, cnt) -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.niccy.hscx_ale, \ + cs->hw.niccy.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" static irqreturn_t niccy_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - + u_char val; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); if (cs->subtyp == NICCY_PCI) { int ival; ival = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); - if (!(ival & PCI_IRQ_ASSERT)) /* IRQ not for us (shared) */ + if (!(ival & PCI_IRQ_ASSERT)) { /* IRQ not for us (shared) */ + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_NONE; + } outl(ival, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); } - return hscxisac_irq(intno, dev_id, regs); + val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = readreg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_ISTA + 0x40); + if (val) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_ISTA); + if (val) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.niccy.isac_ale, cs->hw.niccy.isac, ISAC_MASK, 0); + writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK, 0); + writereg(cs->hw.niccy.hscx_ale, cs->hw.niccy.hscx, HSCX_MASK + 0x40, 0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; } void -niccy_release(struct IsdnCardState *cs) +release_io_niccy(struct IsdnCardState *cs) { if (cs->subtyp == NICCY_PCI) { int val; @@ -175,11 +187,15 @@ val = inl(cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); val &= PCI_IRQ_DISABLE; outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); + release_region(cs->hw.niccy.cfg_reg, 0x40); + release_region(cs->hw.niccy.isac, 4); + } else { + release_region(cs->hw.niccy.isac, 2); + release_region(cs->hw.niccy.isac_ale, 2); } - hisax_release_resources(cs); } -static int +static void niccy_reset(struct IsdnCardState *cs) { if (cs->subtyp == NICCY_PCI) { @@ -189,78 +205,32 @@ val |= PCI_IRQ_ENABLE; outl(val, cs->hw.niccy.cfg_reg + PCI_IRQ_CTRL_REG); } - return 0; + inithscxisac(cs, 3); } -static struct card_ops niccy_ops = { - .init = inithscxisac, - .reset = niccy_reset, - .release = niccy_release, - .irq_func = niccy_interrupt, -}; - -static int __init -niccy_probe(struct IsdnCardState *cs) +static int +niccy_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n", - CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI", - cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale); - cs->card_ops = &niccy_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - return -EBUSY; - return 0; -} - -static int __init -niccy_pnp_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->subtyp = NICCY_PNP; - cs->irq = card->para[0]; - cs->hw.niccy.isac = card->para[1] + ISAC_PNP; - cs->hw.niccy.hscx = card->para[1] + HSCX_PNP; - cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP; - cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP; - cs->hw.niccy.cfg_reg = 0; - - if (!request_io(&cs->rs, cs->hw.niccy.isac, 2, "niccy data")) - goto err; - if (!request_io(&cs->rs, cs->hw.niccy.isac_ale, 2, "niccy addr")) - goto err; - if (niccy_probe(cs) < 0) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -niccy_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - u32 pci_ioaddr; - - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = NICCY_PCI; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.niccy.cfg_reg = pci_resource_start(pdev, 0); - pci_ioaddr = pci_resource_start(pdev, 1); - cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA; - cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR; - cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA; - cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR; - if (!request_io(&cs->rs, cs->hw.niccy.isac, 4, "niccy")) - goto err; - if (!request_io(&cs->rs, cs->hw.niccy.cfg_reg, 0x40, "niccy pci")) - goto err; - if (niccy_probe(cs) < 0) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + u_long flags; + + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + niccy_reset(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_niccy(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + niccy_reset(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); } static struct pci_dev *niccy_dev __initdata = NULL; @@ -271,62 +241,149 @@ int __init setup_niccy(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, niccy_revision); printk(KERN_INFO "HiSax: Niccy driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_NICCY) + return (0); #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; + struct pnp_dev *pnp_d = NULL; + int err; - if ((pb = pnp_find_card( + if ((pnp_c = pnp_find_card( ISAPNP_VENDOR('S', 'D', 'A'), ISAPNP_FUNCTION(0x0150), pnp_c))) { - pnp_c = pb; - pd = NULL; - if (!(pd = pnp_find_dev(pnp_c, + if (!(pnp_d = pnp_find_dev(pnp_c, ISAPNP_VENDOR('S', 'D', 'A'), - ISAPNP_FUNCTION(0x0150), pd))) { + ISAPNP_FUNCTION(0x0150), pnp_d))) { printk(KERN_ERR "NiccyPnP: PnP error card found, no device\n"); return (0); } - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "NiccyPnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "NiccyPnP: activate failed\n"); - pnp_device_detach(pd); - return 0; + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0) || !pnp_port_valid(pd, 1)) { + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[2] = pnp_port_start(pnp_d, 1); + card->para[0] = pnp_irq(pnp_d, 0);; + if (!card->para[0] || !card->para[1] || !card->para[2]) { printk(KERN_ERR "NiccyPnP:some resources are missing %ld/%lx/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0), pnp_port_start(pd, 1)); - pnp_device_detach(pd); + card->para[0], card->para[1], card->para[2]); + pnp_disable_dev(pnp_d); return(0); } - card->para[1] = pnp_port_start(pd, 0); - card->para[2] = pnp_port_start(pd, 1); - card->para[0] = pnp_irq(pd, 0); } else { printk(KERN_INFO "NiccyPnP: no ISAPnP card found\n"); } } #endif if (card->para[1]) { - if (niccy_pnp_probe(card->cs, card) < 0) - return 0; - return 1; + cs->hw.niccy.isac = card->para[1] + ISAC_PNP; + cs->hw.niccy.hscx = card->para[1] + HSCX_PNP; + cs->hw.niccy.isac_ale = card->para[2] + ISAC_PNP; + cs->hw.niccy.hscx_ale = card->para[2] + HSCX_PNP; + cs->hw.niccy.cfg_reg = 0; + cs->subtyp = NICCY_PNP; + cs->irq = card->para[0]; + if (!request_region(cs->hw.niccy.isac, 2, "niccy data")) { + printk(KERN_WARNING + "HiSax: %s data port %x-%x already in use\n", + CardType[card->typ], + cs->hw.niccy.isac, + cs->hw.niccy.isac + 1); + return (0); + } + if (!request_region(cs->hw.niccy.isac_ale, 2, "niccy addr")) { + printk(KERN_WARNING + "HiSax: %s address port %x-%x already in use\n", + CardType[card->typ], + cs->hw.niccy.isac_ale, + cs->hw.niccy.isac_ale + 1); + release_region(cs->hw.niccy.isac, 2); + return (0); + } } else { -#ifdef CONFIG_PCI +#if CONFIG_PCI + u_int pci_ioaddr; + cs->subtyp = 0; if ((niccy_dev = pci_find_device(PCI_VENDOR_ID_SATSAGEM, PCI_DEVICE_ID_SATSAGEM_NICCY, niccy_dev))) { - if (niccy_pci_probe(card->cs, niccy_dev) < 0) - return 0; - return 1; + if (pci_enable_device(niccy_dev)) + return(0); + /* get IRQ */ + if (!niccy_dev->irq) { + printk(KERN_WARNING "Niccy: No IRQ for PCI card found\n"); + return(0); + } + cs->irq = niccy_dev->irq; + cs->hw.niccy.cfg_reg = pci_resource_start(niccy_dev, 0); + if (!cs->hw.niccy.cfg_reg) { + printk(KERN_WARNING "Niccy: No IO-Adr for PCI cfg found\n"); + return(0); + } + pci_ioaddr = pci_resource_start(niccy_dev, 1); + if (!pci_ioaddr) { + printk(KERN_WARNING "Niccy: No IO-Adr for PCI card found\n"); + return(0); + } + cs->subtyp = NICCY_PCI; + } else { + printk(KERN_WARNING "Niccy: No PCI card found\n"); + return(0); + } + cs->irq_flags |= SA_SHIRQ; + cs->hw.niccy.isac = pci_ioaddr + ISAC_PCI_DATA; + cs->hw.niccy.isac_ale = pci_ioaddr + ISAC_PCI_ADDR; + cs->hw.niccy.hscx = pci_ioaddr + HSCX_PCI_DATA; + cs->hw.niccy.hscx_ale = pci_ioaddr + HSCX_PCI_ADDR; + if (!request_region(cs->hw.niccy.isac, 4, "niccy")) { + printk(KERN_WARNING + "HiSax: %s data port %x-%x already in use\n", + CardType[card->typ], + cs->hw.niccy.isac, + cs->hw.niccy.isac + 4); + return (0); + } + if (!request_region(cs->hw.niccy.cfg_reg, 0x40, "niccy pci")) { + printk(KERN_WARNING + "HiSax: %s pci port %x-%x already in use\n", + CardType[card->typ], + cs->hw.niccy.cfg_reg, + cs->hw.niccy.cfg_reg + 0x40); + release_region(cs->hw.niccy.isac, 4); + return (0); } +#else + printk(KERN_WARNING "Niccy: io0 0 and NO_PCI_BIOS\n"); + printk(KERN_WARNING "Niccy: unable to config NICCY PCI\n"); + return (0); #endif /* CONFIG_PCI */ } - return 0; + printk(KERN_INFO "HiSax: %s %s config irq:%d data:0x%X ale:0x%X\n", + CardType[cs->typ], (cs->subtyp==1) ? "PnP":"PCI", + cs->irq, cs->hw.niccy.isac, cs->hw.niccy.isac_ale); + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &niccy_card_msg; + cs->irq_func = &niccy_interrupt; + ISACVersion(cs, "Niccy:"); + if (HscxVersion(cs, "Niccy:")) { + printk(KERN_WARNING + "Niccy: wrong HSCX versions check IO address\n"); + release_io_niccy(cs); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/nj_s.c b/drivers/isdn/hisax/nj_s.c --- a/drivers/isdn/hisax/nj_s.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hisax/nj_s.c Thu Feb 19 23:44:24 2004 @@ -1,4 +1,4 @@ -/* $Id: nj_s.c,v 2.7.6.6 2001/09/23 22:24:50 kai Exp $ +/* $Id: nj_s.c,v 2.13.2.4 2004/01/16 01:53:48 keil Exp $ * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -15,43 +15,74 @@ #include #include "netjet.h" -const char *NETjet_S_revision = "$Revision: 2.7.6.6 $"; +const char *NETjet_S_revision = "$Revision: 2.13.2.4 $"; + +static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off) +{ + return(5); +} + +static void dummywr(struct IsdnCardState *cs, int chan, u_char off, u_char value) +{ +} static irqreturn_t -nj_s_interrupt(int intno, void *dev_id, struct pt_regs *regs) +netjet_s_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val, sval; + u_char val, s1val, s0val; + u_long flags; - spin_lock(&cs->lock); - if (!((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT1)) & - NETJET_ISACIRQ)) { + spin_lock_irqsave(&cs->lock, flags); + s1val = bytein(cs->hw.njet.base + NETJET_IRQSTAT1); + if (!(s1val & NETJET_ISACIRQ)) { val = NETjet_ReadIC(cs, ISAC_ISTA); if (cs->debug & L1_DEB_ISAC) - debugl1(cs, "tiger: i1 %x %x", sval, val); + debugl1(cs, "tiger: i1 %x %x", s1val, val); if (val) { isac_interrupt(cs, val); NETjet_WriteIC(cs, ISAC_MASK, 0xFF); NETjet_WriteIC(cs, ISAC_MASK, 0x0); } - } + s1val = 1; + } else + s1val = 0; + /* + * read/write stat0 is better, because lower IRQ rate + * Note the IRQ is on for 125 us if a condition match + * thats long on modern CPU and so the IRQ is reentered + * all the time. + */ + s0val = bytein(cs->hw.njet.base + NETJET_IRQSTAT0); + if ((s0val | s1val)==0) { // shared IRQ + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_NONE; + } + if (s0val) + byteout(cs->hw.njet.base + NETJET_IRQSTAT0, s0val); /* start new code 13/07/00 GE */ /* set bits in sval to indicate which page is free */ if (inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR) < inl(cs->hw.njet.base + NETJET_DMA_WRITE_IRQ)) /* the 2nd write page is free */ - sval = 0x08; + s0val = 0x08; else /* the 1st write page is free */ - sval = 0x04; + s0val = 0x04; if (inl(cs->hw.njet.base + NETJET_DMA_READ_ADR) < inl(cs->hw.njet.base + NETJET_DMA_READ_IRQ)) /* the 2nd read page is free */ - sval = sval | 0x02; + s0val |= 0x02; else /* the 1st read page is free */ - sval = sval | 0x01; - if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */ + s0val |= 0x01; + if (s0val != cs->hw.njet.last_is0) /* we have a DMA interrupt */ { - cs->hw.njet.irqstat0 = sval; + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + printk(KERN_WARNING "nj LOCK_ATOMIC s0val %x->%x\n", + cs->hw.njet.last_is0, s0val); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED;; + } + cs->hw.njet.irqstat0 = s0val; if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != (cs->hw.njet.last_is0 & NETJET_IRQM0_READ)) /* we have a read dma int */ @@ -61,112 +92,58 @@ /* we have a write dma int */ write_tiger(cs); /* end new code 13/07/00 GE */ + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } -/* if (!testcnt--) { - cs->hw.njet.dmactrl = 0; - byteout(cs->hw.njet.base + NETJET_DMACTRL, - cs->hw.njet.dmactrl); - byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0); - } -*/ - spin_unlock(&cs->lock); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } -static int -nj_s_reset(struct IsdnCardState *cs) +static void +reset_netjet_s(struct IsdnCardState *cs) { cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - cs->hw.njet.ctrl_reg = 0x40; /* Reset Off and status read clear */ + mdelay(10); + cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ /* now edge triggered for TJ320 GE 13/07/00 */ + /* see comment in IRQ function */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + mdelay(10); cs->hw.njet.auxd = 0; cs->hw.njet.dmactrl = 0; byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); - return 0; } -static void -nj_s_init(struct IsdnCardState *cs) -{ - inittiger(cs); - initisac(cs); -} - -static struct card_ops nj_s_ops = { - .init = nj_s_init, - .reset = nj_s_reset, - .release = netjet_release, - .irq_func = nj_s_interrupt, -}; - -static int __init -nj_s_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +static int +NETjet_S_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - if (pci_enable_device(pdev)) - goto err; - - pci_set_master(pdev); + u_long flags; - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.njet.pdev = pdev; - cs->hw.njet.base = pci_resource_start(pdev, 0); - if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netjet-s isdn")) - return 0; - - cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; - cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; - - cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ - byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ - byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.auxd = 0xC0; - cs->hw.njet.dmactrl = 0; - - byteout(cs->hw.njet.auxa, 0); - byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); - byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); - byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); - - switch ((NETjet_ReadIC(cs, ISAC_RBCH) >> 5) & 3) { - case 0 : - break; - case 3 : - printk(KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" ); - goto err; - default : - printk(KERN_WARNING "NETjet-S: No PCI card found\n" ); - goto err; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_netjet_s(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_netjet(cs); + return(0); + case CARD_INIT: + reset_netjet_s(cs); + inittiger(cs); + spin_lock_irqsave(&cs->lock, flags); + clear_pending_isac_ints(cs); + initisac(cs); + /* Reenable all IRQ */ + cs->writeisac(cs, ISAC_MASK, 0); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); } - printk(KERN_INFO - "NETjet-S: PCI card configured at %#lx IRQ %d\n", - cs->hw.njet.base, cs->irq); - - nj_s_reset(cs); - cs->irq_flags |= SA_SHIRQ; - cs->card_ops = &nj_s_ops; - isac_setup(cs, &netjet_dc_ops); - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + return(0); } static struct pci_dev *dev_netjet __initdata = NULL; @@ -174,32 +151,116 @@ int __init setup_netjet_s(struct IsdnCard *card) { + int bytecnt; + struct IsdnCardState *cs = card->cs; char tmp[64]; #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif strcpy(tmp, NETjet_S_revision); - printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", - HiSax_getrev(tmp)); + printk(KERN_INFO "HiSax: Traverse Tech. NETjet-S driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_NETJET_S) + return(0); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + +#if CONFIG_PCI - dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, - PCI_DEVICE_ID_TIGERJET_300, dev_netjet); - if (dev_netjet) { - /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */ - if (dev_netjet->subsystem_vendor == 0x55 && - dev_netjet->subsystem_device == 0x02) { - printk(KERN_WARNING "Netjet: You tried to load this " - "driver with an incompatible TigerJet-card\n"); - printk(KERN_WARNING "Use type=41 for Formula-n " - "enter:now ISDN PCI and compatible\n"); - return 0; + for ( ;; ) + { + if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, + PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { + if (pci_enable_device(dev_netjet)) + return(0); + pci_set_master(dev_netjet); + cs->irq = dev_netjet->irq; + if (!cs->irq) { + printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n"); + return(0); + } + cs->hw.njet.base = pci_resource_start(dev_netjet, 0); + if (!cs->hw.njet.base) { + printk(KERN_WARNING "NETjet-S: No IO-Adr for PCI card found\n"); + return(0); + } + /* 2001/10/04 Christoph Ersfeld, Formula-n Europe AG www.formula-n.com */ + if ((dev_netjet->subsystem_vendor == 0x55) && + (dev_netjet->subsystem_device == 0x02)) { + printk(KERN_WARNING "Netjet: You tried to load this driver with an incompatible TigerJet-card\n"); + printk(KERN_WARNING "Use type=41 for Formula-n enter:now ISDN PCI and compatible\n"); + return(0); + } + /* end new code */ + } else { + printk(KERN_WARNING "NETjet-S: No PCI card found\n"); + return(0); } - if (nj_s_probe(card->cs, dev_netjet)) - return 1; - return 0; + + cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; + cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; + + cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ + byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + mdelay(10); + + cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ + byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + mdelay(10); + + cs->hw.njet.auxd = 0xC0; + cs->hw.njet.dmactrl = 0; + + byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); + byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); + byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); + + switch ( ( ( NETjet_ReadIC( cs, ISAC_RBCH ) >> 5 ) & 3 ) ) + { + case 0 : + break; + + case 3 : + printk( KERN_WARNING "NETjet-S: NETspider-U PCI card found\n" ); + continue; + + default : + printk( KERN_WARNING "NETjet-S: No PCI card found\n" ); + return 0; + } + break; } - printk(KERN_WARNING "NETjet-S: No PCI card found\n"); - return 0; -} +#else + + printk(KERN_WARNING "NETjet-S: NO_PCI_BIOS\n"); + printk(KERN_WARNING "NETjet-S: unable to config NETJET-S PCI\n"); + return (0); + +#endif /* CONFIG_PCI */ + + bytecnt = 256; + printk(KERN_INFO + "NETjet-S: PCI card configured at %#lx IRQ %d\n", + cs->hw.njet.base, cs->irq); + if (!request_region(cs->hw.njet.base, bytecnt, "netjet-s isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %#lx-%#lx already in use\n", + CardType[card->typ], + cs->hw.njet.base, + cs->hw.njet.base + bytecnt); + return (0); + } + cs->readisac = &NETjet_ReadIC; + cs->writeisac = &NETjet_WriteIC; + cs->readisacfifo = &NETjet_ReadICfifo; + cs->writeisacfifo = &NETjet_WriteICfifo; + cs->BC_Read_Reg = &dummyrr; + cs->BC_Write_Reg = &dummywr; + cs->BC_Send_Data = &netjet_fill_dma; + setup_isac(cs); + cs->cardmsg = &NETjet_S_card_msg; + cs->irq_func = &netjet_s_interrupt; + cs->irq_flags |= SA_SHIRQ; + ISACVersion(cs, "NETjet-S:"); + return (1); +} diff -Nru a/drivers/isdn/hisax/nj_u.c b/drivers/isdn/hisax/nj_u.c --- a/drivers/isdn/hisax/nj_u.c Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/nj_u.c Thu Feb 19 23:44:23 2004 @@ -1,4 +1,4 @@ -/* $Id: nj_u.c,v 2.8.6.6 2001/09/23 22:24:50 kai Exp $ +/* $Id: nj_u.c,v 2.14.2.3 2004/01/13 14:31:26 keil Exp $ * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. @@ -15,15 +15,25 @@ #include #include "netjet.h" -const char *NETjet_U_revision = "$Revision: 2.8.6.6 $"; +const char *NETjet_U_revision = "$Revision: 2.14.2.3 $"; + +static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off) +{ + return(5); +} + +static void dummywr(struct IsdnCardState *cs, int chan, u_char off, u_char value) +{ +} static irqreturn_t -nj_u_interrupt(int intno, void *dev_id, struct pt_regs *regs) +netjet_u_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val, sval; + u_char val, sval; + u_long flags; - spin_lock(&cs->lock); + spin_lock_irqsave(&cs->lock, flags); if (!((sval = bytein(cs->hw.njet.base + NETJET_IRQSTAT1)) & NETJET_ISACIRQ)) { val = NETjet_ReadIC(cs, ICC_ISTA); @@ -51,6 +61,10 @@ sval = sval | 0x01; if (sval != cs->hw.njet.last_is0) /* we have a DMA interrupt */ { + if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) { + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; + } cs->hw.njet.irqstat0 = sval; if ((cs->hw.njet.irqstat0 & NETJET_IRQM0_READ) != (cs->hw.njet.last_is0 & NETJET_IRQM0_READ)) @@ -61,113 +75,58 @@ /* we have a write dma int */ write_tiger(cs); /* end new code 13/07/00 GE */ + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); } -/* if (!testcnt--) { - cs->hw.njet.dmactrl = 0; - byteout(cs->hw.njet.base + NETJET_DMACTRL, - cs->hw.njet.dmactrl); - byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0); - } -*/ - spin_unlock(&cs->lock); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } -static int -nj_u_reset(struct IsdnCardState *cs) +static void +reset_netjet_u(struct IsdnCardState *cs) { cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ + mdelay(10); cs->hw.njet.ctrl_reg = 0x40; /* Reset Off and status read clear */ /* now edge triggered for TJ320 GE 13/07/00 */ byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - + mdelay(10); cs->hw.njet.auxd = 0xC0; cs->hw.njet.dmactrl = 0; byteout(cs->hw.njet.auxa, 0); byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); - return 0; } -static void -nj_u_init(struct IsdnCardState *cs) +static int +NETjet_U_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - inittiger(cs); - initicc(cs); - /* Reenable all IRQ */ - NETjet_WriteIC(cs, ICC_MASK, 0); -} - -static struct card_ops nj_u_ops = { - .init = nj_u_init, - .reset = nj_u_reset, - .release = netjet_release, - .irq_func = nj_u_interrupt, -}; - -static int __init -nj_u_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - if (pci_enable_device(pdev)) - goto err; - - pci_set_master(pdev); - - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.njet.pdev = pdev; - cs->hw.njet.base = pci_resource_start(pdev, 0); - if (!request_io(&cs->rs, cs->hw.njet.base, 0x100, "netspider-u isdn")) - goto err; - - cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; - cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; - - cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ - byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ - byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); - - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); /* Timeout 10ms */ - - cs->hw.njet.auxd = 0xC0; - cs->hw.njet.dmactrl = 0; - - byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); - byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); - byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); + u_long flags; - switch ((NETjet_ReadIC(cs, ICC_RBCH) >> 5) & 3) { - case 3: - break; - case 0: - printk(KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" ); - goto err; - default: - printk(KERN_WARNING "NETspider-U: No PCI card found\n" ); - goto err; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_netjet_u(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_netjet(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inittiger(cs); + reset_netjet_u(cs); + clear_pending_icc_ints(cs); + initicc(cs); + /* Reenable all IRQ */ + cs->writeisac(cs, ICC_MASK, 0); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); } - printk(KERN_INFO "NETspider-U: PCI card configured at %#lx IRQ %d\n", - cs->hw.njet.base, cs->irq); - - nj_u_reset(cs); - cs->card_ops = &nj_u_ops; - icc_setup(cs, &netjet_dc_ops); - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + return(0); } static struct pci_dev *dev_netjet __initdata = NULL; @@ -175,21 +134,111 @@ int __init setup_netjet_u(struct IsdnCard *card) { + int bytecnt; + struct IsdnCardState *cs = card->cs; char tmp[64]; +#if CONFIG_PCI +#endif #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif strcpy(tmp, NETjet_U_revision); - printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", - HiSax_getrev(tmp)); - - dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, - PCI_DEVICE_ID_TIGERJET_300, dev_netjet); - if (dev_netjet) { - if (nj_u_probe(card->cs, dev_netjet)) - return 1; - return 0; + printk(KERN_INFO "HiSax: Traverse Tech. NETspider-U driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_NETJET_U) + return(0); + test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags); + +#if CONFIG_PCI + + for ( ;; ) + { + if ((dev_netjet = pci_find_device(PCI_VENDOR_ID_TIGERJET, + PCI_DEVICE_ID_TIGERJET_300, dev_netjet))) { + if (pci_enable_device(dev_netjet)) + return(0); + pci_set_master(dev_netjet); + cs->irq = dev_netjet->irq; + if (!cs->irq) { + printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n"); + return(0); + } + cs->hw.njet.base = pci_resource_start(dev_netjet, 0); + if (!cs->hw.njet.base) { + printk(KERN_WARNING "NETspider-U: No IO-Adr for PCI card found\n"); + return(0); + } + } else { + printk(KERN_WARNING "NETspider-U: No PCI card found\n"); + return(0); + } + + cs->hw.njet.auxa = cs->hw.njet.base + NETJET_AUXDATA; + cs->hw.njet.isac = cs->hw.njet.base | NETJET_ISAC_OFF; + mdelay(10); + + cs->hw.njet.ctrl_reg = 0xff; /* Reset On */ + byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + mdelay(10); + + cs->hw.njet.ctrl_reg = 0x00; /* Reset Off and status read clear */ + byteout(cs->hw.njet.base + NETJET_CTRL, cs->hw.njet.ctrl_reg); + mdelay(10); + + cs->hw.njet.auxd = 0xC0; + cs->hw.njet.dmactrl = 0; + + byteout(cs->hw.njet.auxa, 0); + byteout(cs->hw.njet.base + NETJET_AUXCTRL, ~NETJET_ISACIRQ); + byteout(cs->hw.njet.base + NETJET_IRQMASK1, NETJET_ISACIRQ); + byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); + + switch ( ( ( NETjet_ReadIC( cs, ICC_RBCH ) >> 5 ) & 3 ) ) + { + case 3 : + break; + + case 0 : + printk( KERN_WARNING "NETspider-U: NETjet-S PCI card found\n" ); + continue; + + default : + printk( KERN_WARNING "NETspider-U: No PCI card found\n" ); + return 0; + } + break; } - printk(KERN_WARNING "NETspider-U: No PCI card found\n"); - return 0; +#else + + printk(KERN_WARNING "NETspider-U: NO_PCI_BIOS\n"); + printk(KERN_WARNING "NETspider-U: unable to config NETspider-U PCI\n"); + return (0); + +#endif /* CONFIG_PCI */ + + bytecnt = 256; + + printk(KERN_INFO + "NETspider-U: PCI card configured at %#lx IRQ %d\n", + cs->hw.njet.base, cs->irq); + if (!request_region(cs->hw.njet.base, bytecnt, "netspider-u isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %#lx-%#lx already in use\n", + CardType[card->typ], + cs->hw.njet.base, + cs->hw.njet.base + bytecnt); + return (0); + } + setup_icc(cs); + cs->readisac = &NETjet_ReadIC; + cs->writeisac = &NETjet_WriteIC; + cs->readisacfifo = &NETjet_ReadICfifo; + cs->writeisacfifo = &NETjet_WriteICfifo; + cs->BC_Read_Reg = &dummyrr; + cs->BC_Write_Reg = &dummywr; + cs->BC_Send_Data = &netjet_fill_dma; + cs->cardmsg = &NETjet_U_card_msg; + cs->irq_func = &netjet_u_interrupt; + cs->irq_flags |= SA_SHIRQ; + ICCVersion(cs, "NETspider-U:"); + return (1); } diff -Nru a/drivers/isdn/hisax/q931.c b/drivers/isdn/hisax/q931.c --- a/drivers/isdn/hisax/q931.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hisax/q931.c Thu Feb 19 23:44:24 2004 @@ -1,4 +1,4 @@ -/* $Id: q931.c,v 1.10.6.3 2001/09/23 22:24:50 kai Exp $ +/* $Id: q931.c,v 1.12.2.3 2004/01/13 14:31:26 keil Exp $ * * code to decode ITU Q.931 call control messages * @@ -21,9 +21,9 @@ #include "l3_1tr6.h" void -iecpy(u8 * dest, u8 * iestart, int ieoffset) +iecpy(u_char * dest, u_char * iestart, int ieoffset) { - u8 *p; + u_char *p; int l; p = iestart + ieoffset + 2; @@ -38,7 +38,7 @@ */ static struct MessageType { - u8 nr; + u_char nr; char *descr; } mtlist[] = { @@ -198,7 +198,7 @@ static int -prbits(char *dest, u8 b, int start, int len) +prbits(char *dest, u_char b, int start, int len) { char *dp = dest; @@ -214,8 +214,8 @@ } static -u8 * -skipext(u8 * p) +u_char * +skipext(u_char * p) { while (!(*p++ & 0x80)); return (p); @@ -230,7 +230,7 @@ static struct CauseValue { - u8 nr; + u_char nr; char *edescr; char *ddescr; } cvlist[] = { @@ -442,11 +442,11 @@ static int -prcause(char *dest, u8 * p) +prcause(char *dest, u_char * p) { - u8 *end; + u_char *end; char *dp = dest; - u_int i, cause; + int i, cause; end = p + p[1] + 1; p += 2; @@ -519,7 +519,7 @@ int cause_1tr6_len = (sizeof(cause_1tr6) / sizeof(struct MessageType)); static int -prcause_1tr6(char *dest, u8 * p) +prcause_1tr6(char *dest, u_char * p) { char *dp = dest; int i, cause; @@ -554,7 +554,7 @@ } static int -prchident(char *dest, u8 * p) +prchident(char *dest, u_char * p) { char *dp = dest; @@ -566,7 +566,7 @@ } static int -prcalled(char *dest, u8 * p) +prcalled(char *dest, u_char * p) { int l; char *dp = dest; @@ -583,7 +583,7 @@ return (dp - dest); } static int -prcalling(char *dest, u8 * p) +prcalling(char *dest, u_char * p) { int l; char *dp = dest; @@ -610,7 +610,7 @@ static int -prbearer(char *dest, u8 * p) +prbearer(char *dest, u_char * p) { char *dp = dest, ch; @@ -658,10 +658,10 @@ static int -prbearer_ni1(char *dest, u8 * p) +prbearer_ni1(char *dest, u_char * p) { char *dp = dest; - u8 len; + u_char len; p++; len = *p++; @@ -715,7 +715,7 @@ } static int -general(char *dest, u8 * p) +general(char *dest, u_char * p) { char *dp = dest; char ch = ' '; @@ -742,7 +742,7 @@ } static int -general_ni1(char *dest, u8 * p) +general_ni1(char *dest, u_char * p) { char *dp = dest; char ch = ' '; @@ -769,7 +769,7 @@ } static int -prcharge(char *dest, u8 * p) +prcharge(char *dest, u_char * p) { char *dp = dest; int l; @@ -786,7 +786,7 @@ return (dp - dest); } static int -prtext(char *dest, u8 * p) +prtext(char *dest, u_char * p) { char *dp = dest; int l; @@ -802,7 +802,7 @@ } static int -prfeatureind(char *dest, u8 * p) +prfeatureind(char *dest, u_char * p) { char *dp = dest; @@ -839,7 +839,7 @@ static struct DTag { /* Display tags */ - u8 nr; + u_char nr; char *descr; } dtaglist[] = { { 0x82, "Continuation" }, @@ -868,11 +868,10 @@ #define DTAGSIZE sizeof(dtaglist)/sizeof(struct DTag) static int -disptext_ni1(char *dest, u8 * p) +disptext_ni1(char *dest, u_char * p) { char *dp = dest; - int l, tag, len; - u_int i; + int l, tag, len, i; p++; l = *p++ - 1; @@ -908,7 +907,7 @@ return (dp - dest); } static int -display(char *dest, u8 * p) +display(char *dest, u_char * p) { char *dp = dest; char ch = ' '; @@ -937,7 +936,7 @@ } int -prfacility(char *dest, u8 * p) +prfacility(char *dest, u_char * p) { char *dp = dest; int l, l2; @@ -968,9 +967,9 @@ static struct InformationElement { - u8 nr; + u_char nr; char *descr; - int (*f) (char *, u8 *); + int (*f) (char *, u_char *); } ielist[] = { { @@ -1149,11 +1148,11 @@ #define WE_6_LEN (sizeof(we_6) / sizeof(struct InformationElement)) int -QuickHex(char *txt, u8 * p, int cnt) +QuickHex(char *txt, u_char * p, int cnt) { register int i; register char *t = txt; - register u8 w; + register u_char w; for (i = 0; i < cnt; i++) { *t++ = ' '; @@ -1173,7 +1172,7 @@ } void -LogFrame(struct IsdnCardState *cs, u8 * buf, int size) +LogFrame(struct IsdnCardState *cs, u_char * buf, int size) { char *dp; @@ -1197,11 +1196,11 @@ void dlogframe(struct IsdnCardState *cs, struct sk_buff *skb, int dir) { - u8 *bend, *buf; + u_char *bend, *buf; char *dp; unsigned char pd, cr_l, cr, mt; unsigned char sapi, tei, ftyp; - u_int i, cset = 0, cs_old = 0, cs_fest = 0; + int i, cset = 0, cs_old = 0, cs_fest = 0; int size, finish = 0; if (skb->len < 3) diff -Nru a/drivers/isdn/hisax/rawhdlc.c b/drivers/isdn/hisax/rawhdlc.c --- a/drivers/isdn/hisax/rawhdlc.c Thu Feb 19 23:44:23 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,543 +0,0 @@ -/* $Id: rawhdlc.c,v 1.5.6.2 2001/09/23 22:24:51 kai Exp $ - * - * support routines for cards that don't support HDLC - * - * Author Brent Baccala - * Copyright by Karsten Keil - * by Brent Baccala - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * - * Some passive ISDN cards, such as the Traverse NETJet and the AMD 7930, - * don't perform HDLC encapsulation over the B channel. Drivers for - * such cards use support routines in this file to perform B channel HDLC. - * - * Bit-synchronous HDLC encapsulation is a means of encapsulating packets - * over a continuously transmitting serial communications link. - * It looks like this: - * - * 11111111101111110...........0111111011111111111 - * iiiiiiiiiffffffffdddddddddddffffffffiiiiiiiiiii - * - * i = idle f = flag d = data - * - * When idle, the channel sends a continuous string of ones (mark - * idle; illustrated), or a continuous string of flag characters (flag - * idle). The beginning of a data frame is marked by a flag character - * (01111110), then comes the actual data, followed by another flag - * character, after which another frame may be sent immediately (a - * single flag may serve as both the end of one frame and the start of - * the next), or the link may return to idle. Obviously, the flag - * character can not appear anywhere in the data (or a false - * end-of-frame would occur), so the transmitter performs - * "bit-stuffing" - inserting a zero bit after every five one bits, - * irregardless of the original bit after the five ones. Byte - * ordering is irrelevant at this point - the data is treated as a - * string of bits, not bytes. Since no more than 5 ones may now occur - * in a row, the flag sequence, with its 6 ones, is unique. - * - * Upon reception, a zero bit that occur after 5 one bits is simply - * discarded. A series of 6 one bits is end-of-frame, and a series of - * 7 one bits is an abort. Once bit-stuffing has been corrected for, - * an integer number of bytes should now be present. The last two - * of these bytes form the Frame Check Sequence, a CRC that is verified - * and then discarded. Note that bit-stuffing is performed on the FCS - * just as if it were regular data. - * - * - * - * int make_raw_hdlc_data(u8 *src, u_int slen, - * u8 *dst, u_int dsize) - * - * Used for transmission. Copies slen bytes from src to dst, performing - * HDLC encapsulation (flag bytes, bit-stuffing, CRC) in the process. - * dsize is size of destination buffer, and should be at least - * ((6*slen)/5)+5 bytes to ensure adequate space will be available. - * Function returns length (in bytes) of valid destination buffer, or - * 0 upon destination overflow. - * - * void init_hdlc_state(struct hdlc_state *stateptr, int mode) - * - * Initializes hdlc_state structure before first call to read_raw_hdlc_data - * - * mode = 0: Sane mode - * mode = 1/2: - * Insane mode; NETJet use a shared unsigned int memory block ( - * with busmaster DMA), the bit pattern of every word is - * <8 B1> <8 B2> <8 Mon> <2 D> <4 C/I> - * according to Siemens IOM-2 interface, so we have to handle - * the src buffer as unsigned int and have to shift/mask the - * B-channel bytes. - * mode 1 -> B1 mode 2 -> B2 data is used - * - * int read_raw_hdlc_data(struct hdlc_state *saved_state, - * u8 *src, u_int slen, - * u8 *dst, u_int dsize) - * - * Used for reception. Scans source buffer bit-by-bit looking for - * valid HDLC frames, which are copied to destination buffer. HDLC - * state information is stored in a structure, which allows this - * function to process frames spread across several blocks of raw - * HDLC data. Part of the state information is bit offsets into - * the source and destination buffers. - * - * A return value >0 indicates the length of a valid frame, now - * stored in the destination buffer. In this case, the source - * buffer might not be completely processed, so this function should - * be called again with the same source buffer, possibly with a - * different destination buffer. - * - * A return value of zero indicates that the source buffer was - * completely processed without finding a valid end-of-packet; - * however, we might be in the middle of packet reception, so - * the function should be called again with the next block of - * raw HDLC data and the same destination buffer. It is NOT - * permitted to change the destination buffer in this case, - * since data may already have begun to be stored there. - * - * A return value of -1 indicates some kind of error - destination - * buffer overflow, CRC check failed, frame not a multiple of 8 - * bits. Destination buffer probably contains invalid data, which - * should be discarded. Call function again with same source buffer - * and a new (or same) destination buffer. - * - * Suggested calling sequence: - * - * init_hdlc_state(...); - * for (EACH_RAW_DATA_BLOCK) { - * while (len = read_raw_hdlc_data(...)) { - * if (len == -1) DISCARD_FRAME; - * else PROCESS_FRAME; - * } - * } - * - * - * Test the code in this file as follows: - * gcc -DDEBUGME -o rawhdlctest rawhdlc.c - * ./rawhdlctest < rawdata - * - * The file "rawdata" can be easily generated from a HISAX B-channel - * hex dump (CF CF CF 02 ...) using the following perl script: - * - * while(<>) { - * @hexlist = split ' '; - * while ($hexstr = shift(@hexlist)) { - * printf "%c", hex($hexstr); - * } - * } - * - */ - -#ifdef DEBUGME -#include -#endif - -#include -#include -#include "rawhdlc.h" - -/* There's actually an identical copy of this table in the PPP code - * (ppp_crc16_table), but I don't want this code dependent on PPP - */ - -// static -__u16 fcstab[256] = -{ - 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, - 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, - 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, - 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, - 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, - 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, - 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, - 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, - 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, - 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, - 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, - 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, - 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, - 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, - 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, - 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, - 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, - 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, - 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, - 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, - 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, - 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, - 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, - 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, - 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, - 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, - 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, - 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, - 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, - 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, - 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, - 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 -}; - -#define HDLC_ZERO_SEARCH 0 -#define HDLC_FLAG_SEARCH 1 -#define HDLC_FLAG_FOUND 2 -#define HDLC_FRAME_FOUND 3 -#define HDLC_NULL 4 -#define HDLC_PART 5 -#define HDLC_FULL 6 - -#define HDLC_FLAG_VALUE 0x7e - - -#define MAKE_RAW_BYTE for (j=0; j<8; j++) { \ - bitcnt++;\ - out_val >>= 1;\ - if (val & 1) {\ - s_one++;\ - out_val |= 0x80;\ - } else {\ - s_one = 0;\ - out_val &= 0x7f;\ - }\ - if (bitcnt==8) {\ - if (d_cnt == dsize) return 0;\ - dst[d_cnt++] = out_val;\ - bitcnt = 0;\ - }\ - if (s_one == 5) {\ - out_val >>= 1;\ - out_val &= 0x7f;\ - bitcnt++;\ - s_one = 0;\ - }\ - if (bitcnt==8) {\ - if (d_cnt == dsize) return 0;\ - dst[d_cnt++] = out_val;\ - bitcnt = 0;\ - }\ - val >>= 1;\ - } - -/* Optimization suggestion: If needed, this function could be - * dramatically sped up using a state machine. Each state would - * correspond to having seen N one bits, and being offset M bits into - * the current output byte. N ranges from 0 to 4, M from 0 to 7, so - * we need 5*8 = 35 states. Each state would have a table with 256 - * entries, one for each input character. Each entry would contain - * three output characters, an output state, an a byte increment - * that's either 1 or 2. All this could fit in four bytes; so we need - * 4 bytes * 256 characters = 1 KB for each state (35 KB total). Zero - * the output buffer before you start. For each character in your - * input, you look it up in the current state's table and get three - * bytes to be or'ed into the output at the current byte offset, and - * an byte increment to move your pointer forward. A simple Perl - * script could generate the tables. Given HDLC semantics, probably - * would be better to set output to all 1s, then use ands instead of ors. - * A smaller state machine could operate on nibbles instead of bytes. - * A state machine for 32-bit architectures could use word offsets - * instead of byte offsets, requiring 5*32 = 160 states; probably - * best to work on nibbles in such a case. - */ - - -int make_raw_hdlc_data(u8 *src, u_int slen, u8 *dst, u_int dsize) -{ - register u_int i,d_cnt=0; - register u8 j; - register u8 val; - register u8 s_one = 0; - register u8 out_val = 0; - register u8 bitcnt = 0; - u_int fcs; - - - dst[d_cnt++] = HDLC_FLAG_VALUE; - fcs = PPP_INITFCS; - for (i=0; i>8) & 0xff; - MAKE_RAW_BYTE; - val = HDLC_FLAG_VALUE; - for (j=0; j<8; j++) { - bitcnt++; - out_val >>= 1; - if (val & 1) - out_val |= 0x80; - else - out_val &= 0x7f; - if (bitcnt==8) { - if (d_cnt == dsize) return 0; - dst[d_cnt++] = out_val; - bitcnt = 0; - } - val >>= 1; - } - if (bitcnt) { - while (8>bitcnt++) { - out_val >>= 1; - out_val |= 0x80; - } - if (d_cnt == dsize) return 0; - dst[d_cnt++] = out_val; - } - - return d_cnt; -} - -void init_hdlc_state(struct hdlc_state *stateptr, int mode) -{ - stateptr->state = HDLC_ZERO_SEARCH; - stateptr->r_one = 0; - stateptr->r_val = 0; - stateptr->o_bitcnt = 0; - stateptr->i_bitcnt = 0; - stateptr->insane_mode = mode; -} - -/* Optimization suggestion: A similar state machine could surely - * be developed for this function as well. - */ - -int read_raw_hdlc_data(struct hdlc_state *saved_state, - u8 *src, u_int slen, u8 *dst, u_int dsize) -{ - int retval=0; - register u8 val; - register u8 state = saved_state->state; - register u8 r_one = saved_state->r_one; - register u8 r_val = saved_state->r_val; - register u_int o_bitcnt = saved_state->o_bitcnt; - register u_int i_bitcnt = saved_state->i_bitcnt; - register u_int fcs = saved_state->fcs; - register u_int *isrc = (u_int *) src; - - /* Use i_bitcnt (bit offset into source buffer) to reload "val" - * in case we're starting up again partway through a source buffer - */ - - if ((i_bitcnt >> 3) < slen) { - if (saved_state->insane_mode==1) { - val = isrc[(i_bitcnt >> 3)] & 0xff; - } else if (saved_state->insane_mode==2) { - val = (isrc[i_bitcnt >> 3] >>8) & 0xff; - } else { - val = src[i_bitcnt >> 3]; - } - val >>= i_bitcnt & 7; - } - - /* One bit per loop. Keep going until we've got something to - * report (retval != 0), or we exhaust the source buffer - */ - - while ((retval == 0) && ((i_bitcnt >> 3) < slen)) { - if ((i_bitcnt & 7) == 0) { - if (saved_state->insane_mode==1) { - val = isrc[(i_bitcnt >> 3)] & 0xff; - } else if (saved_state->insane_mode==2) { - val = (isrc[i_bitcnt >> 3] >>8) & 0xff; - } else { - val = src[i_bitcnt >> 3]; - } -#ifdef DEBUGME - printf("Input byte %d: 0x%2x\n", i_bitcnt>>3, val); -#endif - if (val == 0xff) { - state = HDLC_ZERO_SEARCH; - o_bitcnt = 0; - r_one = 0; - i_bitcnt += 8; - continue; - } - } - -#ifdef DEBUGME - /* printf("Data bit=%d (%d/%d)\n", val&1, i_bitcnt>>3, i_bitcnt&7);*/ -#endif - - if (state == HDLC_ZERO_SEARCH) { - if (val & 1) { - r_one++; - } else { - r_one=0; - state= HDLC_FLAG_SEARCH; - } - } else if (state == HDLC_FLAG_SEARCH) { - if (val & 1) { - r_one++; - if (r_one>6) { - state=HDLC_ZERO_SEARCH; - } - } else { - if (r_one==6) { - o_bitcnt=0; - r_val=0; - state=HDLC_FLAG_FOUND; - } - r_one=0; - } - } else if (state == HDLC_FLAG_FOUND) { - if (val & 1) { - r_one++; - if (r_one>6) { - state=HDLC_ZERO_SEARCH; - } else { - r_val >>= 1; - r_val |= 0x80; - o_bitcnt++; - } - } else { - if (r_one==6) { - o_bitcnt=0; - r_val=0; - r_one=0; - i_bitcnt++; - val >>= 1; - continue; - } else if (r_one!=5) { - r_val >>= 1; - r_val &= 0x7f; - o_bitcnt++; - } - r_one=0; - } - if ((state != HDLC_ZERO_SEARCH) && - !(o_bitcnt & 7)) { -#ifdef DEBUGME - printf("HDLC_FRAME_FOUND at i_bitcnt:%d\n",i_bitcnt); -#endif - state=HDLC_FRAME_FOUND; - fcs = PPP_INITFCS; - dst[0] = r_val; - fcs = PPP_FCS (fcs, r_val); - } - } else if (state == HDLC_FRAME_FOUND) { - if (val & 1) { - r_one++; - if (r_one>6) { - state=HDLC_ZERO_SEARCH; - o_bitcnt=0; - } else { - r_val >>= 1; - r_val |= 0x80; - o_bitcnt++; - } - } else { - if (r_one==6) { - r_val=0; - r_one=0; - o_bitcnt++; - if (o_bitcnt & 7) { - /* Alignment error */ -#ifdef DEBUGME - printf("Alignment error\n"); -#endif - state=HDLC_FLAG_SEARCH; - retval = -1; - } else if (fcs==PPP_GOODFCS) { - /* Valid frame */ - state=HDLC_FLAG_FOUND; - retval = (o_bitcnt>>3)-3; - } else { - /* CRC error */ -#ifdef DEBUGME - printf("CRC error; fcs was 0x%x, should have been 0x%x\n", fcs, PPP_GOODFCS); -#endif - state=HDLC_FLAG_FOUND; - retval = -1; - } - } else if (r_one==5) { - r_one=0; - i_bitcnt++; - val >>= 1; - continue; - } else { - r_val >>= 1; - r_val &= 0x7f; - o_bitcnt++; - } - r_one=0; - } - if ((state == HDLC_FRAME_FOUND) && - !(o_bitcnt & 7)) { - if ((o_bitcnt>>3)>=dsize) { - /* Buffer overflow error */ -#ifdef DEBUGME - printf("Buffer overflow error\n"); -#endif - r_val=0; - state=HDLC_FLAG_SEARCH; - retval = -1; - } else { - dst[(o_bitcnt>>3)-1] = r_val; - fcs = PPP_FCS (fcs, r_val); -#ifdef DEBUGME - printf("Output byte %d: 0x%02x; FCS 0x%04x\n", (o_bitcnt>>3)-1, r_val, fcs); -#endif - } - } - } - i_bitcnt ++; - val >>= 1; - } - - /* We exhausted the source buffer before anything else happened - * (retval==0). Reset i_bitcnt in expectation of a new source - * buffer. Other, we either had an error or a valid frame, so - * reset o_bitcnt in expectation of a new destination buffer. - */ - - if (retval == 0) { - i_bitcnt = 0; - } else { - o_bitcnt = 0; - } - - saved_state->state = state; - saved_state->r_one = r_one; - saved_state->r_val = r_val; - saved_state->fcs = fcs; - saved_state->o_bitcnt = o_bitcnt; - saved_state->i_bitcnt = i_bitcnt; - - return (retval); -} - - - -#ifdef DEBUGME - -char buffer[1024]; -char obuffer[1024]; - -main() -{ - int buflen=0; - int len; - struct hdlc_state hdlc_state; - - while((buffer[buflen] = getc(stdin)) != EOF && buflen<1024) buflen++; - - printf("buflen = %d\n", buflen); - - init_hdlc_state(&hdlc_state, 0); - - while (len = read_raw_hdlc_data(&hdlc_state,buffer,buflen,obuffer,1024)) { - if (len == -1) printf("Error @ byte %d/bit %d\n", - hdlc_state.i_bitcnt>>3, hdlc_state.i_bitcnt & 7); - else { - printf("Frame received: len %d\n", len); - } - } - - printf("Done\n"); -} - -#endif diff -Nru a/drivers/isdn/hisax/rawhdlc.h b/drivers/isdn/hisax/rawhdlc.h --- a/drivers/isdn/hisax/rawhdlc.h Thu Feb 19 23:44:27 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,28 +0,0 @@ -/* $Id: rawhdlc.h,v 1.3.6.2 2001/09/23 22:24:51 kai Exp $ - * - * Author Brent Baccala - * Copyright by Brent Baccala - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - */ - -#ifndef RAWHDLC_H -struct hdlc_state { - char insane_mode; - u8 state; - u8 r_one; - u8 r_val; - u_int o_bitcnt; - u_int i_bitcnt; - u_int fcs; -}; - - -int make_raw_hdlc_data(u8 *src, u_int slen, u8 *dst, u_int dsize); -void init_hdlc_state(struct hdlc_state *stateptr, int mode); -int read_raw_hdlc_data(struct hdlc_state *saved_state, - u8 *src, u_int slen, u8 *dst, u_int dsize); -#define RAWHDLC_H -#endif diff -Nru a/drivers/isdn/hisax/s0box.c b/drivers/isdn/hisax/s0box.c --- a/drivers/isdn/hisax/s0box.c Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/s0box.c Thu Feb 19 23:44:23 2004 @@ -1,4 +1,4 @@ -/* $Id: s0box.c,v 2.4.6.2 2001/09/23 22:24:51 kai Exp $ +/* $Id: s0box.c,v 2.6.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for Creatix S0BOX * @@ -17,16 +17,10 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *s0box_revision = "$Revision: 2.4.6.2 $"; -static spinlock_t s0box_lock = SPIN_LOCK_UNLOCKED; +const char *s0box_revision = "$Revision: 2.6.2.4 $"; static inline void -writereg(struct IsdnCardState *cs, int addr, u8 off, u8 val) -{ - unsigned long flags; - unsigned long padr = cs->hw.teles3.cfg_reg; - - spin_lock_irqsave(&s0box_lock, flags); +writereg(unsigned int padr, signed int addr, u_char off, u_char val) { outb_p(0x1c,padr+2); outb_p(0x14,padr+2); outb_p((addr+off)&0x7f,padr); @@ -35,21 +29,16 @@ outb_p(0x17,padr+2); outb_p(0x14,padr+2); outb_p(0x1c,padr+2); - spin_unlock_irqrestore(&s0box_lock, flags); } -static u8 nibtab[] = { 1, 9, 5, 0xd, 3, 0xb, 7, 0xf, +static u_char nibtab[] = { 1, 9, 5, 0xd, 3, 0xb, 7, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 4, 0xc, 2, 0xa, 6, 0xe } ; -static inline u8 -readreg(struct IsdnCardState *cs, int addr, u8 off) -{ - u8 n1, n2; - unsigned long flags; - unsigned long padr = cs->hw.teles3.cfg_reg; +static inline u_char +readreg(unsigned int padr, signed int addr, u_char off) { + register u_char n1, n2; - spin_lock_irqsave(&s0box_lock, flags); outb_p(0x1c,padr+2); outb_p(0x14,padr+2); outb_p((addr+off)|0x80,padr); @@ -60,16 +49,14 @@ n2 = (inb_p(padr+1) >> 3) & 0x17; outb_p(0x14,padr+2); outb_p(0x1c,padr+2); - spin_unlock_irqrestore(&s0box_lock, flags); return nibtab[n1] | (nibtab[n2] << 4); } static inline void -read_fifo(struct IsdnCardState *cs, signed int adr, u8 * data, int size) +read_fifo(unsigned int padr, signed int adr, u_char * data, int size) { int i; - u8 n1, n2; - unsigned long padr = cs->hw.teles3.cfg_reg; + register u_char n1, n2; outb_p(0x1c, padr+2); outb_p(0x14, padr+2); @@ -84,14 +71,13 @@ } outb_p(0x14,padr+2); outb_p(0x1c,padr+2); + return; } static inline void -write_fifo(struct IsdnCardState *cs, signed int adr, u8 * data, int size) +write_fifo(unsigned int padr, signed int adr, u_char * data, int size) { int i; - unsigned long padr = cs->hw.teles3.cfg_reg; - outb_p(0x1c, padr+2); outb_p(0x14, padr+2); outb_p(adr&0x7f, padr); @@ -102,79 +88,140 @@ } outb_p(0x14,padr+2); outb_p(0x1c,padr+2); + return; } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.teles3.isac, offset); + return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.teles3.isac, offset, value); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - read_fifo(cs, cs->hw.teles3.isacfifo, data, size); + read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - write_fifo(cs, cs->hw.teles3.isacfifo, data, size); + write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.isacfifo, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - return readreg(cs, cs->hw.teles3.hscx[hscx], offset); + return (readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - writereg(cs, cs->hw.teles3.hscx[hscx], offset, value); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[hscx], offset, value); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - read_fifo(cs, cs->hw.teles3.hscxfifo[hscx], data, size); +/* + * fast interrupt HSCX stuff goes here + */ + +#define READHSCX(cs, nr, reg) readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[nr], reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscxfifo[nr], ptr, cnt) + +#include "hscx_irq.c" + +static irqreturn_t +s0box_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ +#define MAXCOUNT 5 + struct IsdnCardState *cs = dev_id; + u_char val; + u_long flags; + int count = 0; + + spin_lock_irqsave(&cs->lock, flags); + val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + count++; + val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_ISTA); + if (val && count < MAXCOUNT) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_ISTA); + if (val && count < MAXCOUNT) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + if (count >= MAXCOUNT) + printk(KERN_WARNING "S0Box: more than %d loops in s0box_interrupt\n", count); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.isac, ISAC_MASK, 0x0); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[0], HSCX_MASK, 0x0); + writereg(cs->hw.teles3.cfg_reg, cs->hw.teles3.hscx[1], HSCX_MASK, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} + +void +release_io_s0box(struct IsdnCardState *cs) +{ + release_region(cs->hw.teles3.cfg_reg, 8); +} + +static int +S0Box_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + u_long flags; + + switch (mt) { + case CARD_RESET: + break; + case CARD_RELEASE: + release_io_s0box(cs); + break; + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + break; + case CARD_TEST: + break; + } + return(0); } -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +int __init +setup_s0box(struct IsdnCard *card) { - write_fifo(cs, cs->hw.teles3.hscxfifo[hscx], data, size); -} + struct IsdnCardState *cs = card->cs; + char tmp[64]; -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static struct card_ops s0box_ops = { - .init = inithscxisac, - .release = hisax_release_resources, - .irq_func = hscxisac_irq, -}; + strcpy(tmp, s0box_revision); + printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_S0BOX) + return (0); -static int __init -s0box_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ cs->hw.teles3.cfg_reg = card->para[1]; cs->hw.teles3.hscx[0] = -0x20; cs->hw.teles3.hscx[1] = 0x0; @@ -183,32 +230,37 @@ cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e; cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e; cs->irq = card->para[0]; - if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "S0Box parallel I/O")) - goto err; + if (!request_region(cs->hw.teles3.cfg_reg,8, "S0Box parallel I/O")) { + printk(KERN_WARNING + "HiSax: %s ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.teles3.cfg_reg, + cs->hw.teles3.cfg_reg + 7); + return 0; + } printk(KERN_INFO - "HiSax: %s config irq:%d isac:0x%x cfg:0x%x\n", - CardType[cs->typ], cs->irq, - cs->hw.teles3.isac, cs->hw.teles3.cfg_reg); + "HiSax: %s config irq:%d isac:0x%x cfg:0x%x\n", + CardType[cs->typ], cs->irq, + cs->hw.teles3.isac, cs->hw.teles3.cfg_reg); printk(KERN_INFO - "HiSax: hscx A:0x%x hscx B:0x%x\n", - cs->hw.teles3.hscx[0], cs->hw.teles3.hscx[1]); - cs->card_ops = &s0box_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -int __init -setup_s0box(struct IsdnCard *card) -{ - char tmp[64]; - - strcpy(tmp, s0box_revision); - printk(KERN_INFO "HiSax: S0Box IO driver Rev. %s\n", HiSax_getrev(tmp)); - if (s0box_probe(card->cs, card)) - return 0; - return 1; + "HiSax: hscx A:0x%x hscx B:0x%x\n", + cs->hw.teles3.hscx[0], cs->hw.teles3.hscx[1]); + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &S0Box_card_msg; + cs->irq_func = &s0box_interrupt; + ISACVersion(cs, "S0Box:"); + if (HscxVersion(cs, "S0Box:")) { + printk(KERN_WARNING + "S0Box: wrong HSCX versions check IO address\n"); + release_io_s0box(cs); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/saphir.c b/drivers/isdn/hisax/saphir.c --- a/drivers/isdn/hisax/saphir.c Thu Feb 19 23:44:22 2004 +++ b/drivers/isdn/hisax/saphir.c Thu Feb 19 23:44:22 2004 @@ -1,4 +1,4 @@ -/* $Id: saphir.c,v 1.8.6.2 2001/09/23 22:24:51 kai Exp $ +/* $Id: saphir.c,v 1.10.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for HST Saphir 1 * @@ -19,8 +19,7 @@ #include "isdnl1.h" extern const char *CardType[]; -static char *saphir_rev = "$Revision: 1.8.6.2 $"; -static spinlock_t saphir_lock = SPIN_LOCK_UNLOCKED; +static char *saphir_rev = "$Revision: 1.10.2.4 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -32,138 +31,160 @@ #define SPARE_REG 4 #define RESET_REG 5 -static inline u8 -readreg(struct IsdnCardState *cs, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&saphir_lock, flags); - byteout(cs->hw.saphir.ale, off); + byteout(ale, off); ret = bytein(adr); - spin_unlock_irqrestore(&saphir_lock, flags); - return ret; + return (ret); } static inline void -writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; - - spin_lock_irqsave(&saphir_lock, flags); - byteout(cs->hw.saphir.ale, off); - byteout(adr, data); - spin_unlock_irqrestore(&saphir_lock, flags); + byteout(ale, off); + insb(adr, data, size); } + static inline void -readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 *data, int size) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { - byteout(cs->hw.saphir.ale, off); - insb(adr, data, size); + byteout(ale, off); + byteout(adr, data); } static inline void -writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 *data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - byteout(cs->hw.saphir.ale, off); + byteout(ale, off); outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.saphir.isac, offset); + return (readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.saphir.isac, offset, value); + writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - readfifo(cs, cs->hw.saphir.isac, 0, data, size); + readfifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs, cs->hw.saphir.isac, 0, data, size); + writefifo(cs->hw.saphir.ale, cs->hw.saphir.isac, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - return readreg(cs, cs->hw.saphir.hscx, offset + (hscx ? 0x40 : 0)); + return (readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, + offset + (hscx ? 0x40 : 0))); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - writereg(cs, cs->hw.saphir.hscx, offset + (hscx ? 0x40 : 0), value); + writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, + offset + (hscx ? 0x40 : 0), value); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - readfifo(cs, cs->hw.saphir.hscx, hscx ? 0x40 : 0, data, size); -} +#define READHSCX(cs, nr, reg) readreg(cs->hw.saphir.ale, \ + cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.saphir.ale, \ + cs->hw.saphir.hscx, reg + (nr ? 0x40 : 0), data) -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - writefifo(cs, cs->hw.saphir.hscx, hscx ? 0x40 : 0, data, size); -} +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.saphir.ale, \ + cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.saphir.ale, \ + cs->hw.saphir.hscx, (nr ? 0x40 : 0), ptr, cnt) -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; +#include "hscx_irq.c" static irqreturn_t saphir_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - irqreturn_t ret; + u_char val; + u_long flags; - ret = hscxisac_irq(intno, dev_id, regs); - mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ); - return ret; + spin_lock_irqsave(&cs->lock, flags); + val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = readreg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_ISTA + 0x40); + if (val) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_ISTA); + if (val) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + /* Watchdog */ + if (cs->hw.saphir.timer.function) + mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ); + else + printk(KERN_WARNING "saphir: Spurious timer!\n"); + writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.saphir.ale, cs->hw.saphir.isac, ISAC_MASK, 0); + writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK, 0); + writereg(cs->hw.saphir.ale, cs->hw.saphir.hscx, HSCX_MASK + 0x40, 0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; } static void SaphirWatchDog(struct IsdnCardState *cs) { + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); /* 5 sec WatchDog, so read at least every 4 sec */ - isac_read(cs, ISAC_RBCH); + cs->readisac(cs, ISAC_RBCH); + spin_unlock_irqrestore(&cs->lock, flags); mod_timer(&cs->hw.saphir.timer, jiffies+1*HZ); } -static void -saphir_release(struct IsdnCardState *cs) +void +release_io_saphir(struct IsdnCardState *cs) { byteout(cs->hw.saphir.cfg_reg + IRQ_REG, 0xff); - del_timer_sync(&cs->hw.saphir.timer); + del_timer(&cs->hw.saphir.timer); cs->hw.saphir.timer.function = NULL; - hisax_release_resources(cs); + if (cs->hw.saphir.cfg_reg) + release_region(cs->hw.saphir.cfg_reg, 6); } static int saphir_reset(struct IsdnCardState *cs) { - u8 irq_val; + u_char irq_val; switch(cs->irq) { case 5: irq_val = 0; @@ -186,66 +207,94 @@ } byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val); byteout(cs->hw.saphir.cfg_reg + RESET_REG, 1); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30*HZ)/1000); /* Timeout 30ms */ + mdelay(10); byteout(cs->hw.saphir.cfg_reg + RESET_REG, 0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30*HZ)/1000); /* Timeout 30ms */ + mdelay(10); byteout(cs->hw.saphir.cfg_reg + IRQ_REG, irq_val); byteout(cs->hw.saphir.cfg_reg + SPARE_REG, 0x02); return (0); } -static struct card_ops saphir_ops = { - .init = inithscxisac, - .reset = saphir_reset, - .release = saphir_release, - .irq_func = saphir_interrupt, -}; +static int +saphir_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + u_long flags; + + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + saphir_reset(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_saphir(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); +} -static int __init -saphir_probe(struct IsdnCardState *cs, struct IsdnCard *card) + +int __init +setup_saphir(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; + char tmp[64]; + + strcpy(tmp, saphir_rev); + printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_HSTSAPHIR) + return (0); + + /* IO-Ports */ cs->hw.saphir.cfg_reg = card->para[1]; cs->hw.saphir.isac = card->para[1] + ISAC_DATA; cs->hw.saphir.hscx = card->para[1] + HSCX_DATA; cs->hw.saphir.ale = card->para[1] + ADDRESS_REG; cs->irq = card->para[0]; - - if (!request_io(&cs->rs, cs->hw.saphir.cfg_reg, 6, "saphir")) - goto err; + if (!request_region(cs->hw.saphir.cfg_reg, 6, "saphir")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.saphir.cfg_reg, + cs->hw.saphir.cfg_reg + 5); + return (0); + } printk(KERN_INFO "HiSax: %s config irq:%d io:0x%X\n", - CardType[cs->typ], cs->irq, cs->hw.saphir.cfg_reg); + CardType[cs->typ], cs->irq, cs->hw.saphir.cfg_reg); - if (saphir_reset(cs)) - goto err; - - cs->card_ops = &saphir_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - - init_timer(&cs->hw.saphir.timer); + setup_isac(cs); cs->hw.saphir.timer.function = (void *) SaphirWatchDog; cs->hw.saphir.timer.data = (long) cs; + init_timer(&cs->hw.saphir.timer); cs->hw.saphir.timer.expires = jiffies + 4*HZ; add_timer(&cs->hw.saphir.timer); - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -int __init -setup_saphir(struct IsdnCard *card) -{ - char tmp[64]; - - strcpy(tmp, saphir_rev); - printk(KERN_INFO "HiSax: HST Saphir driver Rev. %s\n", - HiSax_getrev(tmp)); - - if (saphir_probe(card->cs, card) < 0) - return 0; - return 1; + if (saphir_reset(cs)) { + release_io_saphir(cs); + return (0); + } + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &saphir_card_msg; + cs->irq_func = &saphir_interrupt; + ISACVersion(cs, "saphir:"); + if (HscxVersion(cs, "saphir:")) { + printk(KERN_WARNING + "saphir: wrong HSCX versions check IO address\n"); + release_io_saphir(cs); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/sedlbauer.c b/drivers/isdn/hisax/sedlbauer.c --- a/drivers/isdn/hisax/sedlbauer.c Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/hisax/sedlbauer.c Thu Feb 19 23:44:28 2004 @@ -1,4 +1,4 @@ -/* $Id: sedlbauer.c,v 1.25.6.6 2001/09/23 22:24:51 kai Exp $ +/* $Id: sedlbauer.c,v 1.34.2.6 2004/01/24 20:47:24 keil Exp $ * * low level stuff for Sedlbauer cards * includes support for the Sedlbauer speed star (speed star II), @@ -50,16 +50,16 @@ #include extern const char *CardType[]; -static spinlock_t sedlbauer_lock = SPIN_LOCK_UNLOCKED; -const char *Sedlbauer_revision = "$Revision: 1.25.6.6 $"; +const char *Sedlbauer_revision = "$Revision: 1.34.2.6 $"; const char *Sedlbauer_Types[] = {"None", "speed card/win", "speed star", "speed fax+", "speed win II / ISDN PC/104", "speed star II", "speed pci", - "speed fax+ pyramid", "speed fax+ pci"}; + "speed fax+ pyramid", "speed fax+ pci", "HST Saphir III"}; #define PCI_SUBVENDOR_SPEEDFAX_PYRAMID 0x51 +#define PCI_SUBVENDOR_HST_SAPHIR3 0x52 #define PCI_SUBVENDOR_SEDLBAUER_PCI 0x53 #define PCI_SUBVENDOR_SPEEDFAX_PCI 0x54 #define PCI_SUB_ID_SEDLBAUER 0x01 @@ -72,7 +72,9 @@ #define SEDL_SPEED_PCI 6 #define SEDL_SPEEDFAX_PYRAMID 7 #define SEDL_SPEEDFAX_PCI 8 +#define HST_SAPHIR3 9 +#define SEDL_CHIP_TEST 0 #define SEDL_CHIP_ISAC_HSCX 1 #define SEDL_CHIP_ISAC_ISAR 2 #define SEDL_CHIP_IPAC 3 @@ -117,209 +119,264 @@ #define SEDL_RESET 0x3 /* same as DOS driver */ -static inline u8 -readreg(struct IsdnCardState *cs, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - u8 ret; - unsigned long flags; + register u_char ret; - spin_lock_irqsave(&sedlbauer_lock, flags); - byteout(cs->hw.sedl.adr, off); + byteout(ale, off); ret = bytein(adr); - spin_unlock_irqrestore(&sedlbauer_lock, flags); - return ret; + return (ret); } static inline void -readfifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - unsigned long flags; - - spin_lock_irqsave(&sedlbauer_lock, flags); - byteout(cs->hw.sedl.adr, off); + byteout(ale, off); insb(adr, data, size); - spin_unlock_irqrestore(&sedlbauer_lock, flags); } static inline void -writereg(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 data) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { - byteout(cs->hw.sedl.adr, off); + byteout(ale, off); byteout(adr, data); } static inline void -writefifo(struct IsdnCardState *cs, unsigned int adr, u8 off, u8 * data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - byteout(cs->hw.sedl.adr, off); + byteout(ale, off); outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.sedl.isac, offset); + return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.sedl.isac, offset, value); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - readfifo(cs, cs->hw.sedl.isac, 0, data, size); + readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs, cs->hw.sedl.isac, 0, data, size); + writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadISAC_IPAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs, cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0)); + return (readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteISAC_IPAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writereg(cs, cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0), value); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, offset|0x80, value); } static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +ReadISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - readfifo(cs, cs->hw.sedl.hscx, hscx ? 0x40 : 0, data, size); + readfifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size); } static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +WriteISACfifo_IPAC(struct IsdnCardState *cs, u_char * data, int size) { - writefifo(cs, cs->hw.sedl.hscx, hscx ? 0x40 : 0, data, size); + writefifo(cs->hw.sedl.adr, cs->hw.sedl.isac, 0x80, data, size); } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - -static inline u8 -ipac_read(struct IsdnCardState *cs, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - return readreg(cs, cs->hw.sedl.isac, offset); + return (readreg(cs->hw.sedl.adr, + cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0))); } -static inline void -ipac_write(struct IsdnCardState *cs, u8 offset, u8 value) -{ - writereg(cs, cs->hw.sedl.isac, offset, value); -} - -static inline void -ipac_readfifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) -{ - readfifo(cs, cs->hw.sedl.isac, offset, data, size); -} - -static inline void -ipac_writefifo(struct IsdnCardState *cs, u8 offset, u8 *data, int size) +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { - writefifo(cs, cs->hw.sedl.isac, offset, data, size); + writereg(cs->hw.sedl.adr, + cs->hw.sedl.hscx, offset + (hscx ? 0x40 : 0), value); } -/* This will generate ipac_dc_ops and ipac_bc_ops using the functions - * above */ - -BUILD_IPAC_OPS(ipac); - - /* ISAR access routines * mode = 0 access with IRQ on * mode = 1 access with IRQ off * mode = 2 access with IRQ off and using last offset */ -static u8 -isar_read(struct IsdnCardState *cs, int mode, u8 offset) +static u_char +ReadISAR(struct IsdnCardState *cs, int mode, u_char offset) { if (mode == 0) - return readreg(cs, cs->hw.sedl.hscx, offset); - - if (mode == 1) + return (readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset)); + else if (mode == 1) byteout(cs->hw.sedl.adr, offset); - - return bytein(cs->hw.sedl.hscx); + return(bytein(cs->hw.sedl.hscx)); } static void -isar_write(struct IsdnCardState *cs, int mode, u8 offset, u8 value) +WriteISAR(struct IsdnCardState *cs, int mode, u_char offset, u_char value) { if (mode == 0) - return writereg(cs, cs->hw.sedl.hscx, offset, value); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, offset, value); + else { + if (mode == 1) + byteout(cs->hw.sedl.adr, offset); + byteout(cs->hw.sedl.hscx, value); + } +} - if (mode == 1) - byteout(cs->hw.sedl.adr, offset); +/* + * fast interrupt HSCX stuff goes here + */ - byteout(cs->hw.sedl.hscx, value); -} +#define READHSCX(cs, nr, reg) readreg(cs->hw.sedl.adr, \ + cs->hw.sedl.hscx, reg + (nr ? 0x40 : 0)) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.sedl.adr, \ + cs->hw.sedl.hscx, reg + (nr ? 0x40 : 0), data) -static struct bc_hw_ops isar_ops = { - .read_reg = isar_read, - .write_reg = isar_write, -}; +#define READHSCXFIFO(cs, nr, ptr, cnt) readfifo(cs->hw.sedl.adr, \ + cs->hw.sedl.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) writefifo(cs->hw.sedl.adr, \ + cs->hw.sedl.hscx, (nr ? 0x40 : 0), ptr, cnt) + +#include "hscx_irq.c" static irqreturn_t sedlbauer_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; + u_char val; + u_long flags; + spin_lock_irqsave(&cs->lock, flags); if ((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && (*cs->busy_flag == 1)) { /* The card tends to generate interrupts while being removed causing us to just crash the kernel. bad. */ + spin_unlock_irqrestore(&cs->lock, flags); printk(KERN_WARNING "Sedlbauer: card not available!\n"); return IRQ_NONE; } - return hscxisac_irq(intno, dev_id, regs); + + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40); + if (val) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA); + if (val) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0xFF); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0xFF); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK, 0x0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_MASK + 0x40, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} + +static irqreturn_t +sedlbauer_interrupt_ipac(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char ista, val, icnt = 5; + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); + ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA); +Start_IPAC: + if (cs->debug & L1_DEB_IPAC) + debugl1(cs, "IPAC ISTA %02X", ista); + if (ista & 0x0f) { + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, HSCX_ISTA + 0x40); + if (ista & 0x01) + val |= 0x01; + if (ista & 0x04) + val |= 0x02; + if (ista & 0x08) + val |= 0x04; + if (val) + hscx_int_main(cs, val); + } + if (ista & 0x20) { + val = 0xfe & readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA | 0x80); + if (val) { + isac_interrupt(cs, val); + } + } + if (ista & 0x10) { + val = 0x01; + isac_interrupt(cs, val); + } + ista = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ISTA); + if ((ista & 0x3f) && icnt) { + icnt--; + goto Start_IPAC; + } + if (!icnt) + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "Sedlbauer IRQ LOOP"); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xFF); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xC0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; } static irqreturn_t -sedlbauer_isar_interrupt(int intno, void *dev_id, struct pt_regs *regs) +sedlbauer_interrupt_isar(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; + u_char val; int cnt = 5; + u_long flags; - spin_lock(&cs->lock); - val = isar_read(cs, 0, ISAR_IRQBIT); + spin_lock_irqsave(&cs->lock, flags); + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT); Start_ISAR: if (val & ISAR_IRQSTA) isar_int_main(cs); - val = isac_read(cs, ISAC_ISTA); + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA); Start_ISAC: if (val) isac_interrupt(cs, val); - val = isar_read(cs, 0, ISAR_IRQBIT); + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT); if ((val & ISAR_IRQSTA) && --cnt) { if (cs->debug & L1_DEB_HSCX) debugl1(cs, "ISAR IntStat after IntRoutine"); goto Start_ISAR; } - val = isac_read(cs, ISAC_ISTA); + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_ISTA); if (val && --cnt) { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ISAC IntStat after IntRoutine"); @@ -329,362 +386,131 @@ if (cs->debug & L1_DEB_ISAC) debugl1(cs, "Sedlbauer IRQ LOOP"); - isar_write(cs, 0, ISAR_IRQBIT, 0); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - isar_write(cs, 0, ISAR_IRQBIT, ISAR_IRQMSK); - spin_unlock(&cs->lock); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, 0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, ISAC_MASK, 0x0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, ISAR_IRQBIT, ISAR_IRQMSK); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } -static int -sedlbauer_ipac_reset(struct IsdnCardState *cs) +void +release_io_sedlbauer(struct IsdnCardState *cs) { - writereg(cs, cs->hw.sedl.isac, IPAC_POTA2, 0x20); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writereg(cs, cs->hw.sedl.isac, IPAC_POTA2, 0x0); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - writereg(cs, cs->hw.sedl.isac, IPAC_CONF, 0x0); - writereg(cs, cs->hw.sedl.isac, IPAC_ACFG, 0xff); - writereg(cs, cs->hw.sedl.isac, IPAC_AOE, 0x0); - writereg(cs, cs->hw.sedl.isac, IPAC_MASK, 0xc0); - writereg(cs, cs->hw.sedl.isac, IPAC_PCFG, 0x12); - return 0; -} + int bytecnt = 8; -static int -sedlbauer_isar_pci_reset(struct IsdnCardState *cs) -{ - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout((20*HZ)/1000); - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout((20*HZ)/1000); - return 0; -} - -static int -sedlbauer_reset(struct IsdnCardState *cs) -{ - printk(KERN_INFO "Sedlbauer: resetting card\n"); - if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA && - cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX) - return 0; - - if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) { - return sedlbauer_ipac_reset(cs); - } else if ((cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) && - (cs->hw.sedl.bus == SEDL_BUS_PCI)) { - return sedlbauer_isar_pci_reset(cs); - } else { - byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + if (cs->subtyp == SEDL_SPEED_FAX) { + bytecnt = 16; + } else if (cs->hw.sedl.bus == SEDL_BUS_PCI) { + bytecnt = 256; } - return 0; + if (cs->hw.sedl.cfg_reg) + release_region(cs->hw.sedl.cfg_reg, bytecnt); } static void -sedlbauer_isar_release(struct IsdnCardState *cs) +reset_sedlbauer(struct IsdnCardState *cs) { - isar_write(cs, 0, ISAR_IRQBIT, 0); - isac_write(cs, ISAC_MASK, 0xFF); - sedlbauer_reset(cs); - isar_write(cs, 0, ISAR_IRQBIT, 0); - isac_write(cs, ISAC_MASK, 0xFF); - hisax_release_resources(cs); -} - -static void -sedlbauer_led_handler(struct IsdnCardState *cs) -{ - if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID) - return; - - if (cs->status & 0x2000) - cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED2; - else - cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED2; - - if (cs->status & 0x1000) - cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED1; - else - cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED1; - - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); -} - -static void -sedlbauer_isar_init(struct IsdnCardState *cs) -{ - isar_write(cs, 0, ISAR_IRQBIT, 0); - initisac(cs); - initisar(cs); -} - -static struct card_ops sedlbauer_ops = { - .init = inithscxisac, - .reset = sedlbauer_reset, - .release = hisax_release_resources, - .led_handler = sedlbauer_led_handler, - .irq_func = sedlbauer_interrupt, -}; - -static struct card_ops sedlbauer_ipac_ops = { - .init = ipac_init, - .reset = sedlbauer_reset, - .release = hisax_release_resources, - .led_handler = sedlbauer_led_handler, - .irq_func = ipac_irq, -}; - -static struct card_ops sedlbauer_isar_ops = { - .init = sedlbauer_isar_init, - .reset = sedlbauer_reset, - .release = sedlbauer_isar_release, - .led_handler = sedlbauer_led_handler, - .irq_func = sedlbauer_isar_interrupt, -}; - -static int __init -sedl_ipac_probe(struct IsdnCardState *cs) -{ - u8 val; - - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; - val = readreg(cs, cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID); - printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val); - return (val == 1 || val == 2); -} - -static int __init -sedl_ipac_init(struct IsdnCardState *cs) -{ - cs->card_ops = &sedlbauer_ipac_ops; - if (ipac_setup(cs, &ipac_dc_ops, &ipac_bc_ops)) - return -ENODEV; - sedlbauer_reset(cs); - return 0; -} - -static int __init -sedl_isac_isar_init(struct IsdnCardState *cs) -{ - cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar; - cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar; - __set_bit(HW_ISAR, &cs->HW_Flags); - cs->card_ops = &sedlbauer_isar_ops; - cs->auxcmd = &isar_auxcmd; - isac_setup(cs, &isac_ops); - return isar_setup(cs, &isar_ops); -} + printk(KERN_INFO "Sedlbauer: resetting card\n"); -static int __init -sedl_isac_hscx_init(struct IsdnCardState *cs) -{ - cs->card_ops = &sedlbauer_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - return -ENODEV; - sedlbauer_reset(cs); - return 0; + if (!((cs->hw.sedl.bus == SEDL_BUS_PCMCIA) && + (cs->hw.sedl.chip == SEDL_CHIP_ISAC_HSCX))) { + if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) { + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x20); + mdelay(2); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_POTA2, 0x0); + mdelay(10); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_CONF, 0x0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ACFG, 0xff); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_AOE, 0x0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_MASK, 0xc0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_PCFG, 0x12); + } else if ((cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) && + (cs->hw.sedl.bus == SEDL_BUS_PCI)) { + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); + mdelay(2); + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); + mdelay(10); + } else { + byteout(cs->hw.sedl.reset_on, SEDL_RESET); /* Reset On */ + mdelay(2); + byteout(cs->hw.sedl.reset_off, 0); /* Reset Off */ + mdelay(10); + } + } } -static int __init -sedl_card_win_probe(struct IsdnCardState *cs, struct IsdnCard *card) +static int +Sedl_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - cs->irq = card->para[0]; - cs->hw.sedl.cfg_reg = card->para[1]; - cs->hw.sedl.bus = SEDL_BUS_ISA; - if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 8, "sedlbauer isdn")) - goto err; + u_long flags; - if (sedl_ipac_probe(cs)) { - cs->subtyp = SEDL_SPEED_WIN2_PC104; - cs->hw.sedl.chip = SEDL_CHIP_IPAC; - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; - if (sedl_ipac_init(cs)) - goto err; - } else { - cs->subtyp = SEDL_SPEED_CARD_WIN; - cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX; - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX; - cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON; - cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF; - if (sedl_isac_hscx_init(cs)) - goto err; - } - printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n", - Sedlbauer_Types[cs->subtyp], - cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq); - - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -sedl_star_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->hw.sedl.bus = SEDL_BUS_PCMCIA; - if (sedl_ipac_probe(cs)) { - cs->subtyp = SEDL_SPEED_STAR2; - cs->hw.sedl.chip = SEDL_CHIP_IPAC; - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; - if (sedl_ipac_init(cs)) - goto err; - } else { - cs->subtyp = SEDL_SPEED_STAR; - cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX; - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX; - cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; - cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; - if (sedl_isac_hscx_init(cs)) - goto err; - } - printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n", - Sedlbauer_Types[cs->subtyp], - cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 8, cs->irq); - - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -sedl_fax_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->subtyp = SEDL_SPEED_FAX; - cs->hw.sedl.bus = SEDL_BUS_ISA; - cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; - if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 16, "sedlbauer isdn")) - goto err; - - printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n", - Sedlbauer_Types[cs->subtyp], - cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 16, cs->irq); - - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR; - cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_ON; - cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_ISAR_ISA_ISAR_RESET_OFF; - if (sedl_isac_isar_init(cs)) - goto err; - - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -sedl_pci_init(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.sedl.cfg_reg = pci_resource_start(pdev, 0); - cs->hw.sedl.bus = SEDL_BUS_PCI; - - if (!request_io(&cs->rs, cs->hw.sedl.cfg_reg, 256, "sedlbauer isdn")) - return -EBUSY; - - printk(KERN_INFO "Sedlbauer %s: defined at 0x%x-0x%x IRQ %d\n", - Sedlbauer_Types[cs->subtyp], - cs->hw.sedl.cfg_reg, cs->hw.sedl.cfg_reg + 256, cs->irq); - - cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON; - cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF; - byteout(cs->hw.sedl.cfg_reg, 0xff); - byteout(cs->hw.sedl.cfg_reg, 0x00); - byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd); - byteout(cs->hw.sedl.cfg_reg+ 5, 0x02); - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); - current->state = TASK_UNINTERRUPTIBLE; - schedule_timeout((10*HZ)/1000); - byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); - return 0; -} - -static int __init -sedl_fax_pyramid_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = SEDL_SPEEDFAX_PYRAMID; - cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; - if (sedl_pci_init(cs, pdev)) - goto err; - - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR; - if (sedl_isac_isar_init(cs)) - goto err; - - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -sedl_fax_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = SEDL_SPEEDFAX_PCI; - cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; - - if (sedl_pci_init(cs, pdev)) - goto err; - - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAC; - cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_ISAR_PCI_ISAR; - if (sedl_isac_isar_init(cs)) - goto err; - - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -sedl_pci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) -{ - if (pci_enable_device(pdev)) - goto err; - - cs->subtyp = SEDL_SPEED_PCI; - cs->hw.sedl.chip = SEDL_CHIP_IPAC; - if (sedl_pci_init(cs, pdev)) - goto err; - - cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR; - cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC; - if (sedl_ipac_init(cs)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_sedlbauer(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { + spin_lock_irqsave(&cs->lock, flags); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, + ISAR_IRQBIT, 0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, + ISAC_MASK, 0xFF); + reset_sedlbauer(cs); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, + ISAR_IRQBIT, 0); + writereg(cs->hw.sedl.adr, cs->hw.sedl.isac, + ISAC_MASK, 0xFF); + spin_unlock_irqrestore(&cs->lock, flags); + } + release_io_sedlbauer(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + reset_sedlbauer(cs); + if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { + clear_pending_isac_ints(cs); + writereg(cs->hw.sedl.adr, cs->hw.sedl.hscx, + ISAR_IRQBIT, 0); + initisac(cs); + initisar(cs); + /* Reenable all IRQ */ + cs->writeisac(cs, ISAC_MASK, 0); + /* RESET Receiver and Transmitter */ + cs->writeisac(cs, ISAC_CMDR, 0x41); + } else { + inithscxisac(cs, 3); + } + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + case MDL_INFO_CONN: + if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID) + return(0); + spin_lock_irqsave(&cs->lock, flags); + if ((long) arg) + cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED2; + else + cs->hw.sedl.reset_off &= ~SEDL_ISAR_PCI_LED1; + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); + spin_unlock_irqrestore(&cs->lock, flags); + break; + case MDL_INFO_REL: + if (cs->subtyp != SEDL_SPEEDFAX_PYRAMID) + return(0); + spin_lock_irqsave(&cs->lock, flags); + if ((long) arg) + cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED2; + else + cs->hw.sedl.reset_off |= SEDL_ISAR_PCI_LED1; + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); + spin_unlock_irqrestore(&cs->lock, flags); + break; + } + return(0); } static struct pci_dev *dev_sedl __devinitdata = NULL; @@ -700,124 +526,308 @@ { 0, } }; -static struct isapnp_device_id *pdev = &sedl_ids[0]; +static struct isapnp_device_id *ipid __initdata = &sedl_ids[0]; static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __devinit setup_sedlbauer(struct IsdnCard *card) { + int bytecnt, ver, val; struct IsdnCardState *cs = card->cs; char tmp[64]; u16 sub_vendor_id, sub_id; strcpy(tmp, Sedlbauer_revision); - printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", - HiSax_getrev(tmp)); + printk(KERN_INFO "HiSax: Sedlbauer driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ == ISDN_CTYPE_SEDLBAUER) { + cs->subtyp = SEDL_SPEED_CARD_WIN; + cs->hw.sedl.bus = SEDL_BUS_ISA; + cs->hw.sedl.chip = SEDL_CHIP_TEST; + } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) { + cs->subtyp = SEDL_SPEED_STAR; + cs->hw.sedl.bus = SEDL_BUS_PCMCIA; + cs->hw.sedl.chip = SEDL_CHIP_TEST; + } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) { + cs->subtyp = SEDL_SPEED_FAX; + cs->hw.sedl.bus = SEDL_BUS_ISA; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; + } else + return (0); + + bytecnt = 8; if (card->para[1]) { - if (cs->typ == ISDN_CTYPE_SEDLBAUER) { - if (sedl_card_win_probe(card->cs, card) < 0) - return 0; - return 1; - } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_PCMCIA) { - if (sedl_star_probe(card->cs, card) < 0) - return 0; - return 1; - } else if (cs->typ == ISDN_CTYPE_SEDLBAUER_FAX) { - if (sedl_fax_probe(card->cs, card) < 0) - return 0; - return 1; + cs->hw.sedl.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { + bytecnt = 16; } - } + } else { #ifdef __ISAPNP__ - if (isapnp_present()) { - struct pnp_card *pb; - struct pnp_dev *pd; - - while(pdev->card_vendor) { - if ((pb = pnp_find_card(pdev->card_vendor, - pdev->card_device, - pnp_c))) { - pnp_c = pb; - pd = NULL; - if ((pd = pnp_find_dev(pnp_c, - pdev->vendor, - pdev->function, - pd))) { - printk(KERN_INFO "HiSax: %s detected\n", - (char *)pdev->driver_data); - if (pnp_device_attach(pd) < 0) { - printk(KERN_ERR "Sedlbauer PnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pd) < 0) { - printk(KERN_ERR "Sedlbauer PnP: activate failed\n"); - pnp_device_detach(pd); - return 0; - } - if (!pnp_irq_valid(pd, 0) || !pnp_port_valid(pd, 0)) { - printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n", - pnp_irq(pd, 0), pnp_port_start(pd, 0)); - pnp_device_detach(pd); - return 0; - } - card->para[1] = pnp_port_start(pd, 0); - card->para[0] = pnp_irq(pd, 0); - cs->hw.sedl.cfg_reg = card->para[1]; - cs->irq = card->para[0]; - if (pdev->function == ISAPNP_FUNCTION(0x2)) { - if (sedl_fax_probe(card->cs, card)) - return 0; - return 1; + if (isapnp_present()) { + struct pnp_dev *pnp_d; + while(ipid->card_vendor) { + if ((pnp_c = pnp_find_card(ipid->card_vendor, + ipid->card_device, pnp_c))) { + pnp_d = NULL; + if ((pnp_d = pnp_find_dev(pnp_c, + ipid->vendor, ipid->function, pnp_d))) { + int err; + + printk(KERN_INFO "HiSax: %s detected\n", + (char *)ipid->driver_data); + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); + } + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[0] = pnp_irq(pnp_d, 0); + + if (!card->para[0] || !card->para[1]) { + printk(KERN_ERR "Sedlbauer PnP:some resources are missing %ld/%lx\n", + card->para[0], card->para[1]); + pnp_disable_dev(pnp_d); + return(0); + } + cs->hw.sedl.cfg_reg = card->para[1]; + cs->irq = card->para[0]; + if (ipid->function == ISAPNP_FUNCTION(0x2)) { + cs->subtyp = SEDL_SPEED_FAX; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; + bytecnt = 16; + } else { + cs->subtyp = SEDL_SPEED_CARD_WIN; + cs->hw.sedl.chip = SEDL_CHIP_TEST; + } + goto ready; } else { - if (sedl_card_win_probe(card->cs, card)) - return 0; - return 1; + printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n"); + return(0); } - } else { - printk(KERN_ERR "Sedlbauer PnP: PnP error card found, no device\n"); - return 0; } + ipid++; + pnp_c = NULL; + } + if (!ipid->card_vendor) { + printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n"); } - pdev++; - pnp_c=NULL; - } - if (!pdev->card_vendor) { - printk(KERN_INFO "Sedlbauer PnP: no ISAPnP card found\n"); } - } #endif /* Probe for Sedlbauer speed pci */ -#ifdef CONFIG_PCI - dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, - PCI_DEVICE_ID_TIGERJET_100, dev_sedl); - if (dev_sedl) { +#if CONFIG_PCI + if ((dev_sedl = pci_find_device(PCI_VENDOR_ID_TIGERJET, + PCI_DEVICE_ID_TIGERJET_100, dev_sedl))) { + if (pci_enable_device(dev_sedl)) + return(0); + cs->irq = dev_sedl->irq; + if (!cs->irq) { + printk(KERN_WARNING "Sedlbauer: No IRQ for PCI card found\n"); + return(0); + } + cs->hw.sedl.cfg_reg = pci_resource_start(dev_sedl, 0); + } else { + printk(KERN_WARNING "Sedlbauer: No PCI card found\n"); + return(0); + } + cs->irq_flags |= SA_SHIRQ; + cs->hw.sedl.bus = SEDL_BUS_PCI; sub_vendor_id = dev_sedl->subsystem_vendor; sub_id = dev_sedl->subsystem_device; printk(KERN_INFO "Sedlbauer: PCI subvendor:%x subid %x\n", - sub_vendor_id, sub_id); + sub_vendor_id, sub_id); + printk(KERN_INFO "Sedlbauer: PCI base adr %#x\n", + cs->hw.sedl.cfg_reg); if (sub_id != PCI_SUB_ID_SEDLBAUER) { printk(KERN_ERR "Sedlbauer: unknown sub id %#x\n", sub_id); - return 0; + return(0); } if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PYRAMID) { - if (sedl_fax_pyramid_probe(cs, dev_sedl)) - return 0; - return 1; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; + cs->subtyp = SEDL_SPEEDFAX_PYRAMID; } else if (sub_vendor_id == PCI_SUBVENDOR_SPEEDFAX_PCI) { - if (sedl_fax_pci_probe(cs, dev_sedl)) - return 0; - return 1; + cs->hw.sedl.chip = SEDL_CHIP_ISAC_ISAR; + cs->subtyp = SEDL_SPEEDFAX_PCI; + } else if (sub_vendor_id == PCI_SUBVENDOR_HST_SAPHIR3) { + cs->hw.sedl.chip = SEDL_CHIP_IPAC; + cs->subtyp = HST_SAPHIR3; } else if (sub_vendor_id == PCI_SUBVENDOR_SEDLBAUER_PCI) { - if (sedl_pci_probe(cs, dev_sedl)) - return 0; - return 1; + cs->hw.sedl.chip = SEDL_CHIP_IPAC; + cs->subtyp = SEDL_SPEED_PCI; + } else { + printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n", + sub_vendor_id); + return(0); } - printk(KERN_ERR "Sedlbauer: unknown sub vendor id %#x\n", - sub_vendor_id); - return 0; - } + bytecnt = 256; + cs->hw.sedl.reset_on = SEDL_ISAR_PCI_ISAR_RESET_ON; + cs->hw.sedl.reset_off = SEDL_ISAR_PCI_ISAR_RESET_OFF; + byteout(cs->hw.sedl.cfg_reg, 0xff); + byteout(cs->hw.sedl.cfg_reg, 0x00); + byteout(cs->hw.sedl.cfg_reg+ 2, 0xdd); + byteout(cs->hw.sedl.cfg_reg+ 5, 0x02); + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_on); + mdelay(2); + byteout(cs->hw.sedl.cfg_reg +3, cs->hw.sedl.reset_off); + mdelay(10); +#else + printk(KERN_WARNING "Sedlbauer: NO_PCI_BIOS\n"); + return (0); #endif /* CONFIG_PCI */ - return 0; + } +ready: + /* In case of the sedlbauer pcmcia card, this region is in use, + * reserved for us by the card manager. So we do not check it + * here, it would fail. + */ + if (cs->hw.sedl.bus != SEDL_BUS_PCMCIA && + !request_region(cs->hw.sedl.cfg_reg, bytecnt, "sedlbauer isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.sedl.cfg_reg, + cs->hw.sedl.cfg_reg + bytecnt); + return (0); + } + + printk(KERN_INFO + "Sedlbauer: defined at 0x%x-0x%x IRQ %d\n", + cs->hw.sedl.cfg_reg, + cs->hw.sedl.cfg_reg + bytecnt, + cs->irq); + + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &Sedl_card_msg; + +/* + * testing ISA and PCMCIA Cards for IPAC, default is ISAC + * do not test for PCI card, because ports are different + * and PCI card uses only IPAC (for the moment) + */ + if (cs->hw.sedl.bus != SEDL_BUS_PCI) { + val = readreg(cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR, + cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC, IPAC_ID); + printk(KERN_DEBUG "Sedlbauer: testing IPAC version %x\n", val); + if ((val == 1) || (val == 2)) { + /* IPAC */ + cs->subtyp = SEDL_SPEED_WIN2_PC104; + if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) { + cs->subtyp = SEDL_SPEED_STAR2; + } + cs->hw.sedl.chip = SEDL_CHIP_IPAC; + } else { + /* ISAC_HSCX oder ISAC_ISAR */ + if (cs->hw.sedl.chip == SEDL_CHIP_TEST) { + cs->hw.sedl.chip = SEDL_CHIP_ISAC_HSCX; + } + } + } + +/* + * hw.sedl.chip is now properly set + */ + printk(KERN_INFO "Sedlbauer: %s detected\n", + Sedlbauer_Types[cs->subtyp]); + + setup_isac(cs); + if (cs->hw.sedl.chip == SEDL_CHIP_IPAC) { + if (cs->hw.sedl.bus == SEDL_BUS_PCI) { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_PCI_IPAC; + } else { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_IPAC_ANY_IPAC; + } + test_and_set_bit(HW_IPAC, &cs->HW_Flags); + cs->readisac = &ReadISAC_IPAC; + cs->writeisac = &WriteISAC_IPAC; + cs->readisacfifo = &ReadISACfifo_IPAC; + cs->writeisacfifo = &WriteISACfifo_IPAC; + cs->irq_func = &sedlbauer_interrupt_ipac; + val = readreg(cs->hw.sedl.adr, cs->hw.sedl.isac, IPAC_ID); + printk(KERN_INFO "Sedlbauer: IPAC version %x\n", val); + } else { + /* ISAC_HSCX oder ISAC_ISAR */ + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + if (cs->hw.sedl.chip == SEDL_CHIP_ISAC_ISAR) { + if (cs->hw.sedl.bus == SEDL_BUS_PCI) { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + + SEDL_ISAR_PCI_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + + SEDL_ISAR_PCI_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + + SEDL_ISAR_PCI_ISAR; + } else { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + + SEDL_ISAR_ISA_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + + SEDL_ISAR_ISA_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + + SEDL_ISAR_ISA_ISAR; + cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + + SEDL_ISAR_ISA_ISAR_RESET_ON; + cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + + SEDL_ISAR_ISA_ISAR_RESET_OFF; + } + cs->bcs[0].hw.isar.reg = &cs->hw.sedl.isar; + cs->bcs[1].hw.isar.reg = &cs->hw.sedl.isar; + test_and_set_bit(HW_ISAR, &cs->HW_Flags); + cs->irq_func = &sedlbauer_interrupt_isar; + cs->auxcmd = &isar_auxcmd; + ISACVersion(cs, "Sedlbauer:"); + cs->BC_Read_Reg = &ReadISAR; + cs->BC_Write_Reg = &WriteISAR; + cs->BC_Send_Data = &isar_fill_fifo; + bytecnt = 3; + while (bytecnt) { + ver = ISARVersion(cs, "Sedlbauer:"); + if (ver < 0) + printk(KERN_WARNING + "Sedlbauer: wrong ISAR version (ret = %d)\n", ver); + else + break; + reset_sedlbauer(cs); + bytecnt--; + } + if (!bytecnt) { + release_io_sedlbauer(cs); + return (0); + } + } else { + if (cs->hw.sedl.bus == SEDL_BUS_PCMCIA) { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_HSCX; + cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; + cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_PCMCIA_RESET; + cs->irq_flags |= SA_SHIRQ; + } else { + cs->hw.sedl.adr = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ADR; + cs->hw.sedl.isac = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_ISAC; + cs->hw.sedl.hscx = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_HSCX; + cs->hw.sedl.reset_on = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_ON; + cs->hw.sedl.reset_off = cs->hw.sedl.cfg_reg + SEDL_HSCX_ISA_RESET_OFF; + } + cs->irq_func = &sedlbauer_interrupt; + ISACVersion(cs, "Sedlbauer:"); + + if (HscxVersion(cs, "Sedlbauer:")) { + printk(KERN_WARNING + "Sedlbauer: wrong HSCX versions check IO address\n"); + release_io_sedlbauer(cs); + return (0); + } + } + } + return (1); } diff -Nru a/drivers/isdn/hisax/sedlbauer_cs.c b/drivers/isdn/hisax/sedlbauer_cs.c --- a/drivers/isdn/hisax/sedlbauer_cs.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hisax/sedlbauer_cs.c Thu Feb 19 23:44:24 2004 @@ -53,6 +53,7 @@ #include #include #include +#include "hisax_cfg.h" MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Sedlbauer cards"); MODULE_AUTHOR("Marcus Niemann"); @@ -93,8 +94,6 @@ static int protocol = 2; /* EURO-ISDN Default */ MODULE_PARM(protocol, "i"); -extern int sedl_init_pcmcia(int, int, int*, int); - /*====================================================================*/ /* @@ -176,6 +175,7 @@ dev_link_t link; dev_node_t node; int stop; + int cardnr; } local_info_t; /*====================================================================== @@ -203,6 +203,7 @@ local = kmalloc(sizeof(local_info_t), GFP_KERNEL); if (!local) return NULL; memset(local, 0, sizeof(local_info_t)); + local->cardnr = -1; link = &local->link; link->priv = local; /* Interrupt setup */ @@ -324,7 +325,7 @@ config_info_t conf; win_req_t req; memreq_t map; - + IsdnCard_t icard; DEBUG(0, "sedlbauer_config(0x%p)\n", link); @@ -509,10 +510,19 @@ printk("\n"); link->state &= ~DEV_CONFIG_PENDING; - - sedl_init_pcmcia(link->io.BasePort1, link->irq.AssignedIRQ, - &(((local_info_t*)link->priv)->stop), - protocol); + + icard.para[0] = link->irq.AssignedIRQ; + icard.para[1] = link->io.BasePort1; + icard.protocol = protocol; + icard.typ = ISDN_CTYPE_SEDLBAUER_PCMCIA; + + last_ret = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->stop), &icard); + if (last_ret < 0) { + printk(KERN_ERR "sedlbauer_cs: failed to initialize SEDLBAUER PCMCIA %d at i/o %#x\n", + last_ret, link->io.BasePort1); + sedlbauer_release(link); + } else + ((local_info_t*)link->priv)->cardnr = last_ret; return; @@ -532,8 +542,15 @@ static void sedlbauer_release(dev_link_t *link) { + local_info_t *local = link->priv; DEBUG(0, "sedlbauer_release(0x%p)\n", link); + if (local) { + if (local->cardnr >= 0) { + /* no unregister function with hisax */ + HiSax_closecard(local->cardnr); + } + } /* Unlink the device chain */ link->dev = NULL; diff -Nru a/drivers/isdn/hisax/sportster.c b/drivers/isdn/hisax/sportster.c --- a/drivers/isdn/hisax/sportster.c Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/sportster.c Thu Feb 19 23:44:23 2004 @@ -1,4 +1,4 @@ -/* $Id: sportster.c,v 1.14.6.2 2001/09/23 22:24:51 kai Exp $ +/* $Id: sportster.c,v 1.16.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for USR Sportster internal TA * @@ -19,7 +19,7 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *sportster_revision = "$Revision: 1.14.6.2 $"; +const char *sportster_revision = "$Revision: 1.16.2.4 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) @@ -38,91 +38,102 @@ } static inline void -read_fifo(unsigned int adr, u8 * data, int size) +read_fifo(unsigned int adr, u_char * data, int size) { insb(adr, data, size); } static void -write_fifo(unsigned int adr, u8 * data, int size) +write_fifo(unsigned int adr, u_char * data, int size) { outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return bytein(calc_off(cs->hw.spt.isac, offset)); + return (bytein(calc_off(cs->hw.spt.isac, offset))); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { byteout(calc_off(cs->hw.spt.isac, offset), value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { read_fifo(cs->hw.spt.isac, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { write_fifo(cs->hw.spt.isac, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - return bytein(calc_off(cs->hw.spt.hscx[hscx], offset)); + return (bytein(calc_off(cs->hw.spt.hscx[hscx], offset))); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { byteout(calc_off(cs->hw.spt.hscx[hscx], offset), value); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - read_fifo(cs->hw.spt.hscx[hscx], data, size); -} +/* + * fast interrupt HSCX stuff goes here + */ -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - write_fifo(cs->hw.spt.hscx[hscx], data, size); -} +#define READHSCX(cs, nr, reg) bytein(calc_off(cs->hw.spt.hscx[nr], reg)) +#define WRITEHSCX(cs, nr, reg, data) byteout(calc_off(cs->hw.spt.hscx[nr], reg), data) +#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.spt.hscx[nr], ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.spt.hscx[nr], ptr, cnt) -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; +#include "hscx_irq.c" static irqreturn_t sportster_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; + u_char val; + u_long flags; - hscxisac_irq(intno, dev_id, regs); + spin_lock_irqsave(&cs->lock, flags); + val = READHSCX(cs, 1, HSCX_ISTA); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = ReadISAC(cs, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + val = READHSCX(cs, 1, HSCX_ISTA); + if (val) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = ReadISAC(cs, ISAC_ISTA); + if (val) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + /* get a new irq impulse if there any pending */ bytein(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ +1); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } -static void -sportster_release(struct IsdnCardState *cs) +void +release_io_sportster(struct IsdnCardState *cs) { int i, adr; @@ -133,45 +144,50 @@ } } -static int -sportster_reset(struct IsdnCardState *cs) +void +reset_sportster(struct IsdnCardState *cs) { cs->hw.spt.res_irq |= SPORTSTER_RESET; /* Reset On */ byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); + mdelay(10); cs->hw.spt.res_irq &= ~SPORTSTER_RESET; /* Reset Off */ byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - return 0; + mdelay(10); } static int Sportster_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - return(0); -} + u_long flags; -static void -sportster_init(struct IsdnCardState *cs) -{ - inithscxisac(cs); - cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */ - byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_sportster(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_sportster(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + reset_sportster(cs); + inithscxisac(cs, 1); + cs->hw.spt.res_irq |= SPORTSTER_INTE; /* IRQ On */ + byteout(cs->hw.spt.cfg_reg + SPORTSTER_RES_IRQ, cs->hw.spt.res_irq); + inithscxisac(cs, 2); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); } -static struct card_ops sportster_ops = { - .init = sportster_init, - .reset = sportster_reset, - .release = sportster_release, - .irq_func = sportster_interrupt, -}; - static int __init get_io_range(struct IsdnCardState *cs) { - int i, adr; + int i, j, adr; for (i=0;i<64;i++) { adr = cs->hw.spt.cfg_reg + i *1024; @@ -179,65 +195,76 @@ printk(KERN_WARNING "HiSax: %s config port %x-%x already in use\n", CardType[cs->typ], adr, adr + 8); - goto err; - } + break; + } } - return 1; - err: - for (i=i-1; i >= 0; i--) { - adr = cs->hw.spt.cfg_reg + i *1024; - release_region(adr, 8); + if (i==64) + return(1); + else { + for (j=0; jhw.spt.cfg_reg + j *1024; + release_region(adr, 8); + } + return(0); } - return 0; } -static int __init -sportster_probe(struct IsdnCardState *cs, struct IsdnCard *card) +int __init +setup_sportster(struct IsdnCard *card) { - cs->irq = card->para[0]; + struct IsdnCardState *cs = card->cs; + char tmp[64]; + + strcpy(tmp, sportster_revision); + printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_SPORTSTER) + return (0); + cs->hw.spt.cfg_reg = card->para[1]; + cs->irq = card->para[0]; if (!get_io_range(cs)) - return -EBUSY; + return (0); cs->hw.spt.isac = cs->hw.spt.cfg_reg + SPORTSTER_ISAC; cs->hw.spt.hscx[0] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXA; cs->hw.spt.hscx[1] = cs->hw.spt.cfg_reg + SPORTSTER_HSCXB; switch(cs->irq) { - case 5: cs->hw.spt.res_irq = 1; break; - case 7: cs->hw.spt.res_irq = 2; break; - case 10:cs->hw.spt.res_irq = 3; break; - case 11:cs->hw.spt.res_irq = 4; break; - case 12:cs->hw.spt.res_irq = 5; break; - case 14:cs->hw.spt.res_irq = 6; break; - case 15:cs->hw.spt.res_irq = 7; break; - default: - printk(KERN_WARNING "Sportster: wrong IRQ\n"); - goto err; + case 5: cs->hw.spt.res_irq = 1; + break; + case 7: cs->hw.spt.res_irq = 2; + break; + case 10:cs->hw.spt.res_irq = 3; + break; + case 11:cs->hw.spt.res_irq = 4; + break; + case 12:cs->hw.spt.res_irq = 5; + break; + case 14:cs->hw.spt.res_irq = 6; + break; + case 15:cs->hw.spt.res_irq = 7; + break; + default:release_io_sportster(cs); + printk(KERN_WARNING "Sportster: wrong IRQ\n"); + return(0); } - sportster_reset(cs); printk(KERN_INFO "HiSax: %s config irq:%d cfg:0x%X\n", - CardType[cs->typ], cs->irq, cs->hw.spt.cfg_reg); - + CardType[cs->typ], cs->irq, cs->hw.spt.cfg_reg); + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; cs->cardmsg = &Sportster_card_msg; - cs->card_ops = &sportster_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - sportster_release(cs); - return -EBUSY; -} - -int __init -setup_sportster(struct IsdnCard *card) -{ - char tmp[64]; - - strcpy(tmp, sportster_revision); - printk(KERN_INFO "HiSax: USR Sportster driver Rev. %s\n", - HiSax_getrev(tmp)); - - if (sportster_probe(card->cs, card) < 0) - return 0; - return 1; + cs->irq_func = &sportster_interrupt; + ISACVersion(cs, "Sportster:"); + if (HscxVersion(cs, "Sportster:")) { + printk(KERN_WARNING + "Sportster: wrong HSCX versions check IO address\n"); + release_io_sportster(cs); + return (0); + } + return (1); } diff -Nru a/drivers/isdn/hisax/st5481.h b/drivers/isdn/hisax/st5481.h --- a/drivers/isdn/hisax/st5481.h Thu Feb 19 23:44:26 2004 +++ b/drivers/isdn/hisax/st5481.h Thu Feb 19 23:44:26 2004 @@ -219,15 +219,15 @@ #define L1_EVENT_COUNT (EV_TIMER3 + 1) #define ERR(format, arg...) \ -printk(KERN_ERR __FILE__ ": %s: " format "\n" , __FUNCTION__ , ## arg) +printk(KERN_ERR "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg) #define WARN(format, arg...) \ -printk(KERN_WARNING __FILE__ ": %s: " format "\n" , __FUNCTION__ , ## arg) +printk(KERN_WARNING "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg) #define INFO(format, arg...) \ -printk(KERN_INFO __FILE__ ": %s: " format "\n" , __FUNCTION__ , ## arg) +printk(KERN_INFO "%s:%s: " format "\n" , __FILE__, __FUNCTION__ , ## arg) -#include "st5481_hdlc.h" +#include "isdnhdlc.h" #include "fsm.h" #include "hisax_if.h" #include @@ -236,9 +236,9 @@ * FIFO handling */ -/* Generic FIFO structure */ +/* Generic FIFO structure */ struct fifo { - u8 r,w,count,size; + u_char r,w,count,size; spinlock_t lock; }; @@ -270,7 +270,7 @@ index = -1; } else { // Return index where to get the next data to add to the FIFO - index = fifo->w++ & (fifo->size-1); + index = fifo->w++ & (fifo->size-1); fifo->count++; } spin_unlock_irqrestore(&fifo->lock, flags); @@ -289,13 +289,13 @@ return -1; } - spin_lock_irqsave(&fifo->lock, flags); + spin_lock_irqsave(&fifo->lock, flags); if (!fifo->count) { // FIFO empty index = -1; } else { // Return index where to get the next data from the FIFO - index = fifo->r++ & (fifo->size-1); + index = fifo->r++ & (fifo->size-1); fifo->count--; } spin_unlock_irqrestore(&fifo->lock, flags); @@ -336,7 +336,7 @@ }; struct st5481_d_out { - struct hdlc_vars hdlc_state; + struct isdnhdlc_vars hdlc_state; struct urb *urb[2]; /* double buffering */ unsigned long busy; struct sk_buff *tx_skb; @@ -344,15 +344,15 @@ }; struct st5481_b_out { - struct hdlc_vars hdlc_state; + struct isdnhdlc_vars hdlc_state; struct urb *urb[2]; /* double buffering */ - u8 flow_event; + u_char flow_event; u_long busy; struct sk_buff *tx_skb; }; struct st5481_in { - struct hdlc_vars hdlc_state; + struct isdnhdlc_vars hdlc_state; struct urb *urb[2]; /* double buffering */ int mode; int bufsize; @@ -452,7 +452,7 @@ int st5481_isoc_flatten(struct urb *urb); void st5481_usb_pipe_reset(struct st5481_adapter *adapter, - u8 pipe, ctrl_complete_t complete, void *context); + u_char pipe, ctrl_complete_t complete, void *context); void st5481_usb_ctrl_msg(struct st5481_adapter *adapter, u8 request, u8 requesttype, u16 value, u16 index, ctrl_complete_t complete, void *context); @@ -482,7 +482,7 @@ { int i,j; int len,ofs; - u8 *data; + u_char *data; printk(KERN_DEBUG "%s: packets=%d,errors=%d\n", name,urb->number_of_packets,urb->error_count); diff -Nru a/drivers/isdn/hisax/st5481_b.c b/drivers/isdn/hisax/st5481_b.c --- a/drivers/isdn/hisax/st5481_b.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/hisax/st5481_b.c Thu Feb 19 23:44:24 2004 @@ -31,9 +31,9 @@ struct st5481_b_out *b_out = &bcs->b_out; struct st5481_adapter *adapter = bcs->adapter; struct urb *urb; - u_int packet_size, bytes_sent; - int len, offset, buf_size; - u_int i; + unsigned int packet_size,offset; + int len,buf_size,bytes_sent; + int i; struct sk_buff *skb; if (test_and_set_bit(buf_nr, &b_out->busy)) { @@ -67,22 +67,31 @@ bytes_sent = buf_size - len; if (skb->len < bytes_sent) bytes_sent = skb->len; - - memcpy(urb->transfer_buffer+len, skb->data, bytes_sent); - + { /* swap tx bytes to get hearable audio data */ + register unsigned char *src = skb->data; + register unsigned char *dest = urb->transfer_buffer+len; + register unsigned int count; + for (count = 0; count < bytes_sent; count++) + *dest++ = isdnhdlc_bit_rev_tab[*src++]; + } len += bytes_sent; } else { - len += hdlc_encode(&b_out->hdlc_state, - skb->data, skb->len, &bytes_sent, - urb->transfer_buffer+len, buf_size-len); + len += isdnhdlc_encode(&b_out->hdlc_state, + skb->data, skb->len, &bytes_sent, + urb->transfer_buffer+len, buf_size-len); } skb_pull(skb, bytes_sent); - + if (!skb->len) { // Frame sent b_out->tx_skb = NULL; - B_L1L2(bcs, PH_DATA | CONFIRM, skb); + B_L1L2(bcs, PH_DATA | CONFIRM, (void *) skb->truesize); + dev_kfree_skb_any(skb); + +/* if (!(bcs->tx_skb = skb_dequeue(&bcs->sq))) { */ +/* st5481B_sched_event(bcs, B_XMTBUFREADY); */ +/* } */ } } else { if (bcs->mode == L1_MODE_TRANS) { @@ -90,9 +99,9 @@ len = buf_size; } else { // Send flags - len += hdlc_encode(&b_out->hdlc_state, - NULL, 0, &bytes_sent, - urb->transfer_buffer+len, buf_size-len); + len += isdnhdlc_encode(&b_out->hdlc_state, + NULL, 0, &bytes_sent, + urb->transfer_buffer+len, buf_size-len); } } } @@ -136,7 +145,7 @@ */ static void led_blink(struct st5481_adapter *adapter) { - u8 leds = adapter->leds; + u_char leds = adapter->leds; // 50 frames/sec for each channel if (++adapter->led_counter % 50) { @@ -204,7 +213,7 @@ if (bcs->mode != L1_MODE_NULL) { // Open the B channel if (bcs->mode != L1_MODE_TRANS) { - hdlc_out_init(&b_out->hdlc_state, 0, bcs->mode == L1_MODE_HDLC_56K); + isdnhdlc_out_init(&b_out->hdlc_state, 0, bcs->mode == L1_MODE_HDLC_56K); } st5481_usb_pipe_reset(adapter, (bcs->channel+1)*2, NULL, NULL); @@ -260,7 +269,7 @@ endpoint = &altsetting->endpoint[EP_B1_OUT - 1 + bcs->channel * 2]; DBG(4,"endpoint address=%02x,packet size=%d", - endpoint->desc.bEndpointAddress,endpoint->desc.wMaxPacketSize); + endpoint->desc.bEndpointAddress, endpoint->desc.wMaxPacketSize); // Allocate memory for 8000bytes/sec + extra bytes if underrun return st5481_setup_isocpipes(b_out->urb, dev, diff -Nru a/drivers/isdn/hisax/st5481_d.c b/drivers/isdn/hisax/st5481_d.c --- a/drivers/isdn/hisax/st5481_d.c Thu Feb 19 23:44:25 2004 +++ b/drivers/isdn/hisax/st5481_d.c Thu Feb 19 23:44:25 2004 @@ -294,8 +294,8 @@ { struct st5481_d_out *d_out = &adapter->d_out; struct urb *urb; - unsigned int num_packets; - int len, buf_size, bytes_sent, packet_offset; + unsigned int num_packets, packet_offset; + int len, buf_size, bytes_sent; struct sk_buff *skb; struct usb_iso_packet_descriptor *desc; @@ -313,15 +313,15 @@ buf_size = NUM_ISO_PACKETS_D * SIZE_ISO_PACKETS_D_OUT; if (skb) { - len = hdlc_encode(&d_out->hdlc_state, - skb->data, skb->len, &bytes_sent, - urb->transfer_buffer, buf_size); + len = isdnhdlc_encode(&d_out->hdlc_state, + skb->data, skb->len, &bytes_sent, + urb->transfer_buffer, buf_size); skb_pull(skb,bytes_sent); } else { // Send flags or idle - len = hdlc_encode(&d_out->hdlc_state, - NULL, 0, &bytes_sent, - urb->transfer_buffer, buf_size); + len = isdnhdlc_encode(&d_out->hdlc_state, + NULL, 0, &bytes_sent, + urb->transfer_buffer, buf_size); } if (len < buf_size) { @@ -341,7 +341,7 @@ desc = &urb->iso_frame_desc[num_packets]; desc->offset = packet_offset; desc->length = SIZE_ISO_PACKETS_D_OUT; - if (len - packet_offset < (int)desc->length) + if (len - packet_offset < desc->length) desc->length = len - packet_offset; num_packets++; packet_offset += desc->length; @@ -413,7 +413,7 @@ DBG(2,"len=%d",skb->len); - hdlc_out_init(&d_out->hdlc_state, 1, 0); + isdnhdlc_out_init(&d_out->hdlc_state, 1, 0); if (test_and_set_bit(buf_nr, &d_out->busy)) { WARN("ep %d urb %d busy %#lx", EP_D_OUT, buf_nr, d_out->busy); @@ -422,9 +422,9 @@ urb = d_out->urb[buf_nr]; DBG_SKB(0x10, skb); - len = hdlc_encode(&d_out->hdlc_state, - skb->data, skb->len, &bytes_sent, - urb->transfer_buffer, 16); + len = isdnhdlc_encode(&d_out->hdlc_state, + skb->data, skb->len, &bytes_sent, + urb->transfer_buffer, 16); skb_pull(skb, bytes_sent); if(len < 16) @@ -664,7 +664,7 @@ endpoint = &altsetting->endpoint[EP_D_OUT-1]; DBG(2,"endpoint address=%02x,packet size=%d", - endpoint->desc.bEndpointAddress,endpoint->desc.wMaxPacketSize); + endpoint->desc.bEndpointAddress, endpoint->desc.wMaxPacketSize); return st5481_setup_isocpipes(d_out->urb, dev, usb_sndisocpipe(dev, endpoint->desc.bEndpointAddress), diff -Nru a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c --- a/drivers/isdn/hisax/st5481_init.c Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/hisax/st5481_init.c Thu Feb 19 23:44:28 2004 @@ -14,7 +14,6 @@ * TODO: * * b layer1 delay? - * hdlc as module * hotplug / unregister issues * mod_inc/dec_use_count * unify parts of d/b channel usb handling @@ -59,8 +58,8 @@ * This function will be called when the adapter is plugged * into the USB bus. */ -static int probe_st5481(struct usb_interface *intf, - const struct usb_device_id *id) +static int __devinit probe_st5481(struct usb_interface *intf, + const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(intf); struct st5481_adapter *adapter; @@ -140,7 +139,7 @@ usb_set_intfdata(intf, NULL); if (!adapter) return; - + list_del(&adapter->list); st5481_stop(adapter); @@ -196,7 +195,7 @@ st5481_debug = debug; #endif - printk(KERN_INFO "hisax_st5481: ST5481 USB ISDN driver v0.1.0\n"); + printk(KERN_INFO "hisax_st5481: ST5481 USB ISDN driver $Revision: 2.4.2.3 $\n"); retval = st5481_d_init(); if (retval < 0) diff -Nru a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c --- a/drivers/isdn/hisax/st5481_usb.c Thu Feb 19 23:44:26 2004 +++ b/drivers/isdn/hisax/st5481_usb.c Thu Feb 19 23:44:26 2004 @@ -96,7 +96,7 @@ * Asynchronous pipe reset (async version of usb_clear_halt). */ void st5481_usb_pipe_reset(struct st5481_adapter *adapter, - u8 pipe, + u_char pipe, ctrl_complete_t complete, void *context) { DBG(1,"pipe=%02x",pipe); @@ -500,8 +500,8 @@ status = len; len = 0; } else { - status = hdlc_decode(&in->hdlc_state, ptr, len, &count, - in->rcvbuf, in->bufsize); + status = isdnhdlc_decode(&in->hdlc_state, ptr, len, &count, + in->rcvbuf, in->bufsize); ptr += count; len -= count; } @@ -633,8 +633,8 @@ if (in->mode != L1_MODE_NULL) { if (in->mode != L1_MODE_TRANS) - hdlc_rcv_init(&in->hdlc_state, - in->mode == L1_MODE_HDLC_56K); + isdnhdlc_rcv_init(&in->hdlc_state, + in->mode == L1_MODE_HDLC_56K); st5481_usb_pipe_reset(in->adapter, in->ep, NULL, NULL); st5481_usb_device_ctrl_msg(in->adapter, in->counter, diff -Nru a/drivers/isdn/hisax/tei.c b/drivers/isdn/hisax/tei.c --- a/drivers/isdn/hisax/tei.c Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/hisax/tei.c Thu Feb 19 23:44:27 2004 @@ -1,4 +1,4 @@ -/* $Id: tei.c,v 2.17.6.3 2001/09/23 22:24:51 kai Exp $ +/* $Id: tei.c,v 2.20.2.3 2004/01/13 14:31:26 keil Exp $ * * Author Karsten Keil * based on the teles driver from Jan den Ouden @@ -20,7 +20,7 @@ #include #include -const char *tei_revision = "$Revision: 2.17.6.3 $"; +const char *tei_revision = "$Revision: 2.20.2.3 $"; #define ID_REQUEST 1 #define ID_ASSIGNED 2 @@ -34,7 +34,7 @@ static struct Fsm teifsm; -void tei_handler(struct PStack *st, u8 pr, struct sk_buff *skb); +void tei_handler(struct PStack *st, u_char pr, struct sk_buff *skb); enum { ST_TEI_NOP, @@ -74,22 +74,6 @@ "EV_T202", }; -static inline void -mdl_assign(struct IsdnCardState *cs) -{ - cs->status |= 0x0001; - if (cs->card_ops->led_handler) - cs->card_ops->led_handler(cs); -} - -static inline void -mdl_remove(struct IsdnCardState *cs) -{ - cs->status = 0; - if (cs->card_ops->led_handler) - cs->card_ops->led_handler(cs); -} - unsigned int random_ri(void) { @@ -116,10 +100,10 @@ } static void -put_tei_msg(struct PStack *st, u8 m_id, unsigned int ri, u8 tei) +put_tei_msg(struct PStack *st, u_char m_id, unsigned int ri, u_char tei) { struct sk_buff *skb; - u8 *bp; + u_char *bp; if (!(skb = alloc_skb(8, GFP_ATOMIC))) { printk(KERN_WARNING "HiSax: No skb for TEI manager\n"); @@ -135,7 +119,7 @@ bp[2] = ri & 0xff; bp[3] = m_id; bp[4] = (tei << 1) | 1; - L2L1(st, PH_DATA | REQUEST, skb); + st->l2.l2l1(st, PH_DATA | REQUEST, skb); } static void @@ -145,7 +129,7 @@ if (st->l2.tei != -1) { st->ma.tei_m.printdebug(&st->ma.tei_m, - "assign request for already assigned tei %d", + "assign request for allready asigned tei %d", st->l2.tei); return; } @@ -181,9 +165,9 @@ } else if (ri == st->ma.ri) { FsmDelTimer(&st->ma.t202, 1); FsmChangeState(&st->ma.tei_m, ST_TEI_NOP); - L3L2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei); + st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) tei); cs = (struct IsdnCardState *) st->l1.hardware; - mdl_assign(cs); + cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL); } } @@ -255,9 +239,9 @@ if ((st->l2.tei != -1) && ((tei == GROUP_TEI) || (tei == st->l2.tei))) { FsmDelTimer(&st->ma.t202, 5); FsmChangeState(&st->ma.tei_m, ST_TEI_NOP); - L3L2(st, MDL_REMOVE | REQUEST, 0); + st->l3.l3l2(st, MDL_REMOVE | REQUEST, 0); cs = (struct IsdnCardState *) st->l1.hardware; - mdl_remove(cs); + cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL); } } @@ -291,9 +275,9 @@ FsmAddTimer(&st->ma.t202, st->ma.T202, EV_T202, NULL, 3); } else { st->ma.tei_m.printdebug(&st->ma.tei_m, "assign req failed"); - L3L2(st, MDL_ERROR | RESPONSE, 0); + st->l3.l3l2(st, MDL_ERROR | RESPONSE, 0); cs = (struct IsdnCardState *) st->l1.hardware; - mdl_remove(cs); + cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL); FsmChangeState(fi, ST_TEI_NOP); } } @@ -314,9 +298,9 @@ } else { st->ma.tei_m.printdebug(&st->ma.tei_m, "verify req for tei %d failed", st->l2.tei); - L3L2(st, MDL_REMOVE | REQUEST, 0); + st->l3.l3l2(st, MDL_REMOVE | REQUEST, 0); cs = (struct IsdnCardState *) st->l1.hardware; - mdl_remove(cs); + cs->cardmsg(cs, MDL_REMOVE | REQUEST, NULL); FsmChangeState(fi, ST_TEI_NOP); } } @@ -387,9 +371,9 @@ if (st->ma.debug) st->ma.tei_m.printdebug(&st->ma.tei_m, "fixed assign tei %d", st->l2.tei); - L3L2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei); + st->l3.l3l2(st, MDL_ASSIGN | REQUEST, (void *) (long) st->l2.tei); cs = (struct IsdnCardState *) st->l1.hardware; - mdl_assign(cs); + cs->cardmsg(cs, MDL_ASSIGN | REQUEST, NULL); } return; } diff -Nru a/drivers/isdn/hisax/teleint.c b/drivers/isdn/hisax/teleint.c --- a/drivers/isdn/hisax/teleint.c Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/hisax/teleint.c Thu Feb 19 23:44:28 2004 @@ -1,4 +1,4 @@ -/* $Id: teleint.c,v 1.14.6.2 2001/09/23 22:24:52 kai Exp $ +/* $Id: teleint.c,v 1.16.2.5 2004/01/19 15:31:50 keil Exp $ * * low level stuff for TeleInt isdn cards * @@ -18,38 +18,33 @@ extern const char *CardType[]; -const char *TeleInt_revision = "$Revision: 1.14.6.2 $"; -static spinlock_t teleint_lock = SPIN_LOCK_UNLOCKED; +const char *TeleInt_revision = "$Revision: 1.16.2.5 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static inline u8 -readreg(unsigned int ale, unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int ale, unsigned int adr, u_char off) { - register u8 ret; + register u_char ret; int max_delay = 2000; - unsigned long flags; - spin_lock_irqsave(&teleint_lock, flags); byteout(ale, off); ret = HFC_BUSY & bytein(ale); while (ret && --max_delay) ret = HFC_BUSY & bytein(ale); if (!max_delay) { printk(KERN_WARNING "TeleInt Busy not inactive\n"); - spin_unlock_irqrestore(&teleint_lock, flags); return (0); } ret = bytein(adr); - spin_unlock_irqrestore(&teleint_lock, flags); return (ret); } static inline void -readfifo(unsigned int ale, unsigned int adr, u8 off, u8 * data, int size) +readfifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - register u8 ret; + register u_char ret; register int max_delay = 20000; register int i; @@ -68,34 +63,29 @@ static inline void -writereg(unsigned int ale, unsigned int adr, u8 off, u8 data) +writereg(unsigned int ale, unsigned int adr, u_char off, u_char data) { - register u8 ret; + register u_char ret; int max_delay = 2000; - unsigned long flags; - spin_lock_irqsave(&teleint_lock, flags); byteout(ale, off); ret = HFC_BUSY & bytein(ale); while (ret && --max_delay) ret = HFC_BUSY & bytein(ale); if (!max_delay) { printk(KERN_WARNING "TeleInt Busy not inactive\n"); - spin_unlock_irqrestore(&teleint_lock, flags); return; } byteout(adr, data); - spin_unlock_irqrestore(&teleint_lock, flags); } static inline void -writefifo(unsigned int ale, unsigned int adr, u8 off, u8 * data, int size) +writefifo(unsigned int ale, unsigned int adr, u_char off, u_char * data, int size) { - register u8 ret; + register u_char ret; register int max_delay = 20000; register int i; - /* fifo write without cli because it's already done */ byteout(ale, off); for (i = 0; ihw.hfc.cip = offset; return (readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, offset)); } static void -WriteISAC(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { cs->hw.hfc.cip = offset; writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, offset, value); } static void -ReadISACfifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { cs->hw.hfc.cip = 0; readfifo(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, 0, data, size); } static void -WriteISACfifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { cs->hw.hfc.cip = 0; writefifo(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, 0, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = ReadISAC, - .write_reg = WriteISAC, - .read_fifo = ReadISACfifo, - .write_fifo = WriteISACfifo, -}; - -static u8 -ReadHFC(struct IsdnCardState *cs, int data, u8 reg) +static u_char +ReadHFC(struct IsdnCardState *cs, int data, u_char reg) { - register u8 ret; + register u_char ret; if (data) { cs->hw.hfc.cip = reg; @@ -163,7 +146,7 @@ } static void -WriteHFC(struct IsdnCardState *cs, int data, u8 reg, u8 value) +WriteHFC(struct IsdnCardState *cs, int data, u_char reg, u_char value) { byteout(cs->hw.hfc.addr | 1, reg); cs->hw.hfc.cip = reg; @@ -173,18 +156,14 @@ debugl1(cs, "hfc W%c %02x %02x", data ? 'D' : 'C', reg, value); } -static struct bc_hw_ops hfc_ops = { - .read_reg = ReadHFC, - .write_reg = WriteHFC, -}; - static irqreturn_t -teleint_interrupt(int intno, void *dev_id, struct pt_regs *regs) +TeleInt_interrupt(int intno, void *dev_id, struct pt_regs *regs) { struct IsdnCardState *cs = dev_id; - u8 val; + u_char val; + u_long flags; - spin_lock(&cs->lock); + spin_lock_irqsave(&cs->lock, flags); val = readreg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_ISTA); Start_ISAC: if (val) @@ -197,7 +176,7 @@ } writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0xFF); writereg(cs->hw.hfc.addr | 1, cs->hw.hfc.addr, ISAC_MASK, 0x0); - spin_unlock(&cs->lock); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } @@ -205,7 +184,9 @@ TeleInt_Timer(struct IsdnCardState *cs) { int stat = 0; - + u_long flags; + + spin_lock_irqsave(&cs->lock, flags); if (cs->bcs[0].mode) { stat |= 1; main_irq_hfc(&cs->bcs[0]); @@ -214,52 +195,83 @@ stat |= 2; main_irq_hfc(&cs->bcs[1]); } - cs->hw.hfc.timer.expires = jiffies + 1; + spin_unlock_irqrestore(&cs->lock, flags); + stat = HZ/100; + if (!stat) + stat = 1; + cs->hw.hfc.timer.expires = jiffies + stat; add_timer(&cs->hw.hfc.timer); } -static void -teleint_release(struct IsdnCardState *cs) +void +release_io_TeleInt(struct IsdnCardState *cs) { del_timer(&cs->hw.hfc.timer); releasehfc(cs); - hisax_release_resources(cs); + if (cs->hw.hfc.addr) + release_region(cs->hw.hfc.addr, 2); } -static int -teleint_reset(struct IsdnCardState *cs) +static void +reset_TeleInt(struct IsdnCardState *cs) { printk(KERN_INFO "TeleInt: resetting card\n"); cs->hw.hfc.cirm |= HFC_RESET; byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset On */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((30*HZ)/1000); + mdelay(10); cs->hw.hfc.cirm &= ~HFC_RESET; byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); /* Reset Off */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout((10*HZ)/1000); - return 0; + mdelay(10); } -static void -teleint_init(struct IsdnCardState *cs) +static int +TeleInt_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - inithfc(cs); - initisac(cs); - cs->hw.hfc.timer.expires = jiffies + 1; - add_timer(&cs->hw.hfc.timer); -} + u_long flags; + int delay; -static struct card_ops teleint_ops = { - .init = teleint_init, - .reset = teleint_reset, - .release = teleint_release, - .irq_func = teleint_interrupt, -}; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_TeleInt(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_TeleInt(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + reset_TeleInt(cs); + inithfc(cs); + clear_pending_isac_ints(cs); + initisac(cs); + /* Reenable all IRQ */ + cs->writeisac(cs, ISAC_MASK, 0); + cs->writeisac(cs, ISAC_CMDR, 0x41); + spin_unlock_irqrestore(&cs->lock, flags); + delay = HZ/100; + if (!delay) + delay = 1; + cs->hw.hfc.timer.expires = jiffies + delay; + add_timer(&cs->hw.hfc.timer); + return(0); + case CARD_TEST: + return(0); + } + return(0); +} -static int __init -teleint_probe(struct IsdnCardState *cs, struct IsdnCard *card) +int __init +setup_TeleInt(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; + char tmp[64]; + + strcpy(tmp, TeleInt_revision); + printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_TELEINT) + return (0); + cs->hw.hfc.addr = card->para[1] & 0x3fe; cs->irq = card->para[0]; cs->hw.hfc.cirm = HFC_CIRM; @@ -272,61 +284,56 @@ cs->hw.hfc.timer.function = (void *) TeleInt_Timer; cs->hw.hfc.timer.data = (long) cs; init_timer(&cs->hw.hfc.timer); - if (!request_io(&cs->rs, cs->hw.hfc.addr, 2, "TeleInt isdn")) - goto err; - + if (!request_region(cs->hw.hfc.addr, 2, "TeleInt isdn")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.hfc.addr, + cs->hw.hfc.addr + 2); + return (0); + } /* HW IO = IO */ byteout(cs->hw.hfc.addr, cs->hw.hfc.addr & 0xff); byteout(cs->hw.hfc.addr | 1, ((cs->hw.hfc.addr & 0x300) >> 8) | 0x54); switch (cs->irq) { - case 3: - cs->hw.hfc.cirm |= HFC_INTA; - break; - case 4: - cs->hw.hfc.cirm |= HFC_INTB; - break; - case 5: - cs->hw.hfc.cirm |= HFC_INTC; - break; - case 7: - cs->hw.hfc.cirm |= HFC_INTD; - break; - case 10: - cs->hw.hfc.cirm |= HFC_INTE; - break; - case 11: - cs->hw.hfc.cirm |= HFC_INTF; - break; - default: - printk(KERN_WARNING "TeleInt: wrong IRQ\n"); - goto err; + case 3: + cs->hw.hfc.cirm |= HFC_INTA; + break; + case 4: + cs->hw.hfc.cirm |= HFC_INTB; + break; + case 5: + cs->hw.hfc.cirm |= HFC_INTC; + break; + case 7: + cs->hw.hfc.cirm |= HFC_INTD; + break; + case 10: + cs->hw.hfc.cirm |= HFC_INTE; + break; + case 11: + cs->hw.hfc.cirm |= HFC_INTF; + break; + default: + printk(KERN_WARNING "TeleInt: wrong IRQ\n"); + release_io_TeleInt(cs); + return (0); } byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.cirm); byteout(cs->hw.hfc.addr | 1, cs->hw.hfc.ctmt); printk(KERN_INFO "TeleInt: defined at 0x%x IRQ %d\n", - cs->hw.hfc.addr, cs->irq); - - cs->card_ops = &teleint_ops; - teleint_reset(cs); - isac_setup(cs, &isac_ops); - hfc_setup(cs, &hfc_ops); - return 0; - - err: - hisax_release_resources(cs); - return -EBUSY; -} - -int __init -setup_TeleInt(struct IsdnCard *card) -{ - char tmp[64]; - - strcpy(tmp, TeleInt_revision); - printk(KERN_INFO "HiSax: TeleInt driver Rev. %s\n", HiSax_getrev(tmp)); + cs->hw.hfc.addr, cs->irq); - if (teleint_probe(card->cs, card) < 0) - return 0; - return 1; + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHFC; + cs->BC_Write_Reg = &WriteHFC; + cs->cardmsg = &TeleInt_card_msg; + cs->irq_func = &TeleInt_interrupt; + ISACVersion(cs, "TeleInt:"); + return (1); } diff -Nru a/drivers/isdn/hisax/teles0.c b/drivers/isdn/hisax/teles0.c --- a/drivers/isdn/hisax/teles0.c Thu Feb 19 23:44:25 2004 +++ b/drivers/isdn/hisax/teles0.c Thu Feb 19 23:44:25 2004 @@ -1,4 +1,4 @@ -/* $Id: teles0.c,v 2.13.6.2 2001/09/23 22:24:52 kai Exp $ +/* $Id: teles0.c,v 2.15.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for Teles Memory IO isdn cards * @@ -23,97 +23,179 @@ extern const char *CardType[]; -const char *teles0_revision = "$Revision: 2.13.6.2 $"; +const char *teles0_revision = "$Revision: 2.15.2.4 $"; #define TELES_IOMEM_SIZE 0x400 #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static u8 -isac_read(struct IsdnCardState *cs, u8 off) +static inline u_char +readisac(unsigned long adr, u_char off) { - return readb(cs->hw.teles0.membase + - ((off & 1) ? 0x2ff : 0x100) + off); + return readb(adr + ((off & 1) ? 0x2ff : 0x100) + off); } -static void -isac_write(struct IsdnCardState *cs, u8 off, u8 data) +static inline void +writeisac(unsigned long adr, u_char off, u_char data) { - writeb(data, cs->hw.teles0.membase + - ((off & 1) ? 0x2ff : 0x100) + off); mb(); + writeb(data, adr + ((off & 1) ? 0x2ff : 0x100) + off); mb(); } -static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +static inline u_char +readhscx(unsigned long adr, int hscx, u_char off) { - int i; - void *ad = cs->hw.teles0.membase + 0x100; + return readb(adr + (hscx ? 0x1c0 : 0x180) + + ((off & 1) ? 0x1ff : 0) + off); +} + +static inline void +writehscx(unsigned long adr, int hscx, u_char off, u_char data) +{ + writeb(data, adr + (hscx ? 0x1c0 : 0x180) + + ((off & 1) ? 0x1ff : 0) + off); mb(); +} + +static inline void +read_fifo_isac(unsigned long adr, u_char * data, int size) +{ + register int i; + register u_char *ad = (u_char *)adr + 0x100; for (i = 0; i < size; i++) data[i] = readb(ad); } -static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +static inline void +write_fifo_isac(unsigned long adr, u_char * data, int size) +{ + register int i; + register u_char *ad = (u_char *)adr + 0x100; + for (i = 0; i < size; i++) { + writeb(data[i], ad); mb(); + } +} + +static inline void +read_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size) +{ + register int i; + register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180)); + for (i = 0; i < size; i++) + data[i] = readb(ad); +} + +static inline void +write_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size) { int i; - void *ad = cs->hw.teles0.membase + 0x100; + register u_char *ad = (u_char *) (adr + (hscx ? 0x1c0 : 0x180)); for (i = 0; i < size; i++) { writeb(data[i], ad); mb(); } } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; +/* Interface functions */ -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 off) +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readb(cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180) + - ((off & 1) ? 0x1ff : 0) + off); + return (readisac(cs->hw.teles0.membase, offset)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 data) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { - writeb(data, cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180) + - ((off & 1) ? 0x1ff : 0) + off); mb(); + writeisac(cs->hw.teles0.membase, offset, value); } static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - int i; - void *ad = cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180); - for (i = 0; i < size; i++) - data[i] = readb(ad); + read_fifo_isac(cs->hw.teles0.membase, data, size); } static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { - int i; - void *ad = cs->hw.teles0.membase + (hscx ? 0x1c0 : 0x180); - for (i = 0; i < size; i++) { - writeb(data[i], ad); - } + write_fifo_isac(cs->hw.teles0.membase, data, size); } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) +{ + return (readhscx(cs->hw.teles0.membase, hscx, offset)); +} + +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) +{ + writehscx(cs->hw.teles0.membase, hscx, offset, value); +} + +/* + * fast interrupt HSCX stuff goes here + */ + +#define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg) +#define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt) + +#include "hscx_irq.c" + +static irqreturn_t +teles0_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ + struct IsdnCardState *cs = dev_id; + u_char val; + u_long flags; + int count = 0; + + spin_lock_irqsave(&cs->lock, flags); + val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readisac(cs->hw.teles0.membase, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + count++; + val = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA); + if (val && count < 5) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readisac(cs->hw.teles0.membase, ISAC_ISTA); + if (val && count < 5) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF); + writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF); + writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF); + writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0); + writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0); + writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} + +void +release_io_teles0(struct IsdnCardState *cs) +{ + if (cs->hw.teles0.cfg_reg) + release_region(cs->hw.teles0.cfg_reg, 8); + iounmap((unsigned char *)cs->hw.teles0.membase); + release_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE); +} static int -teles0_reset(struct IsdnCardState *cs) +reset_teles0(struct IsdnCardState *cs) { - u8 cfval; + u_char cfval; if (cs->hw.teles0.cfg_reg) { switch (cs->irq) { @@ -158,102 +240,129 @@ return(0); } -static struct card_ops teles0_ops = { - .init = inithscxisac, - .reset = teles0_reset, - .release = hisax_release_resources, - .irq_func = hscxisac_irq, -}; - -static int __init -teles0_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->irq = card->para[0]; - /* 16.0 and 8.0 designed for IOM1 */ - test_and_set_bit(HW_IOM1, &cs->HW_Flags); - cs->hw.teles0.phymem = card->para[1]; - cs->hw.teles0.membase = request_mmio(&cs->rs, cs->hw.teles0.phymem, - TELES_IOMEM_SIZE, "teles iomem"); - if (!cs->hw.teles0.membase) - return -EBUSY; - - if (teles0_reset(cs)) { - printk(KERN_WARNING "Teles0: wrong IRQ\n"); - return -EBUSY; - } - cs->card_ops = &teles0_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - return -EBUSY; - - return 0; -} - -static int __init -teles16_0_probe(struct IsdnCardState *cs, struct IsdnCard *card) +static int +Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - u8 val; + u_long flags; - cs->hw.teles0.cfg_reg = card->para[2]; - if (!request_io(&cs->rs, cs->hw.teles0.cfg_reg, 8, "teles cfg")) - goto err; - - if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) { - printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", - cs->hw.teles0.cfg_reg + 0, val); - goto err; - } - if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) { - printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", - cs->hw.teles0.cfg_reg + 1, val); - goto err; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_teles0(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_teles0(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); } - val = bytein(cs->hw.teles0.cfg_reg + 2);/* 0x1e=without AB - * 0x1f=with AB - * 0x1c 16.3 ??? - */ - if (val != 0x1e && val != 0x1f) { - printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", - cs->hw.teles0.cfg_reg + 2, val); - goto err; - } - if (teles0_probe(cs, card) < 0) - goto err; - - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -teles8_0_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->hw.teles0.cfg_reg = 0; - - if (teles0_probe(cs, card) < 0) - goto err; - - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + return(0); } int __init setup_teles0(struct IsdnCard *card) { + u_char val; + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, teles0_revision); - printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", - HiSax_getrev(tmp)); - - if (card->cs->typ == ISDN_CTYPE_16_0) { - if (teles16_0_probe(card->cs, card) < 0) - return 0; - } else { - if (teles8_0_probe(card->cs, card) < 0) - return 0; + printk(KERN_INFO "HiSax: Teles 8.0/16.0 driver Rev. %s\n", HiSax_getrev(tmp)); + if ((cs->typ != ISDN_CTYPE_16_0) && (cs->typ != ISDN_CTYPE_8_0)) + return (0); + + if (cs->typ == ISDN_CTYPE_16_0) + cs->hw.teles0.cfg_reg = card->para[2]; + else /* 8.0 */ + cs->hw.teles0.cfg_reg = 0; + + if (card->para[1] < 0x10000) { + card->para[1] <<= 4; + printk(KERN_INFO + "Teles0: membase configured DOSish, assuming 0x%lx\n", + (unsigned long) card->para[1]); + } + cs->irq = card->para[0]; + if (cs->hw.teles0.cfg_reg) { + if (!request_region(cs->hw.teles0.cfg_reg, 8, "teles cfg")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.teles0.cfg_reg, + cs->hw.teles0.cfg_reg + 8); + return (0); + } + } + if (cs->hw.teles0.cfg_reg) { + if ((val = bytein(cs->hw.teles0.cfg_reg + 0)) != 0x51) { + printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", + cs->hw.teles0.cfg_reg + 0, val); + release_region(cs->hw.teles0.cfg_reg, 8); + return (0); + } + if ((val = bytein(cs->hw.teles0.cfg_reg + 1)) != 0x93) { + printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", + cs->hw.teles0.cfg_reg + 1, val); + release_region(cs->hw.teles0.cfg_reg, 8); + return (0); + } + val = bytein(cs->hw.teles0.cfg_reg + 2); /* 0x1e=without AB + * 0x1f=with AB + * 0x1c 16.3 ??? + */ + if (val != 0x1e && val != 0x1f) { + printk(KERN_WARNING "Teles0: 16.0 Byte at %x is %x\n", + cs->hw.teles0.cfg_reg + 2, val); + release_region(cs->hw.teles0.cfg_reg, 8); + return (0); + } + } + /* 16.0 and 8.0 designed for IOM1 */ + test_and_set_bit(HW_IOM1, &cs->HW_Flags); + cs->hw.teles0.phymem = card->para[1]; + if (!request_mem_region(cs->hw.teles0.phymem, TELES_IOMEM_SIZE, "teles iomem")) { + printk(KERN_WARNING + "HiSax: %s memory region %lx-%lx already in use\n", + CardType[card->typ], + cs->hw.teles0.phymem, + cs->hw.teles0.phymem + TELES_IOMEM_SIZE); + if (cs->hw.teles0.cfg_reg) + release_region(cs->hw.teles0.cfg_reg, 8); + return (0); + } + cs->hw.teles0.membase = + (unsigned long) ioremap(cs->hw.teles0.phymem, TELES_IOMEM_SIZE); + printk(KERN_INFO + "HiSax: %s config irq:%d mem:0x%lX cfg:0x%X\n", + CardType[cs->typ], cs->irq, + cs->hw.teles0.membase, cs->hw.teles0.cfg_reg); + if (reset_teles0(cs)) { + printk(KERN_WARNING "Teles0: wrong IRQ\n"); + release_io_teles0(cs); + return (0); + } + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &Teles_card_msg; + cs->irq_func = &teles0_interrupt; + ISACVersion(cs, "Teles0:"); + if (HscxVersion(cs, "Teles0:")) { + printk(KERN_WARNING + "Teles0: wrong HSCX versions check IO/MEM addresses\n"); + release_io_teles0(cs); + return (0); } - return 1; + return (1); } diff -Nru a/drivers/isdn/hisax/teles3.c b/drivers/isdn/hisax/teles3.c --- a/drivers/isdn/hisax/teles3.c Thu Feb 19 23:44:28 2004 +++ b/drivers/isdn/hisax/teles3.c Thu Feb 19 23:44:28 2004 @@ -1,4 +1,4 @@ -/* $Id: teles3.c,v 2.17.6.2 2001/09/23 22:24:52 kai Exp $ +/* $Id: teles3.c,v 2.19.2.4 2004/01/13 23:48:39 keil Exp $ * * low level stuff for Teles 16.3 & PNP isdn cards * @@ -21,102 +21,160 @@ #include "isdnl1.h" extern const char *CardType[]; -const char *teles3_revision = "$Revision: 2.17.6.2 $"; +const char *teles3_revision = "$Revision: 2.19.2.4 $"; #define byteout(addr,val) outb(val,addr) #define bytein(addr) inb(addr) -static inline u8 -readreg(unsigned int adr, u8 off) +static inline u_char +readreg(unsigned int adr, u_char off) { return (bytein(adr + off)); } static inline void -writereg(unsigned int adr, u8 off, u8 data) +writereg(unsigned int adr, u_char off, u_char data) { byteout(adr + off, data); } static inline void -read_fifo(unsigned int adr, u8 * data, int size) +read_fifo(unsigned int adr, u_char * data, int size) { insb(adr, data, size); } static void -write_fifo(unsigned int adr, u8 * data, int size) +write_fifo(unsigned int adr, u_char * data, int size) { outsb(adr, data, size); } -static u8 -isac_read(struct IsdnCardState *cs, u8 offset) +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) { - return readreg(cs->hw.teles3.isac, offset); + return (readreg(cs->hw.teles3.isac, offset)); } static void -isac_write(struct IsdnCardState *cs, u8 offset, u8 value) +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) { writereg(cs->hw.teles3.isac, offset, value); } static void -isac_read_fifo(struct IsdnCardState *cs, u8 * data, int size) +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) { read_fifo(cs->hw.teles3.isacfifo, data, size); } static void -isac_write_fifo(struct IsdnCardState *cs, u8 * data, int size) +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) { write_fifo(cs->hw.teles3.isacfifo, data, size); } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 offset) +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) { - return readreg(cs->hw.teles3.hscx[hscx], offset); + return (readreg(cs->hw.teles3.hscx[hscx], offset)); } static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 offset, u8 value) +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) { writereg(cs->hw.teles3.hscx[hscx], offset, value); } -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - read_fifo(cs->hw.teles3.hscxfifo[hscx], data, size); -} +/* + * fast interrupt HSCX stuff goes here + */ -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 *data, int size) -{ - write_fifo(cs->hw.teles3.hscxfifo[hscx], data, size); +#define READHSCX(cs, nr, reg) readreg(cs->hw.teles3.hscx[nr], reg) +#define WRITEHSCX(cs, nr, reg, data) writereg(cs->hw.teles3.hscx[nr], reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo(cs->hw.teles3.hscxfifo[nr], ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo(cs->hw.teles3.hscxfifo[nr], ptr, cnt) + +#include "hscx_irq.c" + +static irqreturn_t +teles3_interrupt(int intno, void *dev_id, struct pt_regs *regs) +{ +#define MAXCOUNT 5 + struct IsdnCardState *cs = dev_id; + u_char val; + u_long flags; + int count = 0; + + spin_lock_irqsave(&cs->lock, flags); + val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA); + Start_HSCX: + if (val) + hscx_int_main(cs, val); + val = readreg(cs->hw.teles3.isac, ISAC_ISTA); + Start_ISAC: + if (val) + isac_interrupt(cs, val); + count++; + val = readreg(cs->hw.teles3.hscx[1], HSCX_ISTA); + if (val && count < MAXCOUNT) { + if (cs->debug & L1_DEB_HSCX) + debugl1(cs, "HSCX IntStat after IntRoutine"); + goto Start_HSCX; + } + val = readreg(cs->hw.teles3.isac, ISAC_ISTA); + if (val && count < MAXCOUNT) { + if (cs->debug & L1_DEB_ISAC) + debugl1(cs, "ISAC IntStat after IntRoutine"); + goto Start_ISAC; + } + if (count >= MAXCOUNT) + printk(KERN_WARNING "Teles3: more than %d loops in teles3_interrupt\n", count); + writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0xFF); + writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0xFF); + writereg(cs->hw.teles3.isac, ISAC_MASK, 0xFF); + writereg(cs->hw.teles3.isac, ISAC_MASK, 0x0); + writereg(cs->hw.teles3.hscx[0], HSCX_MASK, 0x0); + writereg(cs->hw.teles3.hscx[1], HSCX_MASK, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_HANDLED; +} + +inline static void +release_ioregs(struct IsdnCardState *cs, int mask) +{ + if (mask & 1) + release_region(cs->hw.teles3.isac + 32, 32); + if (mask & 2) + release_region(cs->hw.teles3.hscx[0] + 32, 32); + if (mask & 4) + release_region(cs->hw.teles3.hscx[1] + 32, 32); +} + +void +release_io_teles3(struct IsdnCardState *cs) +{ + if (cs->typ == ISDN_CTYPE_TELESPCMCIA) { + release_region(cs->hw.teles3.hscx[1], 96); + } else { + if (cs->hw.teles3.cfg_reg) { + if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { + release_region(cs->hw.teles3.cfg_reg, 1); + } else { + release_region(cs->hw.teles3.cfg_reg, 8); + } + } + release_ioregs(cs, 0x7); + } } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; - static int -teles3_reset(struct IsdnCardState *cs) +reset_teles3(struct IsdnCardState *cs) { - u8 irqcfg; + u_char irqcfg; if (cs->typ != ISDN_CTYPE_TELESPCMCIA) { if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) { @@ -169,160 +227,33 @@ return(0); } -static struct card_ops teles3_ops = { - .init = inithscxisac, - .reset = teles3_reset, - .release = hisax_release_resources, - .irq_func = hscxisac_irq, -}; - static int -teles_hw_init(struct IsdnCardState *cs) +Teles_card_msg(struct IsdnCardState *cs, int mt, void *arg) { - - printk(KERN_INFO "HiSax: %s config irq:%d isac:0x%X cfg:0x%X\n", - CardType[cs->typ], cs->irq, - cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg); - printk(KERN_INFO "HiSax: hscx A:0x%X hscx B:0x%X\n", - cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32); + u_long flags; - if (teles3_reset(cs)) { - printk(KERN_WARNING "Teles3: wrong IRQ\n"); - return -EBUSY; + switch (mt) { + case CARD_RESET: + spin_lock_irqsave(&cs->lock, flags); + reset_teles3(cs); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_RELEASE: + release_io_teles3(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); } - cs->card_ops = &teles3_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - return -EBUSY; - return 0; -} - -static void __init -teles_setup_io(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->irq = card->para[0]; - cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e; - cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e; - cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e; -} - -static int __init -telespcmcia_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->hw.teles3.cfg_reg = 0; - cs->hw.teles3.hscx[0] = card->para[1] - 0x20; - cs->hw.teles3.hscx[1] = card->para[1]; - cs->hw.teles3.isac = card->para[1] + 0x20; - teles_setup_io(cs, card); - if (!request_io(&cs->rs, cs->hw.teles3.hscx[1], 96, - "HiSax Teles PCMCIA")) - goto err; - if (teles_hw_init(cs) < 0) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -teles_request_io(struct IsdnCardState *cs) -{ - if (!request_io(&cs->rs, cs->hw.teles3.isac + 32, 32, "HiSax isac")) - return -EBUSY; - if (!request_io(&cs->rs, cs->hw.teles3.hscx[0]+32, 32, "HiSax hscx A")) - return -EBUSY; - if (!request_io(&cs->rs, cs->hw.teles3.hscx[1]+32, 32, "HiSax hscx B")) - return -EBUSY; - return 0; -} - -static int __init -teles16_3_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - u8 val; - - cs->hw.teles3.cfg_reg = card->para[1]; - switch (cs->hw.teles3.cfg_reg) { - case 0x180: - case 0x280: - case 0x380: - cs->hw.teles3.cfg_reg |= 0xc00; - break; - } - cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420; - cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20; - cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820; - teles_setup_io(cs, card); - if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 8, "teles3 cfg")) - goto err; - if (teles_request_io(cs) < 0) - goto err; - if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) { - printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", - cs->hw.teles3.cfg_reg + 0, val); - goto err; - } - if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) { - printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", - cs->hw.teles3.cfg_reg + 1, val); - goto err; - } - /* 0x1e without AB, 0x1f with AB, 0x1c 16.3 ???, - * 0x39 16.3 1.1, 0x38 16.3 1.3, 0x46 16.3 with AB + Video */ - val = bytein(cs->hw.teles3.cfg_reg + 2); - if (val != 0x46 && val != 0x39 && val != 0x38 && - val != 0x1c && val != 0x1e && val != 0x1f) { - printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", - cs->hw.teles3.cfg_reg + 2, val); - goto err; - } - if (teles_hw_init(cs) < 0) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -compaq_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->hw.teles3.cfg_reg = card->para[3]; - cs->hw.teles3.isac = card->para[2] - 32; - cs->hw.teles3.hscx[0] = card->para[1] - 32; - cs->hw.teles3.hscx[1] = card->para[1]; - teles_setup_io(cs, card); - if (!request_io(&cs->rs, cs->hw.teles3.cfg_reg, 1, "teles3 cfg")) - goto err; - if (teles_request_io(cs) < 0) - goto err; - if (teles_hw_init(cs) < 0) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; -} - -static int __init -telespnp_probe(struct IsdnCardState *cs, struct IsdnCard *card) -{ - cs->hw.teles3.cfg_reg = 0; - cs->hw.teles3.isac = card->para[1] - 32; - cs->hw.teles3.hscx[0] = card->para[2] - 32; - cs->hw.teles3.hscx[1] = card->para[2]; - teles_setup_io(cs, card); - if (teles_request_io(cs) < 0) - goto err; - if (teles_hw_init(cs) < 0) - goto err; - return 0; - err: - hisax_release_resources(cs); - return -EBUSY; + return(0); } #ifdef __ISAPNP__ + static struct isapnp_device_id teles_ids[] __initdata = { { ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110), ISAPNP_VENDOR('T', 'A', 'G'), ISAPNP_FUNCTION(0x2110), @@ -336,80 +267,233 @@ { 0, } }; -static struct isapnp_device_id *tdev = &teles_ids[0]; +static struct isapnp_device_id *ipid __initdata = &teles_ids[0]; static struct pnp_card *pnp_c __devinitdata = NULL; #endif int __devinit setup_teles3(struct IsdnCard *card) { + u_char val; + struct IsdnCardState *cs = card->cs; char tmp[64]; strcpy(tmp, teles3_revision); printk(KERN_INFO "HiSax: Teles IO driver Rev. %s\n", HiSax_getrev(tmp)); + if ((cs->typ != ISDN_CTYPE_16_3) && (cs->typ != ISDN_CTYPE_PNP) + && (cs->typ != ISDN_CTYPE_TELESPCMCIA) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) + return (0); + #ifdef __ISAPNP__ if (!card->para[1] && isapnp_present()) { - struct pnp_card *pnp_card; - struct pnp_dev *pnp_dev; + struct pnp_dev *pnp_d; + while(ipid->card_vendor) { + if ((pnp_c = pnp_find_card(ipid->card_vendor, + ipid->card_device, pnp_c))) { + pnp_d = NULL; + if ((pnp_d = pnp_find_dev(pnp_c, + ipid->vendor, ipid->function, pnp_d))) { + int err; - while(tdev->card_vendor) { - if ((pnp_card = pnp_find_card(tdev->card_vendor, - tdev->card_device, pnp_c))) { - pnp_c = pnp_card; - pnp_dev = NULL; - if ((pnp_dev = pnp_find_dev(pnp_card, - tdev->vendor, - tdev->function, - pnp_dev))) { printk(KERN_INFO "HiSax: %s detected\n", - (char *)tdev->driver_data); - if (pnp_device_attach(pnp_dev) < 0) { - printk(KERN_ERR "Teles PnP: attach failed\n"); - return 0; - } - if (pnp_activate_dev(pnp_dev) < 0) { - printk(KERN_ERR "Teles PnP: activate failed\n"); - pnp_device_detach(pnp_dev); - return 0; + (char *)ipid->driver_data); + pnp_disable_dev(pnp_d); + err = pnp_activate_dev(pnp_d); + if (err<0) { + printk(KERN_WARNING "%s: pnp_activate_dev ret(%d)\n", + __FUNCTION__, err); + return(0); } - if (!pnp_irq_valid(pnp_dev, 0) || - !pnp_port_valid(pnp_dev, 0) || - !pnp_port_valid(pnp_dev, 1)) { - printk(KERN_ERR "Teles PnP: some resources are missing %ld/%lx/%lx\n", - pnp_irq(pnp_dev, 0), pnp_port_start(pnp_dev, 0), pnp_port_start(pnp_dev, 1)); - pnp_device_detach(pnp_dev); - return 0; + card->para[3] = pnp_port_start(pnp_d, 2); + card->para[2] = pnp_port_start(pnp_d, 1); + card->para[1] = pnp_port_start(pnp_d, 0); + card->para[0] = pnp_irq(pnp_d, 0); + if (!card->para[0] || !card->para[1] || !card->para[2]) { + printk(KERN_ERR "Teles PnP:some resources are missing %ld/%lx/%lx\n", + card->para[0], card->para[1], card->para[2]); + pnp_disable_dev(pnp_d); + return(0); } - card->para[3] = pnp_port_start(pnp_dev, 2); - card->para[2] = pnp_port_start(pnp_dev, 1); - card->para[1] = pnp_port_start(pnp_dev, 0); - card->para[0] = pnp_irq(pnp_dev, 0); break; } else { printk(KERN_ERR "Teles PnP: PnP error card found, no device\n"); } } - tdev++; - pnp_c=NULL; + ipid++; + pnp_c = NULL; } - if (!tdev->card_vendor) { + if (!ipid->card_vendor) { printk(KERN_INFO "Teles PnP: no ISAPnP card found\n"); return(0); } } #endif - if (card->cs->typ == ISDN_CTYPE_16_3) { - if (teles16_3_probe(card->cs, card) < 0) - return 0; - } else if (card->cs->typ == ISDN_CTYPE_TELESPCMCIA) { - if (telespcmcia_probe(card->cs, card) < 0) - return 0; - } else if (card->cs->typ == ISDN_CTYPE_COMPAQ_ISA) { - if (compaq_probe(card->cs, card) < 0) - return 0; + if (cs->typ == ISDN_CTYPE_16_3) { + cs->hw.teles3.cfg_reg = card->para[1]; + switch (cs->hw.teles3.cfg_reg) { + case 0x180: + case 0x280: + case 0x380: + cs->hw.teles3.cfg_reg |= 0xc00; + break; + } + cs->hw.teles3.isac = cs->hw.teles3.cfg_reg - 0x420; + cs->hw.teles3.hscx[0] = cs->hw.teles3.cfg_reg - 0xc20; + cs->hw.teles3.hscx[1] = cs->hw.teles3.cfg_reg - 0x820; + } else if (cs->typ == ISDN_CTYPE_TELESPCMCIA) { + cs->hw.teles3.cfg_reg = 0; + cs->hw.teles3.hscx[0] = card->para[1] - 0x20; + cs->hw.teles3.hscx[1] = card->para[1]; + cs->hw.teles3.isac = card->para[1] + 0x20; + } else if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { + cs->hw.teles3.cfg_reg = card->para[3]; + cs->hw.teles3.isac = card->para[2] - 32; + cs->hw.teles3.hscx[0] = card->para[1] - 32; + cs->hw.teles3.hscx[1] = card->para[1]; } else { /* PNP */ - if (telespnp_probe(card->cs, card) < 0) - return 0; + cs->hw.teles3.cfg_reg = 0; + cs->hw.teles3.isac = card->para[1] - 32; + cs->hw.teles3.hscx[0] = card->para[2] - 32; + cs->hw.teles3.hscx[1] = card->para[2]; + } + cs->irq = card->para[0]; + cs->hw.teles3.isacfifo = cs->hw.teles3.isac + 0x3e; + cs->hw.teles3.hscxfifo[0] = cs->hw.teles3.hscx[0] + 0x3e; + cs->hw.teles3.hscxfifo[1] = cs->hw.teles3.hscx[1] + 0x3e; + if (cs->typ == ISDN_CTYPE_TELESPCMCIA) { + if (!request_region(cs->hw.teles3.hscx[1], 96, "HiSax Teles PCMCIA")) { + printk(KERN_WARNING + "HiSax: %s ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.teles3.hscx[1], + cs->hw.teles3.hscx[1] + 96); + return (0); + } + } else { + if (cs->hw.teles3.cfg_reg) { + if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { + if (!request_region(cs->hw.teles3.cfg_reg, 1, "teles3 cfg")) { + printk(KERN_WARNING + "HiSax: %s config port %x already in use\n", + CardType[card->typ], + cs->hw.teles3.cfg_reg); + return (0); + } + } else { + if (!request_region(cs->hw.teles3.cfg_reg, 8, "teles3 cfg")) { + printk(KERN_WARNING + "HiSax: %s config port %x-%x already in use\n", + CardType[card->typ], + cs->hw.teles3.cfg_reg, + cs->hw.teles3.cfg_reg + 8); + return (0); + } + } + } + if (!request_region(cs->hw.teles3.isac + 32, 32, "HiSax isac")) { + printk(KERN_WARNING + "HiSax: %s isac ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.teles3.isac + 32, + cs->hw.teles3.isac + 64); + if (cs->hw.teles3.cfg_reg) { + if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { + release_region(cs->hw.teles3.cfg_reg, 1); + } else { + release_region(cs->hw.teles3.cfg_reg, 8); + } + } + return (0); + } + if (!request_region(cs->hw.teles3.hscx[0] + 32, 32, "HiSax hscx A")) { + printk(KERN_WARNING + "HiSax: %s hscx A ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.teles3.hscx[0] + 32, + cs->hw.teles3.hscx[0] + 64); + if (cs->hw.teles3.cfg_reg) { + if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { + release_region(cs->hw.teles3.cfg_reg, 1); + } else { + release_region(cs->hw.teles3.cfg_reg, 8); + } + } + release_ioregs(cs, 1); + return (0); + } + if (!request_region(cs->hw.teles3.hscx[1] + 32, 32, "HiSax hscx B")) { + printk(KERN_WARNING + "HiSax: %s hscx B ports %x-%x already in use\n", + CardType[cs->typ], + cs->hw.teles3.hscx[1] + 32, + cs->hw.teles3.hscx[1] + 64); + if (cs->hw.teles3.cfg_reg) { + if (cs->typ == ISDN_CTYPE_COMPAQ_ISA) { + release_region(cs->hw.teles3.cfg_reg, 1); + } else { + release_region(cs->hw.teles3.cfg_reg, 8); + } + } + release_ioregs(cs, 3); + return (0); + } + } + if ((cs->hw.teles3.cfg_reg) && (cs->typ != ISDN_CTYPE_COMPAQ_ISA)) { + if ((val = bytein(cs->hw.teles3.cfg_reg + 0)) != 0x51) { + printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", + cs->hw.teles3.cfg_reg + 0, val); + release_io_teles3(cs); + return (0); + } + if ((val = bytein(cs->hw.teles3.cfg_reg + 1)) != 0x93) { + printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", + cs->hw.teles3.cfg_reg + 1, val); + release_io_teles3(cs); + return (0); + } + val = bytein(cs->hw.teles3.cfg_reg + 2);/* 0x1e=without AB + * 0x1f=with AB + * 0x1c 16.3 ??? + * 0x39 16.3 1.1 + * 0x38 16.3 1.3 + * 0x46 16.3 with AB + Video (Teles-Vision) + */ + if (val != 0x46 && val != 0x39 && val != 0x38 && val != 0x1c && val != 0x1e && val != 0x1f) { + printk(KERN_WARNING "Teles: 16.3 Byte at %x is %x\n", + cs->hw.teles3.cfg_reg + 2, val); + release_io_teles3(cs); + return (0); + } + } + printk(KERN_INFO + "HiSax: %s config irq:%d isac:0x%X cfg:0x%X\n", + CardType[cs->typ], cs->irq, + cs->hw.teles3.isac + 32, cs->hw.teles3.cfg_reg); + printk(KERN_INFO + "HiSax: hscx A:0x%X hscx B:0x%X\n", + cs->hw.teles3.hscx[0] + 32, cs->hw.teles3.hscx[1] + 32); + + setup_isac(cs); + if (reset_teles3(cs)) { + printk(KERN_WARNING "Teles3: wrong IRQ\n"); + release_io_teles3(cs); + return (0); + } + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &Teles_card_msg; + cs->irq_func = &teles3_interrupt; + ISACVersion(cs, "Teles3:"); + if (HscxVersion(cs, "Teles3:")) { + printk(KERN_WARNING + "Teles3: wrong HSCX versions check IO address\n"); + release_io_teles3(cs); + return (0); } - return 1; + return (1); } diff -Nru a/drivers/isdn/hisax/teles_cs.c b/drivers/isdn/hisax/teles_cs.c --- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/isdn/hisax/teles_cs.c Thu Feb 19 23:44:29 2004 @@ -0,0 +1,549 @@ +/* $Id: teles_cs.c,v 1.1.2.2 2004/01/25 15:07:06 keil Exp $ */ +/*====================================================================== + + A teles S0 PCMCIA client driver + + Based on skeleton by David Hinds, dhinds@allegro.stanford.edu + Written by Christof Petig, christof.petig@wtal.de + + Also inspired by ELSA PCMCIA driver + by Klaus Lichtenwalder + + Extentions to new hisax_pcmcia by Karsten Keil + + minor changes to be compatible with kernel 2.4.x + by Jan.Schubert@GMX.li + +======================================================================*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "hisax_cfg.h" + +MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Teles PCMCIA cards"); +MODULE_AUTHOR("Christof Petig, christof.petig@wtal.de, Karsten Keil, kkeil@suse.de"); +MODULE_LICENSE("GPL"); + +/* + All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If + you do not define PCMCIA_DEBUG at all, all the debug code will be + left out. If you compile with PCMCIA_DEBUG=0, the debug code will + be present but disabled -- but it can then be enabled for specific + modules at load time with a 'pc_debug=#' option to insmod. +*/ + +#ifdef PCMCIA_DEBUG +static int pc_debug = PCMCIA_DEBUG; +MODULE_PARM(pc_debug, "i"); +#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); +static char *version = +"teles_cs.c 2.10 2002/07/30 22:23:34 kkeil"; +#else +#define DEBUG(n, args...) +#endif + +/*====================================================================*/ + +/* Parameters that can be set with 'insmod' */ + +/* Bit map of interrupts to choose from, the old way */ +/* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, 3 */ +static u_long irq_mask = 0xdeb8; + +/* Newer, simpler way of listing specific interrupts */ +static int irq_list[4] = { -1 }; + +MODULE_PARM(irq_mask, "i"); +MODULE_PARM(irq_list, "1-4i"); + +static int protocol = 2; /* EURO-ISDN Default */ +MODULE_PARM(protocol, "i"); + +/*====================================================================*/ + +/* + The event() function is this driver's Card Services event handler. + It will be called by Card Services when an appropriate card status + event is received. The config() and release() entry points are + used to configure or release a socket, in response to card insertion + and ejection events. They are invoked from the teles_cs event + handler. +*/ + +static void teles_cs_config(dev_link_t *link); +static void teles_cs_release(dev_link_t *link); +static int teles_cs_event(event_t event, int priority, + event_callback_args_t *args); + +/* + The attach() and detach() entry points are used to create and destroy + "instances" of the driver, where each instance represents everything + needed to manage one actual PCMCIA card. +*/ + +static dev_link_t *teles_attach(void); +static void teles_detach(dev_link_t *); + +/* + The dev_info variable is the "key" that is used to match up this + device driver with appropriate cards, through the card configuration + database. +*/ + +static dev_info_t dev_info = "teles_cs"; + +/* + A linked list of "instances" of the teles_cs device. Each actual + PCMCIA card corresponds to one device instance, and is described + by one dev_link_t structure (defined in ds.h). + + You may not want to use a linked list for this -- for example, the + memory card driver uses an array of dev_link_t pointers, where minor + device numbers are used to derive the corresponding array index. +*/ + +static dev_link_t *dev_list = NULL; + +/* + A dev_link_t structure has fields for most things that are needed + to keep track of a socket, but there will usually be some device + specific information that also needs to be kept track of. The + 'priv' pointer in a dev_link_t structure can be used to point to + a device-specific private data structure, like this. + + To simplify the data structure handling, we actually include the + dev_link_t structure in the device's private data structure. + + A driver needs to provide a dev_node_t structure for each device + on a card. In some cases, there is only one device per card (for + example, ethernet cards, modems). In other cases, there may be + many actual or logical devices (SCSI adapters, memory cards with + multiple partitions). The dev_node_t structures need to be kept + in a linked list starting at the 'dev' field of a dev_link_t + structure. We allocate them in the card's private data structure, + because they generally shouldn't be allocated dynamically. + In this case, we also provide a flag to indicate if a device is + "stopped" due to a power management event, or card ejection. The + device IO routines can use a flag like this to throttle IO to a + card that is not ready to accept it. +*/ + +typedef struct local_info_t { + dev_link_t link; + dev_node_t node; + int busy; + int cardnr; +} local_info_t; + +/*====================================================================== + + teles_attach() creates an "instance" of the driver, allocatingx + local data structures for one device. The device is registered + with Card Services. + + The dev_link structure is initialized, but we don't actually + configure the card at this point -- we wait until we receive a + card insertion event. + +======================================================================*/ + +static dev_link_t *teles_attach(void) +{ + client_reg_t client_reg; + dev_link_t *link; + local_info_t *local; + int ret, i; + + DEBUG(0, "teles_attach()\n"); + + /* Allocate space for private device-specific data */ + local = kmalloc(sizeof(local_info_t), GFP_KERNEL); + if (!local) return NULL; + memset(local, 0, sizeof(local_info_t)); + local->cardnr = -1; + link = &local->link; link->priv = local; + + /* Interrupt setup */ + link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED; + link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID|IRQ_SHARE_ID; + if (irq_list[0] == -1) + link->irq.IRQInfo2 = irq_mask; + else + for (i = 0; i < 4; i++) + link->irq.IRQInfo2 |= 1 << irq_list[i]; + link->irq.Handler = NULL; + + /* + General socket configuration defaults can go here. In this + client, we assume very little, and rely on the CIS for almost + everything. In most clients, many details (i.e., number, sizes, + and attributes of IO windows) are fixed by the nature of the + device, and can be hard-wired here. + */ + link->io.NumPorts1 = 96; + link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; + link->io.IOAddrLines = 5; + + link->conf.Attributes = CONF_ENABLE_IRQ; + link->conf.Vcc = 50; + link->conf.IntType = INT_MEMORY_AND_IO; + + /* Register with Card Services */ + link->next = dev_list; + dev_list = link; + client_reg.dev_info = &dev_info; + client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE; + client_reg.EventMask = + CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL | + CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET | + CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME; + client_reg.event_handler = &teles_cs_event; + client_reg.Version = 0x0210; + client_reg.event_callback_args.client_data = link; + ret = pcmcia_register_client(&link->handle, &client_reg); + if (ret != CS_SUCCESS) { + cs_error(link->handle, RegisterClient, ret); + teles_detach(link); + return NULL; + } + + return link; +} /* teles_attach */ + +/*====================================================================== + + This deletes a driver "instance". The device is de-registered + with Card Services. If it has been released, all local data + structures are freed. Otherwise, the structures will be freed + when the device is released. + +======================================================================*/ + +static void teles_detach(dev_link_t *link) +{ + dev_link_t **linkp; + local_info_t *info = link->priv; + int ret; + + DEBUG(0, "teles_detach(0x%p)\n", link); + + /* Locate device structure */ + for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) + if (*linkp == link) break; + if (*linkp == NULL) + return; + + if (link->state & DEV_CONFIG) + teles_cs_release(link); + + /* + If the device is currently configured and active, we won't + actually delete it yet. Instead, it is marked so that when + the release() function is called, that will trigger a proper + detach(). + */ + if (link->state & DEV_CONFIG) { + DEBUG(0, "teles_cs: detach postponed, '%s' " + "still locked\n", link->dev->dev_name); + link->state |= DEV_STALE_LINK; + return; + } + + /* Break the link with Card Services */ + if (link->handle) { + ret = pcmcia_deregister_client(link->handle); + if (ret != CS_SUCCESS) + cs_error(link->handle, DeregisterClient, ret); + } + + /* Unlink device structure and free it */ + *linkp = link->next; + kfree(info); + +} /* teles_detach */ + +/*====================================================================== + + teles_cs_config() is scheduled to run after a CARD_INSERTION event + is received, to configure the PCMCIA socket, and to make the + device available to the system. + +======================================================================*/ +static int get_tuple(client_handle_t handle, tuple_t *tuple, + cisparse_t *parse) +{ + int i = pcmcia_get_tuple_data(handle, tuple); + if (i != CS_SUCCESS) return i; + return pcmcia_parse_tuple(handle, tuple, parse); +} + +static int first_tuple(client_handle_t handle, tuple_t *tuple, + cisparse_t *parse) +{ + int i = pcmcia_get_first_tuple(handle, tuple); + if (i != CS_SUCCESS) return i; + return get_tuple(handle, tuple, parse); +} + +static int next_tuple(client_handle_t handle, tuple_t *tuple, + cisparse_t *parse) +{ + int i = pcmcia_get_next_tuple(handle, tuple); + if (i != CS_SUCCESS) return i; + return get_tuple(handle, tuple, parse); +} + +static void teles_cs_config(dev_link_t *link) +{ + client_handle_t handle; + tuple_t tuple; + cisparse_t parse; + local_info_t *dev; + int i, j, last_fn; + u_short buf[128]; + cistpl_cftable_entry_t *cf = &parse.cftable_entry; + IsdnCard_t icard; + + DEBUG(0, "teles_config(0x%p)\n", link); + handle = link->handle; + dev = link->priv; + + /* + This reads the card's CONFIG tuple to find its configuration + registers. + */ + tuple.DesiredTuple = CISTPL_CONFIG; + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleDataMax = 255; + tuple.TupleOffset = 0; + tuple.Attributes = 0; + i = first_tuple(handle, &tuple, &parse); + if (i != CS_SUCCESS) { + last_fn = ParseTuple; + goto cs_failed; + } + link->conf.ConfigBase = parse.config.base; + link->conf.Present = parse.config.rmask[0]; + + /* Configure card */ + link->state |= DEV_CONFIG; + + tuple.TupleData = (cisdata_t *)buf; + tuple.TupleOffset = 0; tuple.TupleDataMax = 255; + tuple.Attributes = 0; + tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; + i = first_tuple(handle, &tuple, &parse); + while (i == CS_SUCCESS) { + if ( (cf->io.nwin > 0) && cf->io.win[0].base) { + printk(KERN_INFO "(teles_cs: looks like the 96 model)\n"); + link->conf.ConfigIndex = cf->index; + link->io.BasePort1 = cf->io.win[0].base; + i = pcmcia_request_io(link->handle, &link->io); + if (i == CS_SUCCESS) break; + } else { + printk(KERN_INFO "(teles_cs: looks like the 97 model)\n"); + link->conf.ConfigIndex = cf->index; + for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) { + link->io.BasePort1 = j; + i = pcmcia_request_io(link->handle, &link->io); + if (i == CS_SUCCESS) break; + } + break; + } + i = next_tuple(handle, &tuple, &parse); + } + + if (i != CS_SUCCESS) { + last_fn = RequestIO; + goto cs_failed; + } + + i = pcmcia_request_irq(link->handle, &link->irq); + if (i != CS_SUCCESS) { + link->irq.AssignedIRQ = 0; + last_fn = RequestIRQ; + goto cs_failed; + } + + i = pcmcia_request_configuration(link->handle, &link->conf); + if (i != CS_SUCCESS) { + last_fn = RequestConfiguration; + goto cs_failed; + } + + /* At this point, the dev_node_t structure(s) should be + initialized and arranged in a linked list at link->dev. *//* */ + sprintf(dev->node.dev_name, "teles"); + dev->node.major = dev->node.minor = 0x0; + + link->dev = &dev->node; + + /* Finally, report what we've done */ + printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d", + dev->node.dev_name, link->conf.ConfigIndex, + link->conf.Vcc/10, link->conf.Vcc%10); + if (link->conf.Vpp1) + printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10); + if (link->conf.Attributes & CONF_ENABLE_IRQ) + printk(", irq %d", link->irq.AssignedIRQ); + if (link->io.NumPorts1) + printk(", io 0x%04x-0x%04x", link->io.BasePort1, + link->io.BasePort1+link->io.NumPorts1-1); + if (link->io.NumPorts2) + printk(" & 0x%04x-0x%04x", link->io.BasePort2, + link->io.BasePort2+link->io.NumPorts2-1); + printk("\n"); + + link->state &= ~DEV_CONFIG_PENDING; + + icard.para[0] = link->irq.AssignedIRQ; + icard.para[1] = link->io.BasePort1; + icard.protocol = protocol; + icard.typ = ISDN_CTYPE_TELESPCMCIA; + + i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard); + if (i < 0) { + printk(KERN_ERR "teles_cs: failed to initialize Teles PCMCIA %d at i/o %#x\n", + i, link->io.BasePort1); + teles_cs_release(link); + } else + ((local_info_t*)link->priv)->cardnr = i; + + return; +cs_failed: + cs_error(link->handle, last_fn, i); + teles_cs_release(link); +} /* teles_cs_config */ + +/*====================================================================== + + After a card is removed, teles_cs_release() will unregister the net + device, and release the PCMCIA configuration. If the device is + still open, this will be postponed until it is closed. + +======================================================================*/ + +static void teles_cs_release(dev_link_t *link) +{ + local_info_t *local = link->priv; + + DEBUG(0, "teles_cs_release(0x%p)\n", link); + + if (local) { + if (local->cardnr >= 0) { + /* no unregister function with hisax */ + HiSax_closecard(local->cardnr); + } + } + /* Unlink the device chain */ + link->dev = NULL; + + /* Don't bother checking to see if these succeed or not */ + if (link->win) + pcmcia_release_window(link->win); + pcmcia_release_configuration(link->handle); + pcmcia_release_io(link->handle, &link->io); + pcmcia_release_irq(link->handle, &link->irq); + link->state &= ~DEV_CONFIG; + + if (link->state & DEV_STALE_LINK) + teles_detach(link); + +} /* teles_cs_release */ + +/*====================================================================== + + The card status event handler. Mostly, this schedules other + stuff to run after an event is received. A CARD_REMOVAL event + also sets some flags to discourage the net drivers from trying + to talk to the card any more. + + When a CARD_REMOVAL event is received, we immediately set a flag + to block future accesses to this device. All the functions that + actually access the device should check this flag to make sure + the card is still present. + +======================================================================*/ + +static int teles_cs_event(event_t event, int priority, + event_callback_args_t *args) +{ + dev_link_t *link = args->client_data; + local_info_t *dev = link->priv; + + DEBUG(1, "teles_cs_event(%d)\n", event); + + switch (event) { + case CS_EVENT_CARD_REMOVAL: + link->state &= ~DEV_PRESENT; + if (link->state & DEV_CONFIG) { + ((local_info_t*)link->priv)->busy = 1; + teles_cs_release(link); + } + break; + case CS_EVENT_CARD_INSERTION: + link->state |= DEV_PRESENT | DEV_CONFIG_PENDING; + teles_cs_config(link); + break; + case CS_EVENT_PM_SUSPEND: + link->state |= DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_RESET_PHYSICAL: + /* Mark the device as stopped, to block IO until later */ + dev->busy = 1; + if (link->state & DEV_CONFIG) + pcmcia_release_configuration(link->handle); + break; + case CS_EVENT_PM_RESUME: + link->state &= ~DEV_SUSPEND; + /* Fall through... */ + case CS_EVENT_CARD_RESET: + if (link->state & DEV_CONFIG) + pcmcia_request_configuration(link->handle, &link->conf); + dev->busy = 0; + break; + } + return 0; +} /* teles_cs_event */ + +static struct pcmcia_driver teles_cs_driver = { + .owner = THIS_MODULE, + .drv = { + .name = "teles_cs", + }, + .attach = teles_attach, + .detach = teles_detach, +}; + +static int __init init_teles_cs(void) +{ + return pcmcia_register_driver(&teles_cs_driver); +} + +static void __exit exit_teles_cs(void) +{ + pcmcia_unregister_driver(&teles_cs_driver); + + /* XXX: this really needs to move into generic code.. */ + while (dev_list != NULL) + teles_detach(dev_list); +} + +module_init(init_teles_cs); +module_exit(exit_teles_cs); diff -Nru a/drivers/isdn/hisax/telespci.c b/drivers/isdn/hisax/telespci.c --- a/drivers/isdn/hisax/telespci.c Thu Feb 19 23:44:26 2004 +++ b/drivers/isdn/hisax/telespci.c Thu Feb 19 23:44:26 2004 @@ -1,4 +1,4 @@ -/* $Id: telespci.c,v 2.16.6.5 2001/09/23 22:24:52 kai Exp $ +/* $Id: telespci.c,v 2.23.2.3 2004/01/13 14:31:26 keil Exp $ * * low level stuff for Teles PCI isdn cards * @@ -21,7 +21,7 @@ #include extern const char *CardType[]; -const char *telespci_revision = "$Revision: 2.16.6.5 $"; +const char *telespci_revision = "$Revision: 2.23.2.3 $"; #define ZORAN_PO_RQ_PEN 0x02000000 #define ZORAN_PO_WR 0x00800000 @@ -39,233 +39,250 @@ #define WRITE_DATA_HSCX (ZORAN_PO_WR | ZORAN_PO_GID1 | ZORAN_PO_GREG1) #define ZORAN_WAIT_NOBUSY do { \ - portdata = readl(adr); \ + portdata = readl(adr + 0x200); \ } while (portdata & ZORAN_PO_RQ_PEN) -static u8 -isac_read(struct IsdnCardState *cs, u8 off) +static inline u_char +readisac(unsigned long adr, u_char off) { - void *adr = cs->hw.teles0.membase + 0x200; - unsigned int portdata; + register unsigned int portdata; ZORAN_WAIT_NOBUSY; /* set address for ISAC */ - writel(WRITE_ADDR_ISAC | off, adr); + writel(WRITE_ADDR_ISAC | off, adr + 0x200); ZORAN_WAIT_NOBUSY; /* read data from ISAC */ - writel(READ_DATA_ISAC, adr); + writel(READ_DATA_ISAC, adr + 0x200); ZORAN_WAIT_NOBUSY; - return((u8)(portdata & ZORAN_PO_DMASK)); + return((u_char)(portdata & ZORAN_PO_DMASK)); } -static void -isac_write(struct IsdnCardState *cs, u8 off, u8 data) +static inline void +writeisac(unsigned long adr, u_char off, u_char data) { - void *adr = cs->hw.teles0.membase + 0x200; - unsigned int portdata; + register unsigned int portdata; ZORAN_WAIT_NOBUSY; /* set address for ISAC */ - writel(WRITE_ADDR_ISAC | off, adr); + writel(WRITE_ADDR_ISAC | off, adr + 0x200); ZORAN_WAIT_NOBUSY; /* write data to ISAC */ - writel(WRITE_DATA_ISAC | data, adr); + writel(WRITE_DATA_ISAC | data, adr + 0x200); ZORAN_WAIT_NOBUSY; } -static void -isac_read_fifo(struct IsdnCardState *cs, u8 *data, int size) +static inline u_char +readhscx(unsigned long adr, int hscx, u_char off) { - void *adr = cs->hw.teles0.membase + 0x200; - unsigned int portdata; - int i; + register unsigned int portdata; + + ZORAN_WAIT_NOBUSY; + /* set address for HSCX */ + writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200); + ZORAN_WAIT_NOBUSY; + + /* read data from HSCX */ + writel(READ_DATA_HSCX, adr + 0x200); + ZORAN_WAIT_NOBUSY; + return ((u_char)(portdata & ZORAN_PO_DMASK)); +} + +static inline void +writehscx(unsigned long adr, int hscx, u_char off, u_char data) +{ + register unsigned int portdata; + + ZORAN_WAIT_NOBUSY; + /* set address for HSCX */ + writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr + 0x200); + ZORAN_WAIT_NOBUSY; + + /* write data to HSCX */ + writel(WRITE_DATA_HSCX | data, adr + 0x200); + ZORAN_WAIT_NOBUSY; +} + +static inline void +read_fifo_isac(unsigned long adr, u_char * data, int size) +{ + register unsigned int portdata; + register int i; ZORAN_WAIT_NOBUSY; /* read data from ISAC */ for (i = 0; i < size; i++) { /* set address for ISAC fifo */ - writel(WRITE_ADDR_ISAC | 0x1E, adr); + writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200); ZORAN_WAIT_NOBUSY; - writel(READ_DATA_ISAC, adr); + writel(READ_DATA_ISAC, adr + 0x200); ZORAN_WAIT_NOBUSY; - data[i] = (u8)(portdata & ZORAN_PO_DMASK); + data[i] = (u_char)(portdata & ZORAN_PO_DMASK); } } static void -isac_write_fifo(struct IsdnCardState *cs, u8 *data, int size) +write_fifo_isac(unsigned long adr, u_char * data, int size) { - void *adr = cs->hw.teles0.membase + 0x200; - unsigned int portdata; - int i; + register unsigned int portdata; + register int i; ZORAN_WAIT_NOBUSY; /* write data to ISAC */ for (i = 0; i < size; i++) { /* set address for ISAC fifo */ - writel(WRITE_ADDR_ISAC | 0x1E, adr); + writel(WRITE_ADDR_ISAC | 0x1E, adr + 0x200); ZORAN_WAIT_NOBUSY; - writel(WRITE_DATA_ISAC | data[i], adr); + writel(WRITE_DATA_ISAC | data[i], adr + 0x200); ZORAN_WAIT_NOBUSY; } } -static struct dc_hw_ops isac_ops = { - .read_reg = isac_read, - .write_reg = isac_write, - .read_fifo = isac_read_fifo, - .write_fifo = isac_write_fifo, -}; - -static u8 -hscx_read(struct IsdnCardState *cs, int hscx, u8 off) -{ - void *adr = cs->hw.teles0.membase + 0x200; - unsigned int portdata; - - ZORAN_WAIT_NOBUSY; - /* set address for HSCX */ - writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr); - ZORAN_WAIT_NOBUSY; - - /* read data from HSCX */ - writel(READ_DATA_HSCX, adr); - ZORAN_WAIT_NOBUSY; - return ((u8)(portdata & ZORAN_PO_DMASK)); -} - -static void -hscx_write(struct IsdnCardState *cs, int hscx, u8 off, u8 data) +static inline void +read_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size) { - void *adr = cs->hw.teles0.membase + 0x200; - unsigned int portdata; - - ZORAN_WAIT_NOBUSY; - /* set address for HSCX */ - writel(WRITE_ADDR_HSCX | ((hscx ? 0x40:0) + off), adr); - ZORAN_WAIT_NOBUSY; - - /* write data to HSCX */ - writel(WRITE_DATA_HSCX | data, adr); - ZORAN_WAIT_NOBUSY; -} - -static void -hscx_read_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size) -{ - void *adr = cs->hw.teles0.membase + 0x200; - unsigned int portdata; - int i; + register unsigned int portdata; + register int i; ZORAN_WAIT_NOBUSY; /* read data from HSCX */ for (i = 0; i < size; i++) { /* set address for HSCX fifo */ - writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr); + writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200); ZORAN_WAIT_NOBUSY; - writel(READ_DATA_HSCX, adr); + writel(READ_DATA_HSCX, adr + 0x200); ZORAN_WAIT_NOBUSY; - data[i] = (u8) (portdata & ZORAN_PO_DMASK); + data[i] = (u_char) (portdata & ZORAN_PO_DMASK); } } -static void -hscx_write_fifo(struct IsdnCardState *cs, int hscx, u8 * data, int size) +static inline void +write_fifo_hscx(unsigned long adr, int hscx, u_char * data, int size) { - void *adr = cs->hw.teles0.membase + 0x200; unsigned int portdata; - int i; + register int i; ZORAN_WAIT_NOBUSY; /* write data to HSCX */ for (i = 0; i < size; i++) { /* set address for HSCX fifo */ - writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr); + writel(WRITE_ADDR_HSCX |(hscx ? 0x5F:0x1F), adr + 0x200); ZORAN_WAIT_NOBUSY; - writel(WRITE_DATA_HSCX | data[i], adr); + writel(WRITE_DATA_HSCX | data[i], adr + 0x200); ZORAN_WAIT_NOBUSY; udelay(10); } } -static struct bc_hw_ops hscx_ops = { - .read_reg = hscx_read, - .write_reg = hscx_write, - .read_fifo = hscx_read_fifo, - .write_fifo = hscx_write_fifo, -}; +/* Interface functions */ + +static u_char +ReadISAC(struct IsdnCardState *cs, u_char offset) +{ + return (readisac(cs->hw.teles0.membase, offset)); +} + +static void +WriteISAC(struct IsdnCardState *cs, u_char offset, u_char value) +{ + writeisac(cs->hw.teles0.membase, offset, value); +} + +static void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + read_fifo_isac(cs->hw.teles0.membase, data, size); +} + +static void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + write_fifo_isac(cs->hw.teles0.membase, data, size); +} + +static u_char +ReadHSCX(struct IsdnCardState *cs, int hscx, u_char offset) +{ + return (readhscx(cs->hw.teles0.membase, hscx, offset)); +} + +static void +WriteHSCX(struct IsdnCardState *cs, int hscx, u_char offset, u_char value) +{ + writehscx(cs->hw.teles0.membase, hscx, offset, value); +} + +/* + * fast interrupt HSCX stuff goes here + */ + +#define READHSCX(cs, nr, reg) readhscx(cs->hw.teles0.membase, nr, reg) +#define WRITEHSCX(cs, nr, reg, data) writehscx(cs->hw.teles0.membase, nr, reg, data) +#define READHSCXFIFO(cs, nr, ptr, cnt) read_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt) +#define WRITEHSCXFIFO(cs, nr, ptr, cnt) write_fifo_hscx(cs->hw.teles0.membase, nr, ptr, cnt) + +#include "hscx_irq.c" static irqreturn_t telespci_interrupt(int intno, void *dev_id, struct pt_regs *regs) { -#define MAXCOUNT 20 struct IsdnCardState *cs = dev_id; - u8 val; + u_char hval, ival; + u_long flags; - spin_lock(&cs->lock); - val = hscx_read(cs, 1, HSCX_ISTA); - if (val) - hscx_int_main(cs, val); - val = isac_read(cs, ISAC_ISTA); - if (val) - isac_interrupt(cs, val); + spin_lock_irqsave(&cs->lock, flags); + hval = readhscx(cs->hw.teles0.membase, 1, HSCX_ISTA); + if (hval) + hscx_int_main(cs, hval); + ival = readisac(cs->hw.teles0.membase, ISAC_ISTA); + if ((hval | ival) == 0) { + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_NONE; + } + if (ival) + isac_interrupt(cs, ival); /* Clear interrupt register for Zoran PCI controller */ writel(0x70000000, cs->hw.teles0.membase + 0x3C); - hscx_write(cs, 0, HSCX_MASK, 0xFF); - hscx_write(cs, 1, HSCX_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0xFF); - isac_write(cs, ISAC_MASK, 0x0); - hscx_write(cs, 0, HSCX_MASK, 0x0); - hscx_write(cs, 1, HSCX_MASK, 0x0); - spin_unlock(&cs->lock); + writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0xFF); + writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0xFF); + writeisac(cs->hw.teles0.membase, ISAC_MASK, 0xFF); + writeisac(cs->hw.teles0.membase, ISAC_MASK, 0x0); + writehscx(cs->hw.teles0.membase, 0, HSCX_MASK, 0x0); + writehscx(cs->hw.teles0.membase, 1, HSCX_MASK, 0x0); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } -static struct card_ops telespci_ops = { - .init = inithscxisac, - .release = hisax_release_resources, - .irq_func = telespci_interrupt, -}; - -static int __init -telespci_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +void +release_io_telespci(struct IsdnCardState *cs) { - int rc; - - printk(KERN_INFO "TelesPCI: defined at %#lx IRQ %d\n", - pci_resource_start(pdev, 0), pdev->irq); - - rc = -EBUSY; - if (pci_enable_device(pdev)) - goto err; - - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.teles0.membase = request_mmio(&cs->rs, pci_resource_start(pdev, 0), 4096, "telespci"); - if (!cs->hw.teles0.membase) - goto err; + iounmap((void *)cs->hw.teles0.membase); +} - /* Initialize Zoran PCI controller */ - writel(0x00000000, cs->hw.teles0.membase + 0x28); - writel(0x01000000, cs->hw.teles0.membase + 0x28); - writel(0x01000000, cs->hw.teles0.membase + 0x28); - writel(0x7BFFFFFF, cs->hw.teles0.membase + 0x2C); - writel(0x70000000, cs->hw.teles0.membase + 0x3C); - writel(0x61000000, cs->hw.teles0.membase + 0x40); - /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */ +static int +TelesPCI_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + u_long flags; - cs->card_ops = &telespci_ops; - if (hscxisac_setup(cs, &isac_ops, &hscx_ops)) - goto err; - return 0; - err: - hisax_release_resources(cs); - return rc; + switch (mt) { + case CARD_RESET: + return(0); + case CARD_RELEASE: + release_io_telespci(cs); + return(0); + case CARD_INIT: + spin_lock_irqsave(&cs->lock, flags); + inithscxisac(cs, 3); + spin_unlock_irqrestore(&cs->lock, flags); + return(0); + case CARD_TEST: + return(0); + } + return(0); } static struct pci_dev *dev_tel __initdata = NULL; @@ -273,21 +290,70 @@ int __init setup_telespci(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; char tmp[64]; #ifdef __BIG_ENDIAN #error "not running on big endian machines now" #endif strcpy(tmp, telespci_revision); - printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", - HiSax_getrev(tmp)); - dev_tel = pci_find_device(PCI_VENDOR_ID_ZORAN, - PCI_DEVICE_ID_ZORAN_36120, dev_tel); - if (dev_tel) { - if (telespci_probe(card->cs, dev_tel) < 0) - return 0; - return 1; + printk(KERN_INFO "HiSax: Teles/PCI driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_TELESPCI) + return (0); +#if CONFIG_PCI + if ((dev_tel = pci_find_device (PCI_VENDOR_ID_ZORAN, PCI_DEVICE_ID_ZORAN_36120, dev_tel))) { + if (pci_enable_device(dev_tel)) + return(0); + cs->irq = dev_tel->irq; + if (!cs->irq) { + printk(KERN_WARNING "Teles: No IRQ for PCI card found\n"); + return(0); + } + cs->hw.teles0.membase = (u_long) ioremap(pci_resource_start(dev_tel, 0), + PAGE_SIZE); + printk(KERN_INFO "Found: Zoran, base-address: 0x%lx, irq: 0x%x\n", + pci_resource_start(dev_tel, 0), dev_tel->irq); + } else { + printk(KERN_WARNING "TelesPCI: No PCI card found\n"); + return(0); + } +#else + printk(KERN_WARNING "HiSax: Teles/PCI and NO_PCI_BIOS\n"); + printk(KERN_WARNING "HiSax: Teles/PCI unable to config\n"); + return (0); +#endif /* CONFIG_PCI */ + + /* Initialize Zoran PCI controller */ + writel(0x00000000, cs->hw.teles0.membase + 0x28); + writel(0x01000000, cs->hw.teles0.membase + 0x28); + writel(0x01000000, cs->hw.teles0.membase + 0x28); + writel(0x7BFFFFFF, cs->hw.teles0.membase + 0x2C); + writel(0x70000000, cs->hw.teles0.membase + 0x3C); + writel(0x61000000, cs->hw.teles0.membase + 0x40); + /* writel(0x00800000, cs->hw.teles0.membase + 0x200); */ + + printk(KERN_INFO + "HiSax: %s config irq:%d mem:%lx\n", + CardType[cs->typ], cs->irq, + cs->hw.teles0.membase); + + setup_isac(cs); + cs->readisac = &ReadISAC; + cs->writeisac = &WriteISAC; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadHSCX; + cs->BC_Write_Reg = &WriteHSCX; + cs->BC_Send_Data = &hscx_fill_fifo; + cs->cardmsg = &TelesPCI_card_msg; + cs->irq_func = &telespci_interrupt; + cs->irq_flags |= SA_SHIRQ; + ISACVersion(cs, "TelesPCI:"); + if (HscxVersion(cs, "TelesPCI:")) { + printk(KERN_WARNING + "TelesPCI: wrong HSCX versions check IO/MEM addresses\n"); + release_io_telespci(cs); + return (0); } - printk(KERN_WARNING "TelesPCI: No PCI card found\n"); - return 0; + return (1); } diff -Nru a/drivers/isdn/hisax/w6692.c b/drivers/isdn/hisax/w6692.c --- a/drivers/isdn/hisax/w6692.c Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/hisax/w6692.c Thu Feb 19 23:44:27 2004 @@ -1,4 +1,4 @@ -/* $Id: w6692.c,v 1.12.6.6 2001/09/23 22:24:52 kai Exp $ +/* $Id: w6692.c,v 1.18.2.4 2004/02/11 13:21:34 keil Exp $ * * Winbond W6692 specific routines * @@ -41,60 +41,10 @@ extern const char *CardType[]; -const char *w6692_revision = "$Revision: 1.12.6.6 $"; +const char *w6692_revision = "$Revision: 1.18.2.4 $"; #define DBUSY_TIMER_VALUE 80 -static inline u8 -w6692_read_reg(struct IsdnCardState *cs, u8 offset) -{ - return (inb(cs->hw.w6692.iobase + offset)); -} - -static inline void -w6692_write_reg(struct IsdnCardState *cs, u8 offset, u8 value) -{ - outb(value, cs->hw.w6692.iobase + offset); -} - -static void -w6692_read_fifo(struct IsdnCardState *cs, u8 * data, int size) -{ - insb(cs->hw.w6692.iobase + W_D_RFIFO, data, size); -} - -static inline void -w6692_write_fifo(struct IsdnCardState *cs, u8 * data, int size) -{ - outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, size); -} - -static struct dc_hw_ops w6692_dc_hw_ops = { - .read_fifo = w6692_read_fifo, -}; - -static inline u8 -w6692_bc_read_reg(struct IsdnCardState *cs, int bchan, u8 offset) -{ - return (inb(cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset)); -} - -static inline void -w6692_bc_write_reg(struct IsdnCardState *cs, int bchan, u8 offset, u8 value) -{ - outb(value, cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset); -} - -static void -w6692_bc_read_fifo(struct IsdnCardState *cs, int bchan, u8 *data, int len) -{ - insb(cs->hw.w6692.iobase + W_B_RFIFO + (bchan ? 0x40:0), data, len); -} - -static struct bc_hw_ops w6692_bc_hw_ops = { - .read_fifo = w6692_bc_read_fifo, -}; - static char *W6692Ver[] __initdata = {"W6692 V00", "W6692 V01", "W6692 V10", "W6692 V11"}; @@ -104,7 +54,7 @@ { int val; - val = w6692_read_reg(cs, W_D_RBCH); + val = cs->readW6692(cs, W_D_RBCH); printk(KERN_INFO "%s Winbond W6692 version (%x): %s\n", s, val, W6692Ver[(val >> 6) & 3]); } @@ -113,7 +63,7 @@ { if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_command %x", command); - w6692_write_reg(cs, W_CIX, command); + cs->writeisac(cs, W_CIX, command); } @@ -152,9 +102,8 @@ } static void -W6692_bh(void *data) +W6692_bh(struct IsdnCardState *cs) { - struct IsdnCardState *cs = data; struct PStack *stptr; if (!cs) @@ -164,7 +113,7 @@ debugl1(cs, "D-Channel Busy cleared"); stptr = cs->stlist; while (stptr != NULL) { - L1L2(stptr, PH_PAUSE | CONFIRM, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | CONFIRM, NULL); stptr = stptr->next; } } @@ -185,22 +134,58 @@ static void W6692_empty_fifo(struct IsdnCardState *cs, int count) { - recv_empty_fifo_d(cs, count); - w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK); + u_char *ptr; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, "W6692_empty_fifo"); + + if ((cs->rcvidx + count) >= MAX_DFRAME_LEN_L1) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692_empty_fifo overrun %d", + cs->rcvidx + count); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK); + cs->rcvidx = 0; + return; + } + ptr = cs->rcvbuf + cs->rcvidx; + cs->rcvidx += count; + cs->readW6692fifo(cs, ptr, count); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK); + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "W6692_empty_fifo cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } } static void W6692_fill_fifo(struct IsdnCardState *cs) { int count, more; - unsigned char *p; + u_char *ptr; + + if ((cs->debug & L1_DEB_ISAC) && !(cs->debug & L1_DEB_ISAC_FIFO)) + debugl1(cs, "W6692_fill_fifo"); - p = xmit_fill_fifo_d(cs, W_D_FIFO_THRESH, &count, &more); - if (!p) + if (!cs->tx_skb) return; - w6692_write_fifo(cs, p, count); - w6692_write_reg(cs, W_D_CMDR, more ? W_D_CMDR_XMS : (W_D_CMDR_XMS | W_D_CMDR_XME)); + count = cs->tx_skb->len; + if (count <= 0) + return; + + more = 0; + if (count > W_D_FIFO_THRESH) { + more = !0; + count = W_D_FIFO_THRESH; + } + ptr = cs->tx_skb->data; + skb_pull(cs->tx_skb, count); + cs->tx_cnt += count; + cs->writeW6692fifo(cs, ptr, count); + cs->writeW6692(cs, W_D_CMDR, more ? W_D_CMDR_XMS : (W_D_CMDR_XMS | W_D_CMDR_XME)); if (test_and_set_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { debugl1(cs, "W6692_fill_fifo dbusytimer running"); del_timer(&cs->dbusytimer); @@ -208,13 +193,43 @@ init_timer(&cs->dbusytimer); cs->dbusytimer.expires = jiffies + ((DBUSY_TIMER_VALUE * HZ) / 1000); add_timer(&cs->dbusytimer); + if (cs->debug & L1_DEB_ISAC_FIFO) { + char *t = cs->dlog; + + t += sprintf(t, "W6692_fill_fifo cnt %d", count); + QuickHex(t, ptr, count); + debugl1(cs, cs->dlog); + } } static void W6692B_empty_fifo(struct BCState *bcs, int count) { - recv_empty_fifo_b(bcs, count); - w6692_bc_write_reg(bcs->cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); + u_char *ptr; + struct IsdnCardState *cs = bcs->cs; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "W6692B_empty_fifo"); + + if (bcs->hw.w6692.rcvidx + count > HSCX_BUFMAX) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692B_empty_fifo: incoming packet too large"); + cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); + bcs->hw.w6692.rcvidx = 0; + return; + } + ptr = bcs->hw.w6692.rcvbuf + bcs->hw.w6692.rcvidx; + bcs->hw.w6692.rcvidx += count; + READW6692BFIFO(cs, bcs->channel, ptr, count); + cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RACT); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "W6692B_empty_fifo %c cnt %d", + bcs->channel + '1', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } static void @@ -222,33 +237,50 @@ { struct IsdnCardState *cs = bcs->cs; int more, count; - unsigned char *p; + u_char *ptr; - p = xmit_fill_fifo_b(bcs, W_B_FIFO_THRESH, &count, &more); - if (!p) + if (!bcs->tx_skb) + return; + if (bcs->tx_skb->len <= 0) return; - WRITEW6692BFIFO(cs, bcs->channel, p, count); - w6692_bc_write_reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACT | W_B_CMDR_XMS | (more ? 0 : W_B_CMDR_XME)); -} - -static void -reset_xmit(struct BCState *bcs) -{ - w6692_bc_write_reg(bcs->cs, bcs->channel, W_B_CMDR, - W_B_CMDR_XRST | W_B_CMDR_RACT); + more = (bcs->mode == L1_MODE_TRANS) ? 1 : 0; + if (bcs->tx_skb->len > W_B_FIFO_THRESH) { + more = 1; + count = W_B_FIFO_THRESH; + } else + count = bcs->tx_skb->len; + + if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO)) + debugl1(cs, "W6692B_fill_fifo%s%d", (more ? " ": " last "), count); + + ptr = bcs->tx_skb->data; + skb_pull(bcs->tx_skb, count); + bcs->tx_cnt -= count; + bcs->hw.w6692.count += count; + WRITEW6692BFIFO(cs, bcs->channel, ptr, count); + cs->BC_Write_Reg(cs, bcs->channel, W_B_CMDR, W_B_CMDR_RACT | W_B_CMDR_XMS | (more ? 0 : W_B_CMDR_XME)); + if (cs->debug & L1_DEB_HSCX_FIFO) { + char *t = bcs->blog; + + t += sprintf(t, "W6692B_fill_fifo %c cnt %d", + bcs->channel + '1', count); + QuickHex(t, ptr, count); + debugl1(cs, bcs->blog); + } } static void -W6692B_interrupt(struct IsdnCardState *cs, u8 bchan) +W6692B_interrupt(struct IsdnCardState *cs, u_char bchan) { - u8 val; - u8 r; + u_char val; + u_char r; struct BCState *bcs; + struct sk_buff *skb; int count; bcs = (cs->bcs->channel == bchan) ? cs->bcs : (cs->bcs+1); - val = w6692_bc_read_reg(cs, bchan, W_B_EXIR); + val = cs->BC_Read_Reg(cs, bchan, W_B_EXIR); debugl1(cs, "W6692B chan %d B_EXIR 0x%02X", bchan, val); if (!test_bit(BC_FLG_INIT, &bcs->Flag)) { @@ -256,8 +288,10 @@ return; } if (val & W_B_EXI_RME) { /* RME */ - r = w6692_bc_read_reg(cs, bchan, W_B_STAR); - if (r & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB | W_B_STAR_XDOW)) { + r = cs->BC_Read_Reg(cs, bchan, W_B_STAR); + if (r & (W_B_STAR_RDOV | W_B_STAR_CRCE | W_B_STAR_RMB)) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 B STAR %x", r); if ((r & W_B_STAR_RDOV) && bcs->mode) if (cs->debug & L1_DEB_WARN) debugl1(cs, "W6692 B RDOV mode=%d", @@ -265,46 +299,129 @@ if (r & W_B_STAR_CRCE) if (cs->debug & L1_DEB_WARN) debugl1(cs, "W6692 B CRC error"); - w6692_bc_write_reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT); - bcs->rcvidx = 0; + cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT); } else { - count = w6692_bc_read_reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1); + count = cs->BC_Read_Reg(cs, bchan, W_B_RBCL) & (W_B_FIFO_THRESH - 1); if (count == 0) count = W_B_FIFO_THRESH; W6692B_empty_fifo(bcs, count); - recv_rme_b(bcs); + if ((count = bcs->hw.w6692.rcvidx) > 0) { + if (cs->debug & L1_DEB_HSCX_FIFO) + debugl1(cs, "W6692 Bchan Frame %d", count); + if (!(skb = dev_alloc_skb(count))) + printk(KERN_WARNING "W6692: Bchan receive out of memory\n"); + else { + memcpy(skb_put(skb, count), bcs->hw.w6692.rcvbuf, count); + skb_queue_tail(&bcs->rqueue, skb); + } + } } + bcs->hw.w6692.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); } if (val & W_B_EXI_RMR) { /* RMR */ W6692B_empty_fifo(bcs, W_B_FIFO_THRESH); - recv_rpf_b(bcs); - } - if (val & W_B_EXI_XFR) { /* XFR */ - xmit_xpr_b(bcs); + r = cs->BC_Read_Reg(cs, bchan, W_B_STAR); + if (r & W_B_STAR_RDOV) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 B RDOV(RMR) mode=%d",bcs->mode); + cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RACK | W_B_CMDR_RRST | W_B_CMDR_RACT); + if (bcs->mode != L1_MODE_TRANS) + bcs->hw.w6692.rcvidx = 0; + } + if (bcs->mode == L1_MODE_TRANS) { + /* receive audio data */ + if (!(skb = dev_alloc_skb(W_B_FIFO_THRESH))) + printk(KERN_WARNING "HiSax: receive out of memory\n"); + else { + memcpy(skb_put(skb, W_B_FIFO_THRESH), bcs->hw.w6692.rcvbuf, W_B_FIFO_THRESH); + skb_queue_tail(&bcs->rqueue, skb); + } + bcs->hw.w6692.rcvidx = 0; + schedule_event(bcs, B_RCVBUFREADY); + } } if (val & W_B_EXI_XDUN) { /* XDUN */ - xmit_xdu_b(bcs, reset_xmit); + cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT); + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 B EXIR %x Lost TX", val); + if (bcs->mode == 1) + W6692B_fill_fifo(bcs); + else { + /* Here we lost an TX interrupt, so + * restart transmitting the whole frame. + */ + if (bcs->tx_skb) { + skb_push(bcs->tx_skb, bcs->hw.w6692.count); + bcs->tx_cnt += bcs->hw.w6692.count; + bcs->hw.w6692.count = 0; + } + } + return; + } + if (val & W_B_EXI_XFR) { /* XFR */ + r = cs->BC_Read_Reg(cs, bchan, W_B_STAR); + if (r & W_B_STAR_XDOW) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, "W6692 B STAR %x XDOW", r); + cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_XRST | W_B_CMDR_RACT); + if (bcs->tx_skb && (bcs->mode != 1)) { + skb_push(bcs->tx_skb, bcs->hw.w6692.count); + bcs->tx_cnt += bcs->hw.w6692.count; + bcs->hw.w6692.count = 0; + } + } + if (bcs->tx_skb) { + if (bcs->tx_skb->len) { + W6692B_fill_fifo(bcs); + return; + } else { + if (test_bit(FLG_LLI_L1WAKEUP,&bcs->st->lli.flag) && + (PACKET_NOACK != bcs->tx_skb->pkt_type)) { + u_long flags; + spin_lock_irqsave(&bcs->aclock, flags); + bcs->ackcnt += bcs->hw.w6692.count; + spin_unlock_irqrestore(&bcs->aclock, flags); + schedule_event(bcs, B_ACKPENDING); + } + dev_kfree_skb_irq(bcs->tx_skb); + bcs->hw.w6692.count = 0; + bcs->tx_skb = NULL; + } + } + if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) { + bcs->hw.w6692.count = 0; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + W6692B_fill_fifo(bcs); + } else { + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + schedule_event(bcs, B_XMTBUFREADY); + } } } static irqreturn_t -w6692_interrupt(int intno, void *dev_id, struct pt_regs *regs) +W6692_interrupt(int intno, void *dev_id, struct pt_regs *regs) { - struct IsdnCardState *cs = dev_id; - u8 val, exval, v1; - unsigned int count; - int icnt = 5; - - spin_lock(&cs->lock); - - val = w6692_read_reg(cs, W_ISTA); - + struct IsdnCardState *cs = dev_id; + u_char val, exval, v1; + struct sk_buff *skb; + u_int count; + u_long flags; + int icnt = 5; + + spin_lock_irqsave(&cs->lock, flags); + val = cs->readW6692(cs, W_ISTA); + if (!val) { + spin_unlock_irqrestore(&cs->lock, flags); + return IRQ_NONE; + } StartW6692: if (cs->debug & L1_DEB_ISAC) debugl1(cs, "W6692 ISTA %x", val); if (val & W_INT_D_RME) { /* RME */ - exval = w6692_read_reg(cs, W_D_RSTA); + exval = cs->readW6692(cs, W_D_RSTA); if (exval & (W_D_RSTA_RDOV | W_D_RSTA_CRCE | W_D_RSTA_RMB)) { if (exval & W_D_RSTA_RDOV) if (cs->debug & L1_DEB_WARN) @@ -315,58 +432,100 @@ if (exval & W_D_RSTA_RMB) if (cs->debug & L1_DEB_WARN) debugl1(cs, "W6692 D-channel ABORT"); - w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST); - cs->rcvidx = 0; + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RACK | W_D_CMDR_RRST); } else { - count = w6692_read_reg(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1); + count = cs->readW6692(cs, W_D_RBCL) & (W_D_FIFO_THRESH - 1); if (count == 0) count = W_D_FIFO_THRESH; W6692_empty_fifo(cs, count); - recv_rme_d(cs); + if ((count = cs->rcvidx) > 0) { + cs->rcvidx = 0; + if (!(skb = alloc_skb(count, GFP_ATOMIC))) + printk(KERN_WARNING "HiSax: D receive out of memory\n"); + else { + memcpy(skb_put(skb, count), cs->rcvbuf, count); + skb_queue_tail(&cs->rq, skb); + } + } } + cs->rcvidx = 0; + schedule_event(cs, D_RCVBUFREADY); } if (val & W_INT_D_RMR) { /* RMR */ W6692_empty_fifo(cs, W_D_FIFO_THRESH); } if (val & W_INT_D_XFR) { /* XFR */ - xmit_xpr_d(cs); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { + if (cs->tx_skb->len) { + W6692_fill_fifo(cs); + goto afterXFR; + } else { + dev_kfree_skb_irq(cs->tx_skb); + cs->tx_cnt = 0; + cs->tx_skb = NULL; + } + } + if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_cnt = 0; + W6692_fill_fifo(cs); + } else + schedule_event(cs, D_XMTBUFREADY); } + afterXFR: if (val & (W_INT_XINT0 | W_INT_XINT1)) { /* XINT0/1 - never */ if (cs->debug & L1_DEB_ISAC) debugl1(cs, "W6692 spurious XINT!"); } if (val & W_INT_D_EXI) { /* EXI */ - exval = w6692_read_reg(cs, W_D_EXIR); + exval = cs->readW6692(cs, W_D_EXIR); if (cs->debug & L1_DEB_WARN) debugl1(cs, "W6692 D_EXIR %02x", exval); if (exval & (W_D_EXI_XDUN | W_D_EXI_XCOL)) { /* Transmit underrun/collision */ - xmit_xdu_d(cs, NULL); + debugl1(cs, "W6692 D-chan underrun/collision"); + printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL\n"); + if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) + del_timer(&cs->dbusytimer); + if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) + schedule_event(cs, D_CLEARBUSY); + if (cs->tx_skb) { /* Restart frame */ + skb_push(cs->tx_skb, cs->tx_cnt); + cs->tx_cnt = 0; + W6692_fill_fifo(cs); + } else { + printk(KERN_WARNING "HiSax: W6692 XDUN/XCOL no skb\n"); + debugl1(cs, "W6692 XDUN/XCOL no skb"); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST); + } } if (exval & W_D_EXI_RDOV) { /* RDOV */ debugl1(cs, "W6692 D-channel RDOV"); printk(KERN_WARNING "HiSax: W6692 D-RDOV\n"); - w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RRST); + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST); } if (exval & W_D_EXI_TIN2) { /* TIN2 - never */ debugl1(cs, "W6692 spurious TIN2 interrupt"); } if (exval & W_D_EXI_MOC) { /* MOC - not supported */ debugl1(cs, "W6692 spurious MOC interrupt"); - v1 = w6692_read_reg(cs, W_MOSR); + v1 = cs->readW6692(cs, W_MOSR); debugl1(cs, "W6692 MOSR %02x", v1); } if (exval & W_D_EXI_ISC) { /* ISC - Level1 change */ - v1 = w6692_read_reg(cs, W_CIR); + v1 = cs->readW6692(cs, W_CIR); if (cs->debug & L1_DEB_ISAC) debugl1(cs, "W6692 ISC CIR=0x%02X", v1); if (v1 & W_CIR_ICC) { cs->dc.w6692.ph_state = v1 & W_CIR_COD_MASK; if (cs->debug & L1_DEB_ISAC) debugl1(cs, "ph_state_change %x", cs->dc.w6692.ph_state); - sched_d_event(cs, D_L1STATECHANGE); + schedule_event(cs, D_L1STATECHANGE); } if (v1 & W_CIR_SCC) { - v1 = w6692_read_reg(cs, W_SQR); + v1 = cs->readW6692(cs, W_SQR); debugl1(cs, "W6692 SCC SQR=0x%02X", v1); } } @@ -385,16 +544,16 @@ debugl1(cs, "W6692 B channel 2 interrupt"); W6692B_interrupt(cs, 1); } - val = w6692_read_reg(cs, W_ISTA); + val = cs->readW6692(cs, W_ISTA); if (val && icnt) { icnt--; goto StartW6692; } if (!icnt) { printk(KERN_WARNING "W6692 IRQ LOOP\n"); - w6692_write_reg(cs, W_IMASK, 0xff); + cs->writeW6692(cs, W_IMASK, 0xff); } - spin_unlock(&cs->lock); + spin_unlock_irqrestore(&cs->lock, flags); return IRQ_HANDLED; } @@ -403,32 +562,87 @@ { struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware; struct sk_buff *skb = arg; + u_long flags; int val; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_d(cs, skb); + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + skb_queue_tail(&cs->sq, skb); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA Queued", 0); +#endif + } else { + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA", 0); +#endif + W6692_fill_fifo(cs); + } + spin_unlock_irqrestore(&cs->lock, flags); break; - case (PH_PULL |INDICATION): - xmit_pull_ind_d(cs, skb); + case (PH_PULL | INDICATION): + spin_lock_irqsave(&cs->lock, flags); + if (cs->tx_skb) { + if (cs->debug & L1_DEB_WARN) + debugl1(cs, " l2l1 tx_skb exist this shouldn't happen"); + skb_queue_tail(&cs->sq, skb); + spin_unlock_irqrestore(&cs->lock, flags); + break; + } + if (cs->debug & DEB_DLOG_HEX) + LogFrame(cs, skb->data, skb->len); + if (cs->debug & DEB_DLOG_VERBOSE) + dlogframe(cs, skb, 0); + cs->tx_skb = skb; + cs->tx_cnt = 0; +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + Logl2Frame(cs, skb, "PH_DATA_PULLED", 0); +#endif + W6692_fill_fifo(cs); + spin_unlock_irqrestore(&cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_d(st); +#ifdef L2FRAME_DEBUG /* psa */ + if (cs->debug & L1_DEB_LAPD) + debugl1(cs, "-> PH_REQUEST_PULL"); +#endif + if (!cs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (HW_RESET | REQUEST): - if ((cs->dc.w6692.ph_state == W_L1IND_DRD)) + spin_lock_irqsave(&cs->lock, flags); + if ((cs->dc.w6692.ph_state == W_L1IND_DRD)) { ph_command(cs, W_L1CMD_ECK); - else { + spin_unlock_irqrestore(&cs->lock, flags); + } else { ph_command(cs, W_L1CMD_RST); cs->dc.w6692.ph_state = W_L1CMD_RST; + spin_unlock_irqrestore(&cs->lock, flags); W6692_new_ph(cs); } break; case (HW_ENABLE | REQUEST): + spin_lock_irqsave(&cs->lock, flags); ph_command(cs, W_L1CMD_ECK); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_INFO3 | REQUEST): + spin_lock_irqsave(&cs->lock, flags); ph_command(cs, W_L1CMD_AR8); + spin_unlock_irqrestore(&cs->lock, flags); break; case (HW_TESTLOOP | REQUEST): val = 0; @@ -448,7 +662,7 @@ if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) del_timer(&cs->dbusytimer); if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags)) - sched_d_event(cs, D_CLEARBUSY); + schedule_event(cs, D_CLEARBUSY); break; default: if (cs->debug & L1_DEB_WARN) @@ -457,11 +671,15 @@ } } -static int +static void setstack_W6692(struct PStack *st, struct IsdnCardState *cs) { st->l1.l1hw = W6692_l1hw; - return 0; +} + +static void +DC_Close_W6692(struct IsdnCardState *cs) +{ } static void @@ -469,10 +687,12 @@ { struct PStack *stptr; int rbch, star; + u_long flags; + spin_lock_irqsave(&cs->lock, flags); if (test_bit(FLG_DBUSY_TIMER, &cs->HW_Flags)) { - rbch = w6692_read_reg(cs, W_D_RBCH); - star = w6692_read_reg(cs, W_D_STAR); + rbch = cs->readW6692(cs, W_D_RBCH); + star = cs->readW6692(cs, W_D_STAR); if (cs->debug) debugl1(cs, "D-Channel Busy D_RBCH %02x D_STAR %02x", rbch, star); @@ -480,7 +700,7 @@ test_and_set_bit(FLG_L1_DBUSY, &cs->HW_Flags); stptr = cs->stlist; while (stptr != NULL) { - L1L2(stptr, PH_PAUSE | INDICATION, NULL); + stptr->l1.l1l2(stptr, PH_PAUSE | INDICATION, NULL); stptr = stptr->next; } } else { @@ -494,10 +714,13 @@ printk(KERN_WARNING "HiSax: W6692 D-Channel Busy no skb\n"); debugl1(cs, "D-Channel Busy no skb"); } - w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_XRST); /* Transmitter reset */ - cs->card_ops->irq_func(cs->irq, cs, NULL); /* FIXME? */ + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_XRST); /* Transmitter reset */ + spin_unlock_irqrestore(&cs->lock, flags); + cs->irq_func(cs->irq, cs, NULL); + return; } } + spin_unlock_irqrestore(&cs->lock, flags); } static void @@ -514,51 +737,79 @@ switch (mode) { case (L1_MODE_NULL): - w6692_bc_write_reg(cs, bchan, W_B_MODE, 0); + cs->BC_Write_Reg(cs, bchan, W_B_MODE, 0); break; case (L1_MODE_TRANS): - w6692_bc_write_reg(cs, bchan, W_B_MODE, W_B_MODE_MMS); + cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_MMS); break; case (L1_MODE_HDLC): - w6692_bc_write_reg(cs, bchan, W_B_MODE, W_B_MODE_ITF); - w6692_bc_write_reg(cs, bchan, W_B_ADM1, 0xff); - w6692_bc_write_reg(cs, bchan, W_B_ADM2, 0xff); + cs->BC_Write_Reg(cs, bchan, W_B_MODE, W_B_MODE_ITF); + cs->BC_Write_Reg(cs, bchan, W_B_ADM1, 0xff); + cs->BC_Write_Reg(cs, bchan, W_B_ADM2, 0xff); break; } if (mode) - w6692_bc_write_reg(cs, bchan, W_B_CMDR, W_B_CMDR_RRST | + cs->BC_Write_Reg(cs, bchan, W_B_CMDR, W_B_CMDR_RRST | W_B_CMDR_RACT | W_B_CMDR_XRST); - w6692_bc_write_reg(cs, bchan, W_B_EXIM, 0x00); + cs->BC_Write_Reg(cs, bchan, W_B_EXIM, 0x00); } static void W6692_l2l1(struct PStack *st, int pr, void *arg) { struct sk_buff *skb = arg; + struct BCState *bcs = st->l1.bcs; + u_long flags; switch (pr) { case (PH_DATA | REQUEST): - xmit_data_req_b(st->l1.bcs, skb); + spin_lock_irqsave(&bcs->cs->lock, flags); + if (bcs->tx_skb) { + skb_queue_tail(&bcs->squeue, skb); + } else { + bcs->tx_skb = skb; + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->hw.w6692.count = 0; + bcs->cs->BC_Send_Data(bcs); + } + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | INDICATION): - xmit_pull_ind_b(st->l1.bcs, skb); + if (bcs->tx_skb) { + printk(KERN_WARNING "W6692_l2l1: this shouldn't happen\n"); + break; + } + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->tx_skb = skb; + bcs->hw.w6692.count = 0; + bcs->cs->BC_Send_Data(bcs); + spin_unlock_irqrestore(&bcs->cs->lock, flags); break; case (PH_PULL | REQUEST): - xmit_pull_req_b(st); + if (!bcs->tx_skb) { + test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags); + st->l1.l1l2(st, PH_PULL | CONFIRM, NULL); + } else + test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags); break; case (PH_ACTIVATE | REQUEST): - test_and_set_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - W6692Bmode(st->l1.bcs, st->l1.mode, st->l1.bc); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag); + W6692Bmode(bcs, st->l1.mode, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | REQUEST): l1_msg_b(st, pr, arg); break; case (PH_DEACTIVATE | CONFIRM): - test_and_clear_bit(BC_FLG_ACTIV, &st->l1.bcs->Flag); - test_and_clear_bit(BC_FLG_BUSY, &st->l1.bcs->Flag); - W6692Bmode(st->l1.bcs, 0, st->l1.bc); - L1L2(st, PH_DEACTIVATE | CONFIRM, NULL); + spin_lock_irqsave(&bcs->cs->lock, flags); + test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag); + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + W6692Bmode(bcs, 0, st->l1.bc); + spin_unlock_irqrestore(&bcs->cs->lock, flags); + st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL); break; } } @@ -567,13 +818,52 @@ close_w6692state(struct BCState *bcs) { W6692Bmode(bcs, 0, bcs->channel); - bc_close(bcs); + if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) { + if (bcs->hw.w6692.rcvbuf) { + kfree(bcs->hw.w6692.rcvbuf); + bcs->hw.w6692.rcvbuf = NULL; + } + if (bcs->blog) { + kfree(bcs->blog); + bcs->blog = NULL; + } + skb_queue_purge(&bcs->rqueue); + skb_queue_purge(&bcs->squeue); + if (bcs->tx_skb) { + dev_kfree_skb_any(bcs->tx_skb); + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + } + } } static int open_w6692state(struct IsdnCardState *cs, struct BCState *bcs) { - return bc_open(bcs); + if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) { + if (!(bcs->hw.w6692.rcvbuf = kmalloc(HSCX_BUFMAX, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for w6692.rcvbuf\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + return (1); + } + if (!(bcs->blog = kmalloc(MAX_BLOG_SPACE, GFP_ATOMIC))) { + printk(KERN_WARNING + "HiSax: No memory for bcs->blog\n"); + test_and_clear_bit(BC_FLG_INIT, &bcs->Flag); + kfree(bcs->hw.w6692.rcvbuf); + bcs->hw.w6692.rcvbuf = NULL; + return (2); + } + skb_queue_head_init(&bcs->rqueue); + skb_queue_head_init(&bcs->squeue); + } + bcs->tx_skb = NULL; + test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag); + bcs->event = 0; + bcs->hw.w6692.rcvidx = 0; + bcs->tx_cnt = 0; + return (0); } static int @@ -583,166 +873,224 @@ if (open_w6692state(st->l1.hardware, bcs)) return (-1); st->l1.bcs = bcs; - st->l1.l2l1 = W6692_l2l1; + st->l2.l2l1 = W6692_l2l1; setstack_manager(st); bcs->st = st; setstack_l1_B(st); return (0); } -static int -w6692_reset(struct IsdnCardState *cs) +void resetW6692(struct IsdnCardState *cs) { - w6692_write_reg(cs, W_D_CTL, W_D_CTL_SRST); - schedule_timeout((10*HZ)/1000); - w6692_write_reg(cs, W_D_CTL, 0x00); - schedule_timeout((10*HZ)/1000); - w6692_write_reg(cs, W_IMASK, 0xff); - w6692_write_reg(cs, W_D_SAM, 0xff); - w6692_write_reg(cs, W_D_TAM, 0xff); - w6692_write_reg(cs, W_D_EXIM, 0x00); - w6692_write_reg(cs, W_D_MODE, W_D_MODE_RACT); - w6692_write_reg(cs, W_IMASK, 0x18); + cs->writeW6692(cs, W_D_CTL, W_D_CTL_SRST); + mdelay(10); + cs->writeW6692(cs, W_D_CTL, 0x00); + mdelay(10); + cs->writeW6692(cs, W_IMASK, 0xff); + cs->writeW6692(cs, W_D_SAM, 0xff); + cs->writeW6692(cs, W_D_TAM, 0xff); + cs->writeW6692(cs, W_D_EXIM, 0x00); + cs->writeW6692(cs, W_D_MODE, W_D_MODE_RACT); + cs->writeW6692(cs, W_IMASK, 0x18); if (cs->subtyp == W6692_USR) { /* seems that USR implemented some power control features * Pin 79 is connected to the oscilator circuit so we * have to handle it here */ - w6692_write_reg(cs, W_PCTL, 0x80); - w6692_write_reg(cs, W_XDATA, 0x00); + cs->writeW6692(cs, W_PCTL, 0x80); + cs->writeW6692(cs, W_XDATA, 0x00); } - return 0; } -static void -w6692_init(struct IsdnCardState *cs) +void __init initW6692(struct IsdnCardState *cs, int part) { - w6692_reset(cs); - ph_command(cs, W_L1CMD_RST); - cs->dc.w6692.ph_state = W_L1CMD_RST; - W6692_new_ph(cs); - ph_command(cs, W_L1CMD_ECK); - - W6692Bmode(cs->bcs, 0, 0); - W6692Bmode(cs->bcs + 1, 0, 0); + if (part & 1) { + cs->setstack_d = setstack_W6692; + cs->DC_Close = DC_Close_W6692; + cs->dbusytimer.function = (void *) dbusy_timer_handler; + cs->dbusytimer.data = (long) cs; + init_timer(&cs->dbusytimer); + resetW6692(cs); + ph_command(cs, W_L1CMD_RST); + cs->dc.w6692.ph_state = W_L1CMD_RST; + W6692_new_ph(cs); + ph_command(cs, W_L1CMD_ECK); - /* Reenable all IRQ */ - w6692_write_reg(cs, W_IMASK, 0x18); - w6692_write_reg(cs, W_D_EXIM, 0x00); - w6692_bc_write_reg(cs, 0, W_B_EXIM, 0x00); - w6692_bc_write_reg(cs, 1, W_B_EXIM, 0x00); - /* Reset D-chan receiver and transmitter */ - w6692_write_reg(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST); + cs->bcs[0].BC_SetStack = setstack_w6692; + cs->bcs[1].BC_SetStack = setstack_w6692; + cs->bcs[0].BC_Close = close_w6692state; + cs->bcs[1].BC_Close = close_w6692state; + W6692Bmode(cs->bcs, 0, 0); + W6692Bmode(cs->bcs + 1, 0, 0); + } + if (part & 2) { + /* Reenable all IRQ */ + cs->writeW6692(cs, W_IMASK, 0x18); + cs->writeW6692(cs, W_D_EXIM, 0x00); + cs->BC_Write_Reg(cs, 0, W_B_EXIM, 0x00); + cs->BC_Write_Reg(cs, 1, W_B_EXIM, 0x00); + /* Reset D-chan receiver and transmitter */ + cs->writeW6692(cs, W_D_CMDR, W_D_CMDR_RRST | W_D_CMDR_XRST); + } } +/* Interface functions */ -static void -w6692_release(struct IsdnCardState *cs) +static u_char +ReadW6692(struct IsdnCardState *cs, u_char offset) { - w6692_write_reg(cs, W_IMASK, 0xff); - if (cs->subtyp == W6692_USR) - w6692_write_reg(cs, W_XDATA, 0x04); - hisax_release_resources(cs); + return (inb(cs->hw.w6692.iobase + offset)); } -static struct card_ops w6692_ops = { - .init = w6692_init, - .reset = w6692_reset, - .release = w6692_release, - .irq_func = w6692_interrupt, -}; - -static struct dc_l1_ops w6692_dc_l1_ops = { - .fill_fifo = W6692_fill_fifo, - .open = setstack_W6692, - .bh_func = W6692_bh, - .dbusy_func = dbusy_timer_handler, -}; - -static struct bc_l1_ops w6692_bc_l1_ops = { - .fill_fifo = W6692B_fill_fifo, - .open = setstack_w6692, - .close = close_w6692state, -}; +static void +WriteW6692(struct IsdnCardState *cs, u_char offset, u_char value) +{ + outb(value, cs->hw.w6692.iobase + offset); +} -static int id_idx ; +static void +ReadISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + insb(cs->hw.w6692.iobase + W_D_RFIFO, data, size); +} -static struct pci_dev *dev_w6692 __initdata = NULL; +static void +WriteISACfifo(struct IsdnCardState *cs, u_char * data, int size) +{ + outsb(cs->hw.w6692.iobase + W_D_XFIFO, data, size); +} -static int -w6692_hw_init(struct IsdnCardState *cs) +static u_char +ReadW6692B(struct IsdnCardState *cs, int bchan, u_char offset) { - cs->card_ops = &w6692_ops; - cs->dc_hw_ops = &w6692_dc_hw_ops, - cs->bc_hw_ops = &w6692_bc_hw_ops; - dc_l1_init(cs, &w6692_dc_l1_ops); - cs->bc_l1_ops = &w6692_bc_l1_ops; - W6692Version(cs, "W6692:"); - printk(KERN_INFO "W6692 ISTA=0x%X\n", w6692_read_reg(cs, W_ISTA)); - printk(KERN_INFO "W6692 IMASK=0x%X\n", w6692_read_reg(cs, W_IMASK)); - printk(KERN_INFO "W6692 D_EXIR=0x%X\n", w6692_read_reg(cs, W_D_EXIR)); - printk(KERN_INFO "W6692 D_EXIM=0x%X\n", w6692_read_reg(cs, W_D_EXIM)); - printk(KERN_INFO "W6692 D_RSTA=0x%X\n", w6692_read_reg(cs, W_D_RSTA)); - return 0; + return (inb(cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset)); } -static int __init -w6692_probe(struct IsdnCardState *cs, struct pci_dev *pdev) +static void +WriteW6692B(struct IsdnCardState *cs, int bchan, u_char offset, u_char value) { - int rc; + outb(value, cs->hw.w6692.iobase + (bchan ? 0x40 : 0) + offset); +} - printk(KERN_INFO "W6692: %s %s at %#lx IRQ %d\n", - id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name, - pci_resource_start(pdev, 1), pdev->irq); - - rc = -EBUSY; - if (pci_enable_device(pdev)) - goto err; - - /* USR ISDN PCI card TA need some special handling */ - if (cs->subtyp == W6692_WINBOND) { - if (pdev->subsystem_vendor == W6692_SV_USR && - pdev->subsystem_device == W6692_SD_USR) { - cs->subtyp = W6692_USR; - } +static int +w6692_card_msg(struct IsdnCardState *cs, int mt, void *arg) +{ + switch (mt) { + case CARD_RESET: + resetW6692(cs); + return (0); + case CARD_RELEASE: + cs->writeW6692(cs, W_IMASK, 0xff); + release_region(cs->hw.w6692.iobase, 256); + if (cs->subtyp == W6692_USR) { + cs->writeW6692(cs, W_XDATA, 0x04); + } + return (0); + case CARD_INIT: + initW6692(cs, 3); + return (0); + case CARD_TEST: + return (0); } - cs->irq = pdev->irq; - cs->irq_flags |= SA_SHIRQ; - cs->hw.w6692.iobase = pci_resource_start(pdev, 1); - - if (!request_io(&cs->rs, cs->hw.w6692.iobase, 0x100, - id_list[cs->subtyp].card_name)) - goto err; - - w6692_hw_init(cs); - return 0; - err: - hisax_release_resources(cs); - return rc; + return (0); } +static int id_idx ; + +static struct pci_dev *dev_w6692 __initdata = NULL; + int __init setup_w6692(struct IsdnCard *card) { + struct IsdnCardState *cs = card->cs; char tmp[64]; + u_char found = 0; + u_char pci_irq = 0; + u_int pci_ioaddr = 0; -#ifdef __BIG_ENDIAN -#error "not running on big endian machines now" -#endif strcpy(tmp, w6692_revision); printk(KERN_INFO "HiSax: W6692 driver Rev. %s\n", HiSax_getrev(tmp)); + if (cs->typ != ISDN_CTYPE_W6692) + return (0); +#if CONFIG_PCI while (id_list[id_idx].vendor_id) { dev_w6692 = pci_find_device(id_list[id_idx].vendor_id, id_list[id_idx].device_id, dev_w6692); if (dev_w6692) { - card->cs->subtyp = id_idx; - if (w6692_probe(card->cs, dev_w6692) < 0) - return 0; - return 1; + if (pci_enable_device(dev_w6692)) + continue; + cs->subtyp = id_idx; + break; } id_idx++; } - printk(KERN_WARNING "W6692: No PCI card found\n"); - return 0; + if (dev_w6692) { + found = 1; + pci_irq = dev_w6692->irq; + /* I think address 0 is allways the configuration area */ + /* and address 1 is the real IO space KKe 03.09.99 */ + pci_ioaddr = pci_resource_start(dev_w6692, 1); + /* USR ISDN PCI card TA need some special handling */ + if (cs->subtyp == W6692_WINBOND) { + if ((W6692_SV_USR == dev_w6692->subsystem_vendor) && + (W6692_SD_USR == dev_w6692->subsystem_device)) { + cs->subtyp = W6692_USR; + } + } + } + if (!found) { + printk(KERN_WARNING "W6692: No PCI card found\n"); + return (0); + } + cs->irq = pci_irq; + if (!cs->irq) { + printk(KERN_WARNING "W6692: No IRQ for PCI card found\n"); + return (0); + } + if (!pci_ioaddr) { + printk(KERN_WARNING "W6692: NO I/O Base Address found\n"); + return (0); + } + cs->hw.w6692.iobase = pci_ioaddr; + printk(KERN_INFO "Found: %s %s, I/O base: 0x%x, irq: %d\n", + id_list[cs->subtyp].vendor_name, id_list[cs->subtyp].card_name, + pci_ioaddr, pci_irq); + if (!request_region(cs->hw.w6692.iobase, 256, id_list[cs->subtyp].card_name)) { + printk(KERN_WARNING + "HiSax: %s I/O ports %x-%x already in use\n", + id_list[cs->subtyp].card_name, + cs->hw.w6692.iobase, + cs->hw.w6692.iobase + 255); + return (0); + } +#else + printk(KERN_WARNING "HiSax: W6692 and NO_PCI_BIOS\n"); + printk(KERN_WARNING "HiSax: W6692 unable to config\n"); + return (0); +#endif /* CONFIG_PCI */ + + printk(KERN_INFO + "HiSax: %s config irq:%d I/O:%x\n", + id_list[cs->subtyp].card_name, cs->irq, + cs->hw.w6692.iobase); + + INIT_WORK(&cs->tqueue, (void *)(void *) W6692_bh, cs); + cs->readW6692 = &ReadW6692; + cs->writeW6692 = &WriteW6692; + cs->readisacfifo = &ReadISACfifo; + cs->writeisacfifo = &WriteISACfifo; + cs->BC_Read_Reg = &ReadW6692B; + cs->BC_Write_Reg = &WriteW6692B; + cs->BC_Send_Data = &W6692B_fill_fifo; + cs->cardmsg = &w6692_card_msg; + cs->irq_func = &W6692_interrupt; + cs->irq_flags |= SA_SHIRQ; + W6692Version(cs, "W6692:"); + printk(KERN_INFO "W6692 ISTA=0x%X\n", ReadW6692(cs, W_ISTA)); + printk(KERN_INFO "W6692 IMASK=0x%X\n", ReadW6692(cs, W_IMASK)); + printk(KERN_INFO "W6692 D_EXIR=0x%X\n", ReadW6692(cs, W_D_EXIR)); + printk(KERN_INFO "W6692 D_EXIM=0x%X\n", ReadW6692(cs, W_D_EXIM)); + printk(KERN_INFO "W6692 D_RSTA=0x%X\n", ReadW6692(cs, W_D_RSTA)); + return (1); } diff -Nru a/drivers/isdn/hisax/w6692.h b/drivers/isdn/hisax/w6692.h --- a/drivers/isdn/hisax/w6692.h Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hisax/w6692.h Thu Feb 19 23:44:23 2004 @@ -1,4 +1,4 @@ -/* $Id: w6692.h,v 1.2.6.2 2001/09/23 22:24:52 kai Exp $ +/* $Id: w6692.h,v 1.4.2.2 2004/01/12 22:52:29 keil Exp $ * * Winbond W6692 specific defines * @@ -17,6 +17,9 @@ #define writeW6692fifo writeisacfifo /* B-channel FIFO read/write routines */ + +#define READW6692BFIFO(cs,bchan,ptr,count) \ + insb(cs->hw.w6692.iobase+W_B_RFIFO+(bchan?0x40:0),ptr,count) #define WRITEW6692BFIFO(cs,bchan,ptr,count) \ outsb(cs->hw.w6692.iobase+W_B_XFIFO+(bchan?0x40:0),ptr,count) diff -Nru a/drivers/isdn/hysdn/Kconfig b/drivers/isdn/hysdn/Kconfig --- a/drivers/isdn/hysdn/Kconfig Thu Feb 19 23:44:27 2004 +++ b/drivers/isdn/hysdn/Kconfig Thu Feb 19 23:44:27 2004 @@ -3,7 +3,7 @@ # config HYSDN tristate "Hypercope HYSDN cards (Champ, Ergo, Metro) support (module only)" - depends on m && PROC_FS + depends on m && PROC_FS && BROKEN_ON_SMP help Say Y here if you have one of Hypercope's active PCI ISDN cards Champ, Ergo and Metro. You will then get a module called hysdn. diff -Nru a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c --- a/drivers/isdn/hysdn/hysdn_proclog.c Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/hysdn/hysdn_proclog.c Thu Feb 19 23:44:23 2004 @@ -233,7 +233,7 @@ return (0); inf->usage_cnt--; /* new usage count */ - (struct log_data **) file->private_data = &inf->next; /* next structure */ + file->private_data = &inf->next; /* next structure */ if ((len = strlen(inf->log_start)) <= count) { if (copy_to_user(buf, inf->log_start, len)) return -EFAULT; @@ -276,9 +276,9 @@ cli(); pd->if_used++; if (pd->log_head) - (struct log_data **) filep->private_data = &(pd->log_tail->next); + filep->private_data = &pd->log_tail->next; else - (struct log_data **) filep->private_data = &(pd->log_head); + filep->private_data = &pd->log_head; restore_flags(flags); } else { /* simultaneous read/write access forbidden ! */ unlock_kernel(); diff -Nru a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig --- a/drivers/isdn/i4l/Kconfig Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/i4l/Kconfig Thu Feb 19 23:44:24 2004 @@ -2,25 +2,6 @@ # Old ISDN4Linux config # -config ISDN_NET_SIMPLE - bool ' Support raw-IP and other simple protocols' - depends on INET - help - This options enables 'raw IP over ISDN', 'ethernet over ISDN', - 'raw IP with UI header' and 'IP + type field' encapsulations. - - If you never heard of any of those, you probably want to say N. - -config ISDN_NET_CISCO - bool ' Support CISCO router protocols' - depends on INET - help - This options enables 'CISCO HDLC' encapsulation with - optional support for CISCO keep-alive frames. - - Unless you want to connect to a Cisco Router in HDLC mode, - you probably want to say N. - config ISDN_PPP bool "Support synchronous PPP" depends on INET @@ -85,7 +66,7 @@ config ISDN_X25 bool "X.25 PLP on top of ISDN" - depends on X25 && BROKEN + depends on X25 help This feature provides the X.25 protocol over ISDN connections. See for more information @@ -97,6 +78,7 @@ config ISDN_DRV_LOOP tristate "isdnloop support" + depends on BROKEN_ON_SMP help This driver provides a virtual ISDN card. Its primary purpose is testing of linklevel features or configuration without getting @@ -106,7 +88,7 @@ config ISDN_DIVERSION tristate "Support isdn diversion services" - depends on BROKEN + depends on BROKEN && BROKEN_ON_SMP help This option allows you to use some supplementary diversion services in conjunction with the HiSax driver on an EURO/DSS1 @@ -124,3 +106,27 @@ Please read the file . endmenu + +comment "ISDN4Linux hardware drivers" + depends on NET && ISDN && ISDN_I4L + +source "drivers/isdn/hisax/Kconfig" + + +menu "Active cards" + depends on NET && ISDN && ISDN_I4L!=n + +source "drivers/isdn/icn/Kconfig" + +source "drivers/isdn/pcbit/Kconfig" + +source "drivers/isdn/sc/Kconfig" + +source "drivers/isdn/act2000/Kconfig" + +source "drivers/isdn/tpam/Kconfig" + +source "drivers/isdn/hysdn/Kconfig" + +endmenu + diff -Nru a/drivers/isdn/i4l/Makefile b/drivers/isdn/i4l/Makefile --- a/drivers/isdn/i4l/Makefile Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/i4l/Makefile Thu Feb 19 23:44:24 2004 @@ -2,18 +2,17 @@ # Each configuration option enables a list of files. -obj-$(CONFIG_ISDN) += isdn.o +obj-$(CONFIG_ISDN_I4L) += isdn.o obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o # Multipart objects. -isdn-y := isdn_net_lib.o isdn_fsm.o isdn_tty.o \ - isdn_v110.o isdn_common.o -isdn-$(CONFIG_ISDN_NET_SIMPLE) += isdn_net.o -isdn-$(CONFIG_ISDN_NET_CISCO) += isdn_ciscohdlck.o -isdn-$(CONFIG_ISDN_PPP) += isdn_ppp.o isdn_ppp_ccp.o -isdn-$(CONFIG_ISDN_PPP_VJ) += isdn_ppp_vj.o -isdn-$(CONFIG_ISDN_MPP) += isdn_ppp_mp.o +isdn-y := isdn_net.o isdn_tty.o isdn_v110.o isdn_common.o + +# Optional parts of multipart objects. + +isdn-$(CONFIG_ISDN_PPP) += isdn_ppp.o isdn-$(CONFIG_ISDN_X25) += isdn_concap.o isdn_x25iface.o -isdn-$(CONFIG_ISDN_AUDIO) += isdn_audio.o +isdn-$(CONFIG_ISDN_AUDIO) += isdn_audio.o isdn-$(CONFIG_ISDN_TTY_FAX) += isdn_ttyfax.o + diff -Nru a/drivers/isdn/i4l/isdn_audio.c b/drivers/isdn/i4l/isdn_audio.c --- a/drivers/isdn/i4l/isdn_audio.c Thu Feb 19 23:44:22 2004 +++ b/drivers/isdn/i4l/isdn_audio.c Thu Feb 19 23:44:22 2004 @@ -1,20 +1,21 @@ -/* Linux ISDN subsystem, audio conversion and compression +/* $Id: isdn_audio.c,v 1.1.2.2 2004/01/12 22:37:18 keil Exp $ + * + * Linux ISDN subsystem, audio conversion and compression (linklevel). * * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) - * 1996 by Christian Mock (cm@tahina.priv.at) - * 1998 by Armin Schindler (mac@gismo.telekom.de) + * DTMF code (c) 1996 by Christian Mock (cm@kukuruz.ping.at) + * Silence detection (c) 1998 by Armin Schindler (mac@gismo.telekom.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * - * DTMF code by Christian Mock - * Silence detection by Armin Schindler */ #include #include "isdn_audio.h" #include "isdn_common.h" -#include "isdn_tty.h" + +char *isdn_audio_revision = "$Revision: 1.1.2.2 $"; /* * Misc. lookup-tables. @@ -168,39 +169,19 @@ 0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a }; -#define NCOEFF 16 /* number of frequencies to be analyzed */ -#define DTMF_TRESH 25000 /* above this is dtmf */ +#define NCOEFF 8 /* number of frequencies to be analyzed */ +#define DTMF_TRESH 4000 /* above this is dtmf */ #define SILENCE_TRESH 200 /* below this is silence */ -#define H2_TRESH 20000 /* 2nd harmonic */ #define AMP_BITS 9 /* bits per sample, reduced to avoid overflow */ #define LOGRP 0 #define HIGRP 1 -typedef struct { - int grp; /* low/high group */ - int k; /* k */ - int k2; /* k fuer 2. harmonic */ -} dtmf_t; - /* For DTMF recognition: * 2 * cos(2 * PI * k / N) precalculated for all k */ static int cos2pik[NCOEFF] = { - 55812, 29528, 53603, 24032, 51193, 14443, 48590, 6517, - 38113, -21204, 33057, -32186, 25889, -45081, 18332, -55279 -}; - -static dtmf_t dtmf_tones[8] = -{ - {LOGRP, 0, 1}, /* 697 Hz */ - {LOGRP, 2, 3}, /* 770 Hz */ - {LOGRP, 4, 5}, /* 852 Hz */ - {LOGRP, 6, 7}, /* 941 Hz */ - {HIGRP, 8, 9}, /* 1209 Hz */ - {HIGRP, 10, 11}, /* 1336 Hz */ - {HIGRP, 12, 13}, /* 1477 Hz */ - {HIGRP, 14, 15} /* 1633 Hz */ + 55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332 }; static char dtmf_matrix[4][4] = @@ -226,10 +207,8 @@ : "0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff) : "memory", "ax"); #else - while (n--) { - *buff = table[*buff]; - buff++; - } + while (n--) + *buff = table[*(unsigned char *)buff], buff++; #endif } @@ -500,13 +479,25 @@ sk2 = sk1; sk1 = sk; } + /* Avoid overflows */ + sk >>= 1; + sk2 >>= 1; + /* compute |X(k)|**2 */ + /* report overflows. This should not happen. */ + /* Comment this out if desired */ + if (sk < -32768 || sk > 32767) + printk(KERN_DEBUG + "isdn_audio: dtmf goertzel overflow, sk=%d\n", sk); + if (sk2 < -32768 || sk2 > 32767) + printk(KERN_DEBUG + "isdn_audio: dtmf goertzel overflow, sk2=%d\n", sk2); result[k] = ((sk * sk) >> AMP_BITS) - ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) + ((sk2 * sk2) >> AMP_BITS); } skb_queue_tail(&info->dtmf_queue, skb); - mod_timer(&info->read_timer, jiffies + 4); + isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); } void @@ -517,31 +508,63 @@ dtmf_state *s; int silence; int i; + int di; + int ch; int grp[2]; char what; char *p; + int thresh; while ((skb = skb_dequeue(&info->dtmf_queue))) { result = (int *) skb->data; s = info->dtmf_state; - grp[LOGRP] = grp[HIGRP] = -2; + grp[LOGRP] = grp[HIGRP] = -1; silence = 0; - for (i = 0; i < 8; i++) { - if ((result[dtmf_tones[i].k] > DTMF_TRESH) && - (result[dtmf_tones[i].k2] < H2_TRESH)) - grp[dtmf_tones[i].grp] = (grp[dtmf_tones[i].grp] == -2) ? i : -1; - else if ((result[dtmf_tones[i].k] < SILENCE_TRESH) && - (result[dtmf_tones[i].k2] < SILENCE_TRESH)) + thresh = 0; + for (i = 0; i < NCOEFF; i++) { + if (result[i] > DTMF_TRESH) { + if (result[i] > thresh) + thresh = result[i]; + } + else if (result[i] < SILENCE_TRESH) silence++; } - if (silence == 8) + if (silence == NCOEFF) what = ' '; else { - if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) { - what = dtmf_matrix[grp[LOGRP]][grp[HIGRP] - 4]; - if (s->last != ' ' && s->last != '.') - s->last = what; /* min. 1 non-DTMF between DTMF */ - } else + if (thresh > 0) { + thresh = thresh >> 4; /* touchtones must match within 12 dB */ + for (i = 0; i < NCOEFF; i++) { + if (result[i] < thresh) + continue; /* ignore */ + /* good level found. This is allowed only one time per group */ + if (i < NCOEFF / 2) { + /* lowgroup*/ + if (grp[LOGRP] >= 0) { + // Bad. Another tone found. */ + grp[LOGRP] = -1; + break; + } + else + grp[LOGRP] = i; + } + else { /* higroup */ + if (grp[HIGRP] >= 0) { // Bad. Another tone found. */ + grp[HIGRP] = -1; + break; + } + else + grp[HIGRP] = i - NCOEFF/2; + } + } + if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) { + what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]]; + if (s->last != ' ' && s->last != '.') + s->last = what; /* min. 1 non-DTMF between DTMF */ + } else + what = '.'; + } + else what = '.'; } if ((what != s->last) && (what != ' ') && (what != '.')) { @@ -550,17 +573,16 @@ *p++ = 0x10; *p = what; skb_trim(skb, 2); - if ((size_t)skb_headroom(skb) < sizeof(isdnaudio_header)) { - printk(KERN_WARNING - "isdn_audio: insufficient skb_headroom, dropping\n"); - kfree_skb(skb); - return; - } ISDN_AUDIO_SKB_DLECOUNT(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0; - isdn_tty_queue_tail(info, skb, 2); - if (((get_isdn_dev())->modempoll) && (info->rcvsched)) - mod_timer(&info->read_timer, jiffies + 4); + di = info->isdn_driver; + ch = info->isdn_channel; + __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb); + dev->drv[di]->rcvcount[ch] += 2; + /* Schedule dequeuing */ + if ((dev->modempoll) && (info->rcvsched)) + isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); + wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]); } else kfree_skb(skb); s->last = what; @@ -648,6 +670,8 @@ isdn_audio_put_dle_code(modem_info * info, u_char code) { struct sk_buff *skb; + int di; + int ch; char *p; skb = dev_alloc_skb(2); @@ -660,18 +684,16 @@ p = (char *) skb_put(skb, 2); p[0] = 0x10; p[1] = code; - if ((size_t)skb_headroom(skb) < sizeof(isdnaudio_header)) { - printk(KERN_WARNING - "isdn_audio: insufficient skb_headroom, dropping\n"); - kfree_skb(skb); - return; - } ISDN_AUDIO_SKB_DLECOUNT(skb) = 0; ISDN_AUDIO_SKB_LOCK(skb) = 0; - isdn_tty_queue_tail(info, skb, 2); + di = info->isdn_driver; + ch = info->isdn_channel; + __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb); + dev->drv[di]->rcvcount[ch] += 2; /* Schedule dequeuing */ - if (((get_isdn_dev())->modempoll) && (info->rcvsched)) - mod_timer(&info->read_timer, jiffies + 4); + if ((dev->modempoll) && (info->rcvsched)) + isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1); + wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]); } void @@ -682,7 +704,7 @@ what = ' '; - if (s->idx > (u_int)(info->emu.vpar[2] * 800)) { + if (s->idx > (info->emu.vpar[2] * 800)) { s->idx = 0; if (!s->state) { /* silence from beginning of rec */ what = 's'; @@ -690,9 +712,9 @@ what = 'q'; } } - if ((what == 's') || (what == 'q')) { - printk(KERN_DEBUG "ttyI%d: %s\n", info->line, - (what=='s') ? "silence":"quiet"); - isdn_audio_put_dle_code(info, what); - } + if ((what == 's') || (what == 'q')) { + printk(KERN_DEBUG "ttyI%d: %s\n", info->line, + (what=='s') ? "silence":"quiet"); + isdn_audio_put_dle_code(info, what); + } } diff -Nru a/drivers/isdn/i4l/isdn_audio.h b/drivers/isdn/i4l/isdn_audio.h --- a/drivers/isdn/i4l/isdn_audio.h Thu Feb 19 23:44:23 2004 +++ b/drivers/isdn/i4l/isdn_audio.h Thu Feb 19 23:44:23 2004 @@ -1,4 +1,6 @@ -/* Linux ISDN subsystem, audio conversion and compression +/* $Id: isdn_audio.h,v 1.1.2.2 2004/01/12 22:37:18 keil Exp $ + * + * Linux ISDN subsystem, audio conversion and compression (linklevel). * * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) * @@ -18,6 +20,7 @@ typedef struct dtmf_state { char last; + char llast; int idx; int buf[DTMF_NPOINTS]; } dtmf_state; diff -Nru a/drivers/isdn/i4l/isdn_ciscohdlck.c b/drivers/isdn/i4l/isdn_ciscohdlck.c --- a/drivers/isdn/i4l/isdn_ciscohdlck.c Thu Feb 19 23:44:22 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,452 +0,0 @@ -/* Linux ISDN subsystem, CISCO HDLC network interfaces - * - * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de) - * 1995,96 by Thinking Objects Software GmbH Wuerzburg - * 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de) - * 1999-2002 by Kai Germaschewski - * 2001 by Bjoern A. Zeeb - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - * - * For info on the protocol, see http://i4l.zabbadoz.net/i4l/cisco-hdlc.txt - */ - -#include "isdn_common.h" -#include "isdn_net_lib.h" -#include "isdn_ciscohdlck.h" - -#include -#include - -/* - * Definitions for Cisco-HDLC header. - */ - -#define CISCO_ADDR_UNICAST 0x0f -#define CISCO_ADDR_BROADCAST 0x8f -#define CISCO_CTRL 0x00 -#define CISCO_TYPE_CDP 0x2000 -#define CISCO_TYPE_SLARP 0x8035 -#define CISCO_SLARP_REQUEST 0 -#define CISCO_SLARP_REPLY 1 -#define CISCO_SLARP_KEEPALIVE 2 - -/* - * CISCO HDLC keepalive specific stuff - */ -static struct sk_buff* -isdn_net_ciscohdlck_alloc_skb(isdn_net_dev *idev, int len) -{ - unsigned short hl = isdn_slot_hdrlen(idev->isdn_slot); - struct sk_buff *skb; - - skb = alloc_skb(hl + len, GFP_ATOMIC); - if (!skb) { - printk("isdn out of mem at %s:%d!\n", __FILE__, __LINE__); - return NULL; - } - skb_reserve(skb, hl); - return skb; -} - -/* cisco hdlck device private ioctls */ -static int -isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - isdn_net_local *mlp = dev->priv; - struct inl_cisco *cisco = mlp->inl_priv; - unsigned long len = 0; - int period; - char debserint; - int rc = 0; - - if (mlp->p_encap != ISDN_NET_ENCAP_CISCOHDLCK) - return -EINVAL; - - switch (cmd) { - /* get/set keepalive period */ - case SIOCGKEEPPERIOD: - len = sizeof(cisco->keepalive_period); - if (copy_to_user((char *)ifr->ifr_ifru.ifru_data, - (char *)&cisco->keepalive_period, len)) - rc = -EFAULT; - break; - case SIOCSKEEPPERIOD: - len = sizeof(cisco->keepalive_period); - if (copy_from_user((char *)&period, - (char *)ifr->ifr_ifru.ifru_data, len)) { - rc = -EFAULT; - break; - } - if (period <= 0 || period > 32767) { - rc = -EINVAL; - break; - } - mod_timer(&cisco->timer, jiffies + period * HZ); - printk(KERN_INFO "%s: Keepalive period set " - "to %d seconds.\n", dev->name, period); - cisco->keepalive_period = period; - break; - - /* get/set debugging */ - case SIOCGDEBSERINT: - len = sizeof(cisco->debserint); - if (copy_to_user((char *)ifr->ifr_ifru.ifru_data, - (char *)&cisco->debserint, len)) - rc = -EFAULT; - break; - case SIOCSDEBSERINT: - len = sizeof(cisco->debserint); - if (copy_from_user((char *)&debserint, - (char *)ifr->ifr_ifru.ifru_data, len)) { - rc = -EFAULT; - break; - } - if (debserint < 0 || debserint > 64) { - rc = -EINVAL; - break; - } - cisco->debserint = debserint; - break; - - default: - rc = -EINVAL; - break; - } - return (rc); -} - -/* called via cisco_timer.function */ -static void -isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data) -{ - isdn_net_local *mlp = (isdn_net_local *) data; - isdn_net_dev *idev; - struct inl_cisco *cisco = mlp->inl_priv; - struct sk_buff *skb; - unsigned char *p; - unsigned long last_cisco_myseq = cisco->myseq; - int myseq_diff = 0; - - if (list_empty(&mlp->online)) { - isdn_BUG(); - return; - } - idev = list_entry(mlp->online.next, isdn_net_dev, online); - cisco->myseq++; - - myseq_diff = cisco->myseq - cisco->mineseen; - if (cisco->line_state && (myseq_diff >= 3 || myseq_diff <= -3)) { - /* line up -> down */ - cisco->line_state = 0; - printk (KERN_WARNING - "UPDOWN: Line protocol on Interface %s," - " changed state to down\n", idev->name); - /* should stop routing higher-level data accross */ - } else if (!cisco->line_state && - myseq_diff >= 0 && myseq_diff <= 2) { - /* line down -> up */ - cisco->line_state = 1; - printk (KERN_WARNING - "UPDOWN: Line protocol on Interface %s," - " changed state to up\n", idev->name); - /* restart routing higher-level data accross */ - } - - if (cisco->debserint) - printk (KERN_DEBUG "%s: HDLC " - "myseq %u, mineseen %u%c, yourseen %u, %s\n", - idev->name, cisco->myseq, cisco->mineseen, - (last_cisco_myseq == cisco->mineseen) ? '*' : 040, - cisco->yourseq, - (cisco->line_state) ? "line up" : "line down"); - - skb = isdn_net_ciscohdlck_alloc_skb(idev, 4 + 14); - if (!skb) - return; - - p = skb_put(skb, 4 + 14); - - /* cisco header */ - p += put_u8 (p, CISCO_ADDR_UNICAST); - p += put_u8 (p, CISCO_CTRL); - p += put_u16(p, CISCO_TYPE_SLARP); - - /* slarp keepalive */ - p += put_u32(p, CISCO_SLARP_KEEPALIVE); - p += put_u32(p, cisco->myseq); - p += put_u32(p, cisco->yourseq); - p += put_u16(p, 0xffff); // reliablity, always 0xffff - - isdn_net_write_super(idev, skb); - - mod_timer(&cisco->timer, jiffies + cisco->keepalive_period * HZ); -} - -static void -isdn_net_ciscohdlck_slarp_send_request(isdn_net_local *mlp) -{ - isdn_net_dev *idev; - struct sk_buff *skb; - unsigned char *p; - - if (list_empty(&mlp->online)) { - isdn_BUG(); - return; - } - idev = list_entry(mlp->online.next, isdn_net_dev, online); - - skb = isdn_net_ciscohdlck_alloc_skb(idev, 4 + 14); - if (!skb) - return; - - p = skb_put(skb, 4 + 14); - - /* cisco header */ - p += put_u8 (p, CISCO_ADDR_UNICAST); - p += put_u8 (p, CISCO_CTRL); - p += put_u16(p, CISCO_TYPE_SLARP); - - /* slarp request */ - p += put_u32(p, CISCO_SLARP_REQUEST); - p += put_u32(p, 0); // address - p += put_u32(p, 0); // netmask - p += put_u16(p, 0); // unused - - isdn_net_write_super(idev, skb); -} - -static void -isdn_ciscohdlck_connected(isdn_net_dev *idev) -{ - isdn_net_local *lp = idev->mlp; - struct inl_cisco *cisco = lp->inl_priv; - - cisco->myseq = 0; - cisco->mineseen = 0; - cisco->yourseq = 0; - cisco->keepalive_period = 10; - cisco->last_slarp_in = 0; - cisco->line_state = 0; - cisco->debserint = 0; - - if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) { - /* send slarp request because interface/seq.no.s reset */ - isdn_net_ciscohdlck_slarp_send_request(lp); - - init_timer(&cisco->timer); - cisco->timer.data = (unsigned long) lp; - cisco->timer.function = isdn_net_ciscohdlck_slarp_send_keepalive; - cisco->timer.expires = jiffies + cisco->keepalive_period * HZ; - add_timer(&cisco->timer); - } - netif_wake_queue(&lp->dev); -} - -static void -isdn_ciscohdlck_disconnected(isdn_net_dev *idev) -{ - isdn_net_local *lp = idev->mlp; - struct inl_cisco *cisco = lp->inl_priv; - - if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK) { - del_timer(&cisco->timer); - } -} - -static void -isdn_net_ciscohdlck_slarp_send_reply(isdn_net_dev *idev) -{ - isdn_net_local *mlp = idev->mlp; - struct sk_buff *skb; - unsigned char *p; - struct in_device *in_dev = NULL; - u32 addr = 0; /* local ipv4 address */ - u32 mask = 0; /* local netmask */ - - if ((in_dev = mlp->dev.ip_ptr) != NULL) { - /* take primary(first) address of interface */ - struct in_ifaddr *ifa = in_dev->ifa_list; - if (ifa != NULL) { - addr = ifa->ifa_local; - mask = ifa->ifa_mask; - } - } - - skb = isdn_net_ciscohdlck_alloc_skb(idev, 4 + 14); - if (!skb) - return; - - p = skb_put(skb, 4 + 14); - - /* cisco header */ - p += put_u8 (p, CISCO_ADDR_UNICAST); - p += put_u8 (p, CISCO_CTRL); - p += put_u16(p, CISCO_TYPE_SLARP); - - /* slarp reply, send own ip/netmask; if values are nonsense remote - * should think we are unable to provide it with an address via SLARP */ - p += put_u32(p, CISCO_SLARP_REPLY); - p += put_u32(p, addr); // address - p += put_u32(p, mask); // netmask - p += put_u16(p, 0); // unused - - isdn_net_write_super(idev, skb); -} - -static void -isdn_net_ciscohdlck_slarp_in(isdn_net_dev *idev, struct sk_buff *skb) -{ - isdn_net_local *mlp = idev->mlp; - struct inl_cisco *cisco = mlp->inl_priv; - unsigned char *p; - int period; - u32 code; - u32 my_seq, addr; - u32 your_seq, mask; - u32 local; - u16 unused; - - if (skb->len < 14) - return; - - p = skb->data; - p += get_u32(p, &code); - - switch (code) { - case CISCO_SLARP_REQUEST: - cisco->yourseq = 0; - isdn_net_ciscohdlck_slarp_send_reply(idev); - break; - case CISCO_SLARP_REPLY: - addr = ntohl(*(u32 *)p); - mask = ntohl(*(u32 *)(p+4)); - if (mask != 0xfffffffc) - goto slarp_reply_out; - if ((addr & 3) == 0 || (addr & 3) == 3) - goto slarp_reply_out; - local = addr ^ 3; - printk(KERN_INFO "%s: got slarp reply: " - "remote ip: %d.%d.%d.%d, " - "local ip: %d.%d.%d.%d " - "mask: %d.%d.%d.%d\n", - idev->name, - HIPQUAD(addr), - HIPQUAD(local), - HIPQUAD(mask)); - break; - slarp_reply_out: - printk(KERN_INFO "%s: got invalid slarp " - "reply (%d.%d.%d.%d/%d.%d.%d.%d) " - "- ignored\n", idev->name, - HIPQUAD(addr), HIPQUAD(mask)); - break; - case CISCO_SLARP_KEEPALIVE: - period = (jiffies - cisco->last_slarp_in + HZ/2 - 1) / HZ; - if (cisco->debserint && - (period != cisco->keepalive_period) && - cisco->last_slarp_in) { - printk(KERN_DEBUG "%s: Keepalive period mismatch - " - "is %d but should be %d.\n", - idev->name, period, cisco->keepalive_period); - } - cisco->last_slarp_in = jiffies; - p += get_u32(p, &my_seq); - p += get_u32(p, &your_seq); - p += get_u16(p, &unused); - cisco->yourseq = my_seq; - cisco->mineseen = your_seq; - break; - } -} - -static void -isdn_ciscohdlck_receive(isdn_net_local *lp, isdn_net_dev *idev, - struct sk_buff *skb) -{ - struct inl_cisco *cisco = lp->inl_priv; - unsigned char *p; - u8 addr; - u8 ctrl; - u16 type; - - if (skb->len < 4) - goto out_free; - - p = skb->data; - p += get_u8 (p, &addr); - p += get_u8 (p, &ctrl); - p += get_u16(p, &type); - skb_pull(skb, 4); - - if ((addr != CISCO_ADDR_UNICAST && addr != CISCO_ADDR_BROADCAST) || - ctrl != CISCO_CTRL) { - printk(KERN_DEBUG "%s: Unknown Cisco header %#02x %#02x\n", - idev->name, addr, ctrl); - goto out_free; - } - - switch (type) { - case CISCO_TYPE_SLARP: - isdn_net_ciscohdlck_slarp_in(idev, skb); - goto out_free; - case CISCO_TYPE_CDP: - if (cisco->debserint) - printk(KERN_DEBUG "%s: Received CDP packet. use " - "\"no cdp enable\" on cisco.\n", idev->name); - goto out_free; - default: - /* no special cisco protocol */ - idev->huptimer = 0; - skb->protocol = htons(type); - netif_rx(skb); - return; - } - - out_free: - kfree_skb(skb); -} - -static int -isdn_ciscohdlck_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, - void *daddr, void *saddr, unsigned plen) -{ - unsigned char *p = skb_push(skb, 4); - - p += put_u8 (p, CISCO_ADDR_UNICAST); - p += put_u8 (p, CISCO_CTRL); - p += put_u16(p, type); - - return 4; -} - -static int -isdn_ciscohdlck_open(isdn_net_local *lp) -{ - lp->inl_priv = kmalloc(sizeof(struct inl_cisco), GFP_KERNEL); - if (!lp->inl_priv) - return -ENOMEM; - - return 0; -} - -static void -isdn_ciscohdlck_close(isdn_net_local *lp) -{ - kfree(lp->inl_priv); -} - -struct isdn_netif_ops isdn_ciscohdlck_ops = { - .hard_start_xmit = isdn_net_start_xmit, - .hard_header = isdn_ciscohdlck_header, - .do_ioctl = isdn_ciscohdlck_dev_ioctl, - .flags = IFF_NOARP | IFF_POINTOPOINT, - .type = ARPHRD_CISCO, - .receive = isdn_ciscohdlck_receive, - .connected = isdn_ciscohdlck_connected, - .disconnected = isdn_ciscohdlck_disconnected, - .open = isdn_ciscohdlck_open, - .close = isdn_ciscohdlck_close, -}; diff -Nru a/drivers/isdn/i4l/isdn_ciscohdlck.h b/drivers/isdn/i4l/isdn_ciscohdlck.h --- a/drivers/isdn/i4l/isdn_ciscohdlck.h Thu Feb 19 23:44:28 2004 +++ /dev/null Wed Dec 31 16:00:00 1969 @@ -1,26 +0,0 @@ -/* Linux ISDN subsystem, CISCO HDLC network interfaces - * - * Copyright 1999-2002 by Kai Germaschewski - * 2001 by Bjoern A. Zeeb - * - * This software may be used and distributed according to the terms - * of the GNU General Public License, incorporated herein by reference. - */ - -#ifndef ISDN_CISCOHDLCK_H -#define ISDN_CISCOHDLCK_H - -extern struct isdn_netif_ops isdn_ciscohdlck_ops; - -struct inl_cisco { - u32 myseq; /* local keepalive seq. for Cisco */ - u32 mineseen; /* returned keepalive seq. from remote */ - u32 yourseq; /* remote keepalive seq. for Cisco */ - int keepalive_period; /* keepalive period */ - int last_slarp_in; /* jiffie of last recvd keepalive pkt */ - char line_state; /* state of line */ - char debserint; /* debugging flags */ - struct timer_list timer; -}; - -#endif diff -Nru a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c --- a/drivers/isdn/i4l/isdn_common.c Thu Feb 19 23:44:24 2004 +++ b/drivers/isdn/i4l/isdn_common.c Thu Feb 19 23:44:24 2004 @@ -1,4 +1,6 @@ -/* Linux ISDN subsystem, common used functions +/* $Id: isdn_common.c,v 1.1.2.3 2004/02/10 01:07:13 keil Exp $ + * + * Linux ISDN subsystem, common used functions (linklevel). * * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de) * Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg @@ -6,6 +8,7 @@ * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. + * */ #include @@ -16,958 +19,94 @@ #include #include #include -#include #include "isdn_common.h" -#include "isdn_net_lib.h" -#include "isdn_net.h" #include "isdn_tty.h" +#include "isdn_net.h" #include "isdn_ppp.h" #ifdef CONFIG_ISDN_AUDIO #include "isdn_audio.h" #endif +#ifdef CONFIG_ISDN_DIVERSION_MODULE +#define CONFIG_ISDN_DIVERSION +#endif +#ifdef CONFIG_ISDN_DIVERSION #include -#include +#endif /* CONFIG_ISDN_DIVERSION */ +#include "isdn_v110.h" + +/* Debugflags */ +#undef ISDN_DEBUG_STATCALLB MODULE_DESCRIPTION("ISDN4Linux: link layer"); MODULE_AUTHOR("Fritz Elfert"); MODULE_LICENSE("GPL"); -static isdn_dev_t *isdndev; - -isdn_dev_t * -get_isdn_dev(void) { - return(isdndev); -} - -/* Description of hardware-level-driver */ -typedef struct isdn_driver { - int di; - char id[20]; - atomic_t refcnt; - unsigned long flags; /* Misc driver Flags */ - unsigned long features; - int channels; /* Number of channels */ - wait_queue_head_t st_waitq; /* Wait-Queue for status-reads */ - int maxbufsize; /* Maximum Buffersize supported*/ - int stavail; /* Chars avail on Status-device*/ - isdn_if *interface; /* Interface to driver */ - char msn2eaz[10][ISDN_MSNLEN]; /* MSN->EAZ */ - spinlock_t lock; - struct isdn_slot *slots; - struct fsm_inst fi; -} isdn_driver_t; - -static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED; -static isdn_driver_t *drivers[ISDN_MAX_DRIVERS]; - -static void isdn_lock_driver(struct isdn_driver *drv); -static void isdn_unlock_driver(struct isdn_driver *drv); - -/* ====================================================================== */ - -static void drv_destroy(struct isdn_driver *drv); - -static inline struct isdn_driver * -get_drv(struct isdn_driver *drv) -{ - printk("get_drv %d: %d -> %d\n", drv->di, atomic_read(&drv->refcnt), - atomic_read(&drv->refcnt) + 1); - atomic_inc(&drv->refcnt); - return drv; -} - -static inline void -put_drv(struct isdn_driver *drv) -{ - printk("put_drv %d: %d -> %d\n", drv->di, atomic_read(&drv->refcnt), - atomic_read(&drv->refcnt) - 1); - if (atomic_dec_and_test(&drv->refcnt)) { - drv_destroy(drv); - } -} - -/* ====================================================================== */ - -static struct fsm slot_fsm; -static void slot_debug(struct fsm_inst *fi, char *fmt, ...); - -static char *slot_st_str[] = { - "ST_SLOT_NULL", - "ST_SLOT_BOUND", - "ST_SLOT_IN", - "ST_SLOT_WAIT_DCONN", - "ST_SLOT_DCONN", - "ST_SLOT_WAIT_BCONN", - "ST_SLOT_ACTIVE", - "ST_SLOT_WAIT_BHUP", - "ST_SLOT_WAIT_DHUP", -}; - -static char *ev_str[] = { - "EV_DRV_REGISTER", - "EV_STAT_RUN", - "EV_STAT_STOP", - "EV_STAT_UNLOAD", - "EV_STAT_STAVAIL", - "EV_STAT_ADDCH", - "EV_STAT_ICALL", - "EV_STAT_DCONN", - "EV_STAT_BCONN", - "EV_STAT_BHUP", - "EV_STAT_DHUP", - "EV_STAT_BSENT", - "EV_STAT_CINF", - "EV_STAT_CAUSE", - "EV_STAT_DISPLAY", - "EV_STAT_FAXIND", - "EV_STAT_AUDIO", - "EV_CMD_CLREAZ", - "EV_CMD_SETEAZ", - "EV_CMD_SETL2", - "EV_CMD_SETL3", - "EV_CMD_DIAL", - "EV_CMD_ACCEPTD", - "EV_CMD_ACCEPTB", - "EV_CMD_HANGUP", - "EV_DATA_REQ", - "EV_DATA_IND", - "EV_SLOT_BIND", - "EV_SLOT_UNBIND", -}; - -static int __slot_command(struct isdn_slot *slot, isdn_ctrl *cmd); - -static void isdn_v110_setl2(struct isdn_slot *slot, isdn_ctrl *cmd); -static void __isdn_v110_open(struct isdn_slot *slot); -static void __isdn_v110_close(struct isdn_slot *slot); -static void __isdn_v110_bsent(struct isdn_slot *slot, int pr, isdn_ctrl *cmd); -static int isdn_v110_data_ind(struct isdn_slot *slot, struct sk_buff *skb); -static int isdn_v110_data_req(struct isdn_slot *slot, struct sk_buff *skb); - -static inline int -do_event_cb(struct isdn_slot *slot, int pr, void *arg) -{ - if (slot->event_cb) - return slot->event_cb(slot, pr, arg); - - return -ENXIO; -} - -static int -slot_bind(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - - isdn_lock_driver(slot->drv); - fsm_change_state(fi, ST_SLOT_BOUND); - - return 0; -} - -/* just pass through command */ -static int -slot_command(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl *c = arg; - - return __slot_command(slot, c); -} - -/* just pass through status */ -static int -slot_stat(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - - do_event_cb(slot, pr, arg); - return 0; -} - -/* just pass through command */ -static int -slot_setl2(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl *c = arg; - - isdn_v110_setl2(slot, c); - - return __slot_command(slot, c); -} - -static int -slot_dial(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl *ctrl = arg; - int retval; - - retval = __slot_command(slot, ctrl); - if (retval >= 0) - fsm_change_state(fi, ST_SLOT_WAIT_DCONN); - - return retval; -} - -static int -slot_acceptd(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl *ctrl = arg; - int retval; - - retval = __slot_command(slot, ctrl); - if (retval >= 0) - fsm_change_state(fi, ST_SLOT_WAIT_DCONN); - - return retval; -} - -static int -slot_acceptb(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl *ctrl = arg; - int retval; - - retval = __slot_command(slot, ctrl); - if (retval >= 0) - fsm_change_state(fi, ST_SLOT_WAIT_BCONN); - - return retval; -} - -static int -slot_actv_hangup(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl *ctrl = arg; - int retval; - - retval = __slot_command(slot, ctrl); - if (retval >= 0) { - fsm_change_state(fi, ST_SLOT_WAIT_BHUP); - } - return retval; -} - -static int -slot_dconn(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - - fsm_change_state(fi, ST_SLOT_DCONN); - do_event_cb(slot, pr, arg); - return 0; -} - -static int -slot_bconn(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - - fsm_change_state(fi, ST_SLOT_ACTIVE); - __isdn_v110_open(slot); - - isdn_info_update(); - - do_event_cb(slot, pr, arg); - return 0; -} - -static int -slot_bhup(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - - __isdn_v110_close(slot); - fsm_change_state(fi, ST_SLOT_WAIT_DHUP); - - do_event_cb(slot, pr, arg); - return 0; -} - -static int -slot_dhup(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; +isdn_dev *dev; - fsm_change_state(fi, ST_SLOT_BOUND); +static char *isdn_revision = "$Revision: 1.1.2.3 $"; - do_event_cb(slot, pr, arg); - return 0; -} - -static int -slot_data_req(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - struct sk_buff *skb = arg; - - return isdn_v110_data_req(slot, skb); -} - -static int -slot_data_ind(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - struct sk_buff *skb = arg; - - /* Update statistics */ - slot->ibytes += skb->len; - - return isdn_v110_data_ind(slot, skb); -} - -static int -slot_bsent(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl *ctrl = arg; - - __isdn_v110_bsent(slot, pr, ctrl); - return 0; -} - -static int -slot_icall(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl *ctrl = arg; - int retval; - - isdn_lock_driver(slot->drv); - fsm_change_state(fi, ST_SLOT_IN); - slot_debug(fi, "ICALL: %s\n", ctrl->parm.num); - if (isdndev->global_flags & ISDN_GLOBAL_STOPPED) - return 0; - - strcpy(slot->num, ctrl->parm.setup.phone); - /* Try to find a network-interface which will accept incoming call */ - retval = isdn_net_find_icall(slot, &ctrl->parm.setup); - - /* already taken by net now? */ - if (fi->state != ST_SLOT_IN) - goto out; - - retval = isdn_tty_find_icall(slot, &ctrl->parm.setup); - out: - return 0; -} - -/* should become broadcast later */ -static int -slot_in_dhup(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - - isdn_unlock_driver(slot->drv); - fsm_change_state(fi, ST_SLOT_NULL); - do_event_cb(slot, pr, arg); - return 0; -} - -static int -slot_unbind(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_slot *slot = fi->userdata; - isdn_ctrl cmd; - - isdn_unlock_driver(slot->drv); - fsm_change_state(fi, ST_SLOT_NULL); - strcpy(slot->num, "???"); - cmd.parm.num[0] = '\0'; - isdn_slot_command(slot, ISDN_CMD_SETEAZ, &cmd); - slot->ibytes = 0; - slot->obytes = 0; - slot->usage = ISDN_USAGE_NONE; - put_drv(slot->drv); - isdn_info_update(); - return 0; -} - -static struct fsm_node slot_fn_tbl[] = { - { ST_SLOT_NULL, EV_SLOT_BIND, slot_bind }, - { ST_SLOT_NULL, EV_STAT_ICALL, slot_icall }, - - { ST_SLOT_BOUND, EV_CMD_CLREAZ, slot_command }, - { ST_SLOT_BOUND, EV_CMD_SETEAZ, slot_command }, - { ST_SLOT_BOUND, EV_CMD_SETL2, slot_setl2 }, - { ST_SLOT_BOUND, EV_CMD_SETL3, slot_command }, - { ST_SLOT_BOUND, EV_CMD_DIAL, slot_dial }, - { ST_SLOT_BOUND, EV_SLOT_UNBIND, slot_unbind }, - - { ST_SLOT_IN, EV_CMD_SETL2, slot_setl2 }, - { ST_SLOT_IN, EV_CMD_SETL3, slot_command }, - { ST_SLOT_IN, EV_CMD_ACCEPTD, slot_acceptd }, - { ST_SLOT_IN, EV_STAT_DHUP, slot_in_dhup }, - - { ST_SLOT_WAIT_DCONN, EV_STAT_DCONN, slot_dconn }, - { ST_SLOT_WAIT_DCONN, EV_STAT_DHUP, slot_dhup }, - - { ST_SLOT_DCONN, EV_CMD_ACCEPTB, slot_acceptb }, - { ST_SLOT_DCONN, EV_STAT_BCONN, slot_bconn }, - - { ST_SLOT_WAIT_BCONN, EV_STAT_BCONN, slot_bconn }, - - { ST_SLOT_ACTIVE, EV_DATA_REQ, slot_data_req }, - { ST_SLOT_ACTIVE, EV_DATA_IND, slot_data_ind }, - { ST_SLOT_ACTIVE, EV_CMD_HANGUP, slot_actv_hangup }, - { ST_SLOT_ACTIVE, EV_STAT_BSENT, slot_bsent }, - { ST_SLOT_ACTIVE, EV_STAT_BHUP, slot_bhup }, - { ST_SLOT_ACTIVE, EV_STAT_FAXIND, slot_stat }, - { ST_SLOT_ACTIVE, EV_STAT_AUDIO, slot_stat }, - - { ST_SLOT_WAIT_BHUP, EV_STAT_BHUP, slot_bhup }, - - { ST_SLOT_WAIT_DHUP, EV_STAT_DHUP, slot_dhup }, -}; - -static struct fsm slot_fsm = { - .st_cnt = ARRAY_SIZE(slot_st_str), - .st_str = slot_st_str, - .ev_cnt = ARRAY_SIZE(ev_str), - .ev_str = ev_str, - .fn_cnt = ARRAY_SIZE(slot_fn_tbl), - .fn_tbl = slot_fn_tbl, -}; - -static void slot_debug(struct fsm_inst *fi, char *fmt, ...) -{ - va_list args; - struct isdn_slot *slot = fi->userdata; - char buf[128]; - char *p = buf; - - va_start(args, fmt); - p += sprintf(p, "slot (%d:%d): ", slot->di, slot->ch); - p += vsprintf(p, fmt, args); - va_end(args); - printk(KERN_DEBUG "%s\n", buf); -} - -/* ====================================================================== */ - -static spinlock_t stat_lock = SPIN_LOCK_UNLOCKED; - -static struct fsm drv_fsm; +extern char *isdn_net_revision; +extern char *isdn_tty_revision; +#ifdef CONFIG_ISDN_PPP +extern char *isdn_ppp_revision; +#else +static char *isdn_ppp_revision = ": none $"; +#endif +#ifdef CONFIG_ISDN_AUDIO +extern char *isdn_audio_revision; +#else +static char *isdn_audio_revision = ": none $"; +#endif +extern char *isdn_v110_revision; -enum { - ST_DRV_NULL, - ST_DRV_LOADED, - ST_DRV_RUNNING, -}; +#ifdef CONFIG_ISDN_DIVERSION +static isdn_divert_if *divert_if; /* = NULL */ +#endif /* CONFIG_ISDN_DIVERSION */ -static char *drv_st_str[] = { - "ST_DRV_NULL", - "ST_DRV_LOADED", - "ST_DRV_RUNNING", -}; -#define DRV_FLAG_REJBUS 1 +static int isdn_writebuf_stub(int, int, const u_char *, int, int); +static void set_global_features(void); +static int isdn_wildmat(char *s, char *p); -static int __drv_command(struct isdn_driver *drv, isdn_ctrl *cmd); -static int -isdn_writebuf_skb(struct isdn_slot *slot, struct sk_buff *skb) +static inline void +isdn_lock_driver(isdn_driver_t *drv) { - struct sk_buff *skb2; - struct isdn_driver *drv = slot->drv; - int hl = drv->interface->hl_hdrlen; - int retval; - - if (skb_headroom(skb) >= hl) { - retval = drv->interface->writebuf_skb(slot->di, slot->ch, 1, skb); - goto out; - } - skb2 = skb_realloc_headroom(skb, hl); - if (!skb2) { - retval = -ENOMEM; - goto out; - } - retval = drv->interface->writebuf_skb(slot->di, slot->ch, 1, skb2); - if (retval < 0) - kfree_skb(skb2); - else - kfree_skb(skb); - - out: - if (retval > 0) - slot->obytes += retval; - - return retval; + try_module_get(drv->interface->owner); + drv->locks++; } -int -__isdn_drv_lookup(char *drvid) +void +isdn_lock_drivers(void) { - int drvidx; + int i; - for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) { - if (!drivers[drvidx]) + for (i = 0; i < ISDN_MAX_DRIVERS; i++) { + if (!dev->drv[i]) continue; - - if (strcmp(drivers[drvidx]->id, drvid) == 0) - return drvidx; + isdn_lock_driver(dev->drv[i]); } - return -1; } -int -isdn_drv_lookup(char *drvid) -{ - unsigned long flags; - int drvidx; - - spin_lock_irqsave(&drivers_lock, flags); - drvidx = __isdn_drv_lookup(drvid); - spin_unlock_irqrestore(&drivers_lock, flags); - return drvidx; -} - -static void -drv_destroy(struct isdn_driver *drv) -{ - kfree(drv->slots); - kfree(drv); -} - -static struct isdn_driver * -get_drv_by_nr(int di) -{ - unsigned long flags; - struct isdn_driver *drv; - - BUG_ON(di < 0 || di >= ISDN_MAX_DRIVERS); - - spin_lock_irqsave(&drivers_lock, flags); - drv = drivers[di]; - if (drv) - get_drv(drv); - spin_unlock_irqrestore(&drivers_lock, flags); - return drv; -} - -char * -isdn_drv_drvid(int di) +static inline void +isdn_unlock_driver(isdn_driver_t *drv) { - if (!drivers[di]) { - isdn_BUG(); - return ""; + if (drv->locks > 0) { + drv->locks--; + module_put(drv->interface->owner); } - return drivers[di]->id; } -/* - * Helper keeping track of the features the drivers support - */ -static void -set_global_features(void) +void +isdn_unlock_drivers(void) { - unsigned long flags; - int drvidx; + int i; - isdndev->global_features = 0; - spin_lock_irqsave(&drivers_lock, flags); - for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) { - if (!drivers[drvidx]) - continue; - if (drivers[drvidx]->fi.state != ST_DRV_RUNNING) + for (i = 0; i < ISDN_MAX_DRIVERS; i++) { + if (!dev->drv[i]) continue; - isdndev->global_features |= drivers[drvidx]->features; - } - spin_unlock_irqrestore(&drivers_lock, flags); -} - -/* - * driver state machine - */ -static int isdn_add_channels(struct isdn_driver *, int); -static void isdn_receive_skb_callback(int di, int ch, struct sk_buff *skb); -static int isdn_status_callback(isdn_ctrl * c); - -static void isdn_v110_add_features(struct isdn_driver *drv); - -static int -drv_register(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_driver *drv = fi->userdata; - isdn_if *iif = arg; - - fsm_change_state(fi, ST_DRV_LOADED); - drv->maxbufsize = iif->maxbufsize; - drv->interface = iif; - iif->channels = drv->di; - iif->rcvcallb_skb = isdn_receive_skb_callback; - iif->statcallb = isdn_status_callback; - - isdn_info_update(); - return(0); -} - -static int -drv_stat_run(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_driver *drv = fi->userdata; - fsm_change_state(fi, ST_DRV_RUNNING); - - drv->features = drv->interface->features; - isdn_v110_add_features(drv); - set_global_features(); - return(0); -} - -static int -drv_stat_stop(struct fsm_inst *fi, int pr, void *arg) -{ - fsm_change_state(fi, ST_DRV_LOADED); - set_global_features(); - return(0); -} - -static int -drv_stat_unload(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_driver *drv = fi->userdata; - unsigned long flags; - - spin_lock_irqsave(&drivers_lock, flags); - drivers[drv->di] = NULL; - spin_unlock_irqrestore(&drivers_lock, flags); - put_drv(drv); - - isdndev->channels -= drv->channels; - - isdn_info_update(); - return 0; -} - -static int -drv_stat_stavail(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_driver *drv = fi->userdata; - unsigned long flags; - isdn_ctrl *c = arg; - - spin_lock_irqsave(&stat_lock, flags); - drv->stavail += c->arg; - spin_unlock_irqrestore(&stat_lock, flags); - wake_up_interruptible(&drv->st_waitq); - return 0; -} - -static int -drv_to_slot(struct fsm_inst *fi, int pr, void *arg) -{ - struct isdn_driver *drv = fi->userdata; - isdn_ctrl *c = arg; - int ch = c->arg & 0xff; - - return fsm_event(&drv->slots[ch].fi, pr, arg); -} - -static struct fsm_node drv_fn_tbl[] = { - { ST_DRV_NULL, EV_DRV_REGISTER, drv_register }, - - { ST_DRV_LOADED, EV_STAT_RUN, drv_stat_run }, - { ST_DRV_LOADED, EV_STAT_STAVAIL, drv_stat_stavail }, - { ST_DRV_LOADED, EV_STAT_UNLOAD, drv_stat_unload }, - - { ST_DRV_RUNNING, EV_STAT_STOP, drv_stat_stop }, - { ST_DRV_RUNNING, EV_STAT_STAVAIL, drv_stat_stavail }, - { ST_DRV_RUNNING, EV_STAT_ICALL, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_DCONN, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_BCONN, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_BHUP, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_DHUP, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_BSENT, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_CINF, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_CAUSE, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_DISPLAY, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_FAXIND, drv_to_slot }, - { ST_DRV_RUNNING, EV_STAT_AUDIO, drv_to_slot }, -}; - -static struct fsm drv_fsm = { - .st_cnt = ARRAY_SIZE(drv_st_str), - .st_str = drv_st_str, - .ev_cnt = ARRAY_SIZE(ev_str), - .ev_str = ev_str, - .fn_cnt = ARRAY_SIZE(drv_fn_tbl), - .fn_tbl = drv_fn_tbl, -}; - -static void drv_debug(struct fsm_inst *fi, char *fmt, ...) -{ - va_list args; - struct isdn_driver *drv = fi->userdata; - char buf[128]; - char *p = buf; - - va_start(args, fmt); - p += sprintf(p, "%s: ", drv->id); - p += vsprintf(p, fmt, args); - va_end(args); - printk(KERN_DEBUG "%s\n", buf); -} - -/* ====================================================================== */ -/* callbacks from hardware driver */ -/* ====================================================================== */ - -/* Receive a packet from B-Channel. */ -static void -isdn_receive_skb_callback(int di, int ch, struct sk_buff *skb) -{ - struct isdn_driver *drv; - - drv = get_drv_by_nr(di); - if (!drv) { - /* hardware driver is buggy - driver isn't registered */ - isdn_BUG(); - goto out; - } - /* we short-cut here instead of going through the driver fsm */ - if (drv->fi.state != ST_DRV_RUNNING) { - /* hardware driver is buggy - driver isn't running */ - isdn_BUG(); - goto out; - } - if (fsm_event(&drv->slots[ch].fi, EV_DATA_IND, skb)) - dev_kfree_skb(skb); - out: - put_drv(drv); -} - -/* Receive status indications */ -static int -isdn_status_callback(isdn_ctrl *c) -{ - struct isdn_driver *drv; - int rc; - - drv = get_drv_by_nr(c->driver); - if (!drv) { - /* hardware driver is buggy - driver isn't registered */ - isdn_BUG(); - return 1; - } - - switch (c->command) { - case ISDN_STAT_STAVAIL: - rc = fsm_event(&drv->fi, EV_STAT_STAVAIL, c); - break; - case ISDN_STAT_RUN: - rc = fsm_event(&drv->fi, EV_STAT_RUN, c); - break; - case ISDN_STAT_STOP: - rc = fsm_event(&drv->fi, EV_STAT_STOP, c); - break; - case ISDN_STAT_UNLOAD: - rc = fsm_event(&drv->fi, EV_STAT_UNLOAD, c); - break; - case ISDN_STAT_ADDCH: - rc = fsm_event(&drv->fi, EV_STAT_ADDCH, c); - break; - case ISDN_STAT_ICALL: - rc = fsm_event(&drv->fi, EV_STAT_ICALL, c); - break; - case ISDN_STAT_DCONN: - rc = fsm_event(&drv->fi, EV_STAT_DCONN, c); - break; - case ISDN_STAT_BCONN: - rc = fsm_event(&drv->fi, EV_STAT_BCONN, c); - break; - case ISDN_STAT_BHUP: - rc = fsm_event(&drv->fi, EV_STAT_BHUP, c); - break; - case ISDN_STAT_DHUP: - rc = fsm_event(&drv->fi, EV_STAT_DHUP, c); - break; - case ISDN_STAT_BSENT: - rc = fsm_event(&drv->fi, EV_STAT_BSENT, c); - break; - case ISDN_STAT_CINF: - rc = fsm_event(&drv->fi, EV_STAT_CINF, c); - break; - case ISDN_STAT_CAUSE: - rc = fsm_event(&drv->fi, EV_STAT_CAUSE, c); - break; - case ISDN_STAT_DISPLAY: - rc = fsm_event(&drv->fi, EV_STAT_DISPLAY, c); - break; - case ISDN_STAT_FAXIND: - rc = fsm_event(&drv->fi, EV_STAT_FAXIND, c); - break; - case ISDN_STAT_AUDIO: - rc = fsm_event(&drv->fi, EV_STAT_AUDIO, c); - break; -#warning FIXME divert interface -#if 0 - case ISDN_STAT_ICALL: - /* Find any ttyI, waiting for D-channel setup */ - if (isdn_tty_stat_callback(i, c)) { - cmd.driver = di; - cmd.arg = c->arg; - cmd.command = ISDN_CMD_ACCEPTB; - isdn_command(&cmd); - break; - } - break; - switch (r) { - case 0: - if (divert_if) - if ((retval = divert_if->stat_callback(c))) - return(retval); /* processed */ - if ((!retval) && (drivers[di]->flags & DRV_FLAG_REJBUS)) { - /* No tty responding */ - cmd.driver = di; - cmd.arg = c->arg; - cmd.command = ISDN_CMD_HANGUP; - isdn_command(&cmd); - retval = 2; - } - break; - case 1: /* incoming call accepted by net interface */ - - case 2: /* For calling back, first reject incoming call ... */ - case 3: /* Interface found, but down, reject call actively */ - retval = 2; - printk(KERN_INFO "isdn: Rejecting Call\n"); - cmd.driver = di; - cmd.arg = c->arg; - cmd.command = ISDN_CMD_HANGUP; - isdn_command(&cmd); - if (r == 3) - break; - /* Fall through */ - case 4: - /* ... then start callback. */ - break; - case 5: - /* Number would eventually match, if longer */ - retval = 3; - break; - } - dbg_statcallb("ICALL: ret=%d\n", retval); - return retval; - break; - case ISDN_STAT_DHUP: - if (divert_if) - divert_if->stat_callback(c); - break; - case ISDN_STAT_DISCH: - save_flags(flags); - cli(); - for (i = 0; i < ISDN_MAX_CHANNELS; i++) - if ((slots[i].di == di) && - (slots[i].ch == c->arg)) { - if (c->parm.num[0]) - slots[i].usage &= ~ISDN_USAGE_DISABLED; - else if (USG_NONE(isdn_slot_usage(i))) - slots[i].usage |= ISDN_USAGE_DISABLED; - else - retval = -1; - break; - } - restore_flags(flags); - break; - case CAPI_PUT_MESSAGE: - return(isdn_capi_rec_hl_msg(&c->parm.cmsg)); - case ISDN_STAT_PROT: - case ISDN_STAT_REDIR: - if (divert_if) - return(divert_if->stat_callback(c)); -#endif - default: - rc = 1; + isdn_unlock_driver(dev->drv[i]); } - put_drv(drv); - return rc; -} - -/* ====================================================================== */ - -/* - * Register a new ISDN interface - */ -int -register_isdn(isdn_if *iif) -{ - struct isdn_driver *drv; - unsigned long flags; - int drvidx; - - drv = kmalloc(sizeof(*drv), GFP_ATOMIC); - if (!drv) { - printk(KERN_WARNING "register_isdn: out of mem\n"); - goto fail; - } - memset(drv, 0, sizeof(*drv)); - - atomic_set(&drv->refcnt, 0); - spin_lock_init(&drv->lock); - init_waitqueue_head(&drv->st_waitq); - drv->fi.fsm = &drv_fsm; - drv->fi.state = ST_DRV_NULL; - drv->fi.debug = 1; - drv->fi.userdata