summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-18 22:06:10 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-18 22:06:10 +0000
commitaba4e552a2f2c1492441acbccedd8e0a4c53f916 (patch)
tree23921efb2b4af590160f034a89ff3da2ecca6e47
parent9e17e1aa1cf1cb497d2f67147a51831888affcf3 (diff)
Merge with Linux 2.3.43.
-rw-r--r--CREDITS42
-rw-r--r--Documentation/Configure.help144
-rw-r--r--MAINTAINERS41
-rw-r--r--Makefile2
-rw-r--r--arch/alpha/lib/csum_ipv6_magic.S42
-rw-r--r--arch/i386/config.in2
-rw-r--r--arch/i386/kernel/smpboot.c11
-rw-r--r--arch/m68k/amiga/amiints.c6
-rw-r--r--arch/m68k/atari/debug.c4
-rw-r--r--arch/m68k/bvme6000/config.c1
-rw-r--r--arch/m68k/kernel/signal.c2
-rw-r--r--arch/m68k/kernel/traps.c23
-rw-r--r--arch/m68k/mac/debug.c4
-rw-r--r--arch/m68k/mvme147/config.c1
-rw-r--r--arch/m68k/mvme16x/config.c1
-rw-r--r--arch/sparc/Makefile10
-rw-r--r--arch/sparc/ap1000/Makefile20
-rw-r--r--arch/sparc/ap1000/apinline.h86
-rw-r--r--arch/sparc/ap1000/aplib.c496
-rw-r--r--arch/sparc/ap1000/apmmu.c1144
-rw-r--r--arch/sparc/ap1000/approm.c148
-rw-r--r--arch/sparc/ap1000/bnet.c1205
-rw-r--r--arch/sparc/ap1000/dma.c74
-rw-r--r--arch/sparc/ap1000/hw.c200
-rw-r--r--arch/sparc/ap1000/irq.c64
-rw-r--r--arch/sparc/ap1000/kgdb.c78
-rw-r--r--arch/sparc/ap1000/mpp.c83
-rw-r--r--arch/sparc/ap1000/msc.c1262
-rw-r--r--arch/sparc/ap1000/sync.c55
-rw-r--r--arch/sparc/ap1000/timer.c125
-rw-r--r--arch/sparc/ap1000/tnet.c708
-rw-r--r--arch/sparc/ap1000/util.c436
-rw-r--r--arch/sparc/config.in67
-rw-r--r--arch/sparc/defconfig19
-rw-r--r--arch/sparc/kernel/head.S9
-rw-r--r--arch/sparc/kernel/ioport.c2
-rw-r--r--arch/sparc/kernel/irq.c8
-rw-r--r--arch/sparc/kernel/process.c5
-rw-r--r--arch/sparc/kernel/setup.c15
-rw-r--r--arch/sparc/kernel/sparc_ksyms.c2
-rw-r--r--arch/sparc/kernel/sys_sparc.c11
-rw-r--r--arch/sparc/kernel/sys_sunos.c2
-rw-r--r--arch/sparc/kernel/systbls.S8
-rw-r--r--arch/sparc/kernel/time.c19
-rw-r--r--arch/sparc/mm/Makefile5
-rw-r--r--arch/sparc/mm/asyncd.c290
-rw-r--r--arch/sparc/mm/init.c11
-rw-r--r--arch/sparc/mm/loadmmu.c7
-rw-r--r--arch/sparc/prom/bootstr.c7
-rw-r--r--arch/sparc/prom/console.c15
-rw-r--r--arch/sparc/prom/devops.c5
-rw-r--r--arch/sparc/prom/init.c10
-rw-r--r--arch/sparc/prom/memory.c15
-rw-r--r--arch/sparc/prom/mp.c6
-rw-r--r--arch/sparc/prom/printf.c6
-rw-r--r--arch/sparc64/config.in2
-rw-r--r--arch/sparc64/defconfig9
-rw-r--r--arch/sparc64/kernel/binfmt_elf32.c2
-rw-r--r--arch/sparc64/kernel/dtlb_backend.S4
-rw-r--r--arch/sparc64/kernel/dtlb_base.S4
-rw-r--r--arch/sparc64/kernel/dtlb_prot.S4
-rw-r--r--arch/sparc64/kernel/ioctl32.c2
-rw-r--r--arch/sparc64/kernel/iommu_common.c2
-rw-r--r--arch/sparc64/kernel/itlb_base.S4
-rw-r--r--arch/sparc64/kernel/pci_iommu.c2
-rw-r--r--arch/sparc64/kernel/pci_psycho.c2
-rw-r--r--arch/sparc64/kernel/pci_sabre.c2
-rw-r--r--arch/sparc64/kernel/sbus.c2
-rw-r--r--arch/sparc64/kernel/sparc64_ksyms.c12
-rw-r--r--arch/sparc64/kernel/starfire.c4
-rw-r--r--arch/sparc64/kernel/sys_sparc.c2
-rw-r--r--arch/sparc64/kernel/sys_sunos32.c2
-rw-r--r--arch/sparc64/kernel/systbls.S6
-rw-r--r--arch/sparc64/lib/debuglocks.c4
-rw-r--r--arch/sparc64/lib/memscan.S4
-rw-r--r--arch/sparc64/mm/Makefile4
-rw-r--r--arch/sparc64/mm/asyncd.c283
-rw-r--r--arch/sparc64/solaris/misc.c2
-rw-r--r--drivers/Makefile6
-rw-r--r--drivers/ap1000/Makefile29
-rw-r--r--drivers/ap1000/am79c830.h276
-rw-r--r--drivers/ap1000/am79c864.h162
-rw-r--r--drivers/ap1000/ap.c307
-rw-r--r--drivers/ap1000/apfddi-reg.h14
-rw-r--r--drivers/ap1000/apfddi.c702
-rw-r--r--drivers/ap1000/apfddi.h142
-rw-r--r--drivers/ap1000/bif.c280
-rw-r--r--drivers/ap1000/ddv.c1008
-rw-r--r--drivers/ap1000/ddv_util.c116
-rw-r--r--drivers/ap1000/mac.c1177
-rw-r--r--drivers/ap1000/mac.h82
-rw-r--r--drivers/ap1000/plc.c393
-rw-r--r--drivers/ap1000/plc.h53
-rw-r--r--drivers/ap1000/ringbuf.c311
-rw-r--r--drivers/ap1000/smt-types.h167
-rw-r--r--drivers/block/cmd64x.c2
-rw-r--r--drivers/block/swim3.c40
-rw-r--r--drivers/block/swim_iop.c38
-rw-r--r--drivers/char/agp/agpgart_be.c81
-rw-r--r--drivers/char/agp/agpgart_fe.c3
-rw-r--r--drivers/char/generic_serial.c9
-rw-r--r--drivers/char/generic_serial.h3
-rw-r--r--drivers/char/joystick/joy-creative.c2
-rw-r--r--drivers/char/scc.h613
-rw-r--r--drivers/char/serial167.c100
-rw-r--r--drivers/char/tty_io.c21
-rw-r--r--drivers/char/vme_scc.c1136
-rw-r--r--drivers/i2c/Config.in22
-rw-r--r--drivers/i2c/i2c-core.c612
-rw-r--r--drivers/i2c/i2c-dev.c605
-rw-r--r--drivers/i2c/i2c-elektor.c213
-rw-r--r--drivers/i2c/i2c-pcf8584.h38
-rw-r--r--drivers/ieee1394/ieee1394_syms.c1
-rw-r--r--drivers/ieee1394/ieee1394_transactions.c24
-rw-r--r--drivers/ieee1394/ieee1394_transactions.h3
-rw-r--r--drivers/ieee1394/ohci1394.c462
-rw-r--r--drivers/ieee1394/ohci1394.h26
-rw-r--r--drivers/ieee1394/raw1394.c30
-rw-r--r--drivers/net/Makefile4
-rw-r--r--drivers/net/Space.c21
-rw-r--r--drivers/net/cs89x0.h8
-rw-r--r--drivers/net/daynaport.c451
-rw-r--r--drivers/net/irda/Config.in10
-rw-r--r--drivers/net/irda/Makefile12
-rw-r--r--drivers/net/irda/airport.c358
-rw-r--r--drivers/net/irda/irport.c61
-rw-r--r--drivers/net/irda/irtty.c10
-rw-r--r--drivers/net/irda/nsc-ircc.c (renamed from drivers/net/irda/nsc_fir.c)1018
-rw-r--r--drivers/net/irda/smc-ircc.c699
-rw-r--r--drivers/net/irda/toshoboe.c46
-rw-r--r--drivers/net/irda/w83977af_ir.c51
-rw-r--r--drivers/net/mac89x0.c678
-rw-r--r--drivers/net/macmace.c825
-rw-r--r--drivers/net/macsonic.c834
-rw-r--r--drivers/net/sun3lance.c21
-rw-r--r--drivers/net/sunbmac.c2
-rw-r--r--drivers/net/sunhme.c2
-rw-r--r--drivers/net/sunlance.c2
-rw-r--r--drivers/net/sunqe.c2
-rw-r--r--drivers/sbus/audio/cs4231.c2
-rw-r--r--drivers/sbus/audio/dbri.c2
-rw-r--r--drivers/sbus/char/zs.c14
-rw-r--r--drivers/scsi/esp.c2
-rw-r--r--drivers/scsi/scsi_merge.c2
-rw-r--r--drivers/scsi/sd.c55
-rw-r--r--drivers/sound/Config.in2
-rw-r--r--drivers/sound/Makefile4
-rw-r--r--drivers/sound/ac97_codec.c440
-rw-r--r--drivers/sound/ac97_codec.h157
-rw-r--r--drivers/sound/trident.c3055
-rw-r--r--drivers/sound/trident.h266
-rw-r--r--drivers/usb/Config.in1
-rw-r--r--drivers/usb/Makefile2
-rw-r--r--drivers/usb/acm.c36
-rw-r--r--drivers/usb/ov511.c2
-rw-r--r--drivers/usb/printer.c19
-rw-r--r--drivers/usb/scanner.c1
-rw-r--r--drivers/usb/uhci-debug.h399
-rw-r--r--drivers/usb/uhci.c2214
-rw-r--r--drivers/usb/uhci.h425
-rw-r--r--drivers/usb/usb-core.c3
-rw-r--r--drivers/usb/usb-serial.c8
-rw-r--r--drivers/usb/usb-uhci-debug.h195
-rw-r--r--drivers/usb/usb-uhci.c2
-rw-r--r--drivers/usb/usb.c47
-rw-r--r--drivers/usb/usb.h1
-rw-r--r--drivers/video/dn_accel.h9
-rw-r--r--drivers/video/dn_cfb4.c546
-rw-r--r--drivers/video/dn_cfb8.c594
-rw-r--r--drivers/video/dnfb.c394
-rw-r--r--fs/autofs4/inode.c8
-rw-r--r--fs/nfsd/export.c1
-rw-r--r--fs/nfsd/lockd.c2
-rw-r--r--fs/nfsd/nfsproc.c4
-rw-r--r--fs/nfsd/vfs.c55
-rw-r--r--fs/proc/base.c11
-rw-r--r--fs/qnx4/bitmap.c6
-rw-r--r--fs/qnx4/dir.c4
-rw-r--r--fs/qnx4/inode.c14
-rw-r--r--fs/select.c16
-rw-r--r--include/asm-alpha/checksum.h2
-rw-r--r--include/asm-arm/checksum.h4
-rw-r--r--include/asm-i386/checksum.h4
-rw-r--r--include/asm-m68k/checksum.h4
-rw-r--r--include/asm-m68k/entry.h36
-rw-r--r--include/asm-m68k/init.h18
-rw-r--r--include/asm-m68k/kgdb.h83
-rw-r--r--include/asm-m68k/semaphore.h35
-rw-r--r--include/asm-mips/checksum.h6
-rw-r--r--include/asm-mips64/checksum.h6
-rw-r--r--include/asm-sh/checksum.h4
-rw-r--r--include/asm-sparc/ap1000/DdvReqTable.h107
-rw-r--r--include/asm-sparc/ap1000/apbif.h205
-rw-r--r--include/asm-sparc/ap1000/aplib.h119
-rw-r--r--include/asm-sparc/ap1000/apreg.h619
-rw-r--r--include/asm-sparc/ap1000/apservice.h111
-rw-r--r--include/asm-sparc/ap1000/pgtapmmu.h141
-rw-r--r--include/asm-sparc/checksum.h6
-rw-r--r--include/asm-sparc/ethtool.h4
-rw-r--r--include/asm-sparc/page.h128
-rw-r--r--include/asm-sparc/sbus.h2
-rw-r--r--include/asm-sparc/scatterlist.h5
-rw-r--r--include/asm-sparc/siginfo.h2
-rw-r--r--include/asm-sparc/types.h4
-rw-r--r--include/asm-sparc/unistd.h4
-rw-r--r--include/asm-sparc64/checksum.h6
-rw-r--r--include/asm-sparc64/dma.h2
-rw-r--r--include/asm-sparc64/ethtool.h4
-rw-r--r--include/asm-sparc64/floppy.h2
-rw-r--r--include/asm-sparc64/io.h2
-rw-r--r--include/asm-sparc64/parport.h2
-rw-r--r--include/asm-sparc64/sbus.h2
-rw-r--r--include/asm-sparc64/types.h2
-rw-r--r--include/asm-sparc64/unistd.h4
-rw-r--r--include/linux/agp_backend.h1
-rw-r--r--include/linux/agpgart.h8
-rw-r--r--include/linux/auto_fs.h8
-rw-r--r--include/linux/i2c-dev.h127
-rw-r--r--include/linux/i2c-elektor.h10
-rw-r--r--include/linux/mmzone.h6
-rw-r--r--include/linux/nfsd/export.h3
-rw-r--r--include/linux/nfsd/nfsd.h5
-rw-r--r--include/linux/proc_fs.h3
-rw-r--r--include/linux/qnx4_fs.h7
-rw-r--r--include/linux/serial.h15
-rw-r--r--include/linux/serialP.h10
-rw-r--r--include/net/irda/ircomm_tty.h4
-rw-r--r--include/net/irda/irda.h4
-rw-r--r--include/net/irda/irda_device.h28
-rw-r--r--include/net/irda/irmod.h4
-rw-r--r--include/net/irda/irport.h8
-rw-r--r--include/net/irda/irtty.h11
-rw-r--r--include/net/irda/nsc-ircc.h (renamed from include/net/irda/nsc_fir.h)79
-rw-r--r--include/net/irda/smc-ircc.h237
-rw-r--r--include/net/irda/toshoboe.h28
-rw-r--r--include/net/irda/w83977af_ir.h12
-rw-r--r--include/net/irda/wrapper.h6
-rw-r--r--ipc/shm.c9
-rw-r--r--kernel/exit.c3
-rw-r--r--net/ax25/af_ax25.c2
-rw-r--r--net/ipv4/ipconfig.c2
-rw-r--r--net/ipv4/tcp.c8
-rw-r--r--net/ipv4/tcp_input.c60
-rw-r--r--net/ipv4/tcp_ipv4.c3
-rw-r--r--net/ipv4/tcp_output.c4
-rw-r--r--net/ipv6/ipv6_sockglue.c3
-rw-r--r--net/ipv6/tcp_ipv6.c3
-rw-r--r--net/irda/irda_device.c10
-rw-r--r--net/irda/wrapper.c30
-rw-r--r--net/netrom/af_netrom.c2
-rw-r--r--net/rose/af_rose.c2
-rw-r--r--net/sched/sch_dsmark.c4
-rw-r--r--net/sched/sch_gred.c94
253 files changed, 13875 insertions, 19545 deletions
diff --git a/CREDITS b/CREDITS
index 693d651f1..2b176177a 100644
--- a/CREDITS
+++ b/CREDITS
@@ -287,6 +287,13 @@ N: Erik Inge Bolsø
E: knan@mo.himolde.no
D: Misc kernel hacks
+N: Andreas E. Bombe
+E: andreas.bombe@munich.netsurf.de
+W: http://home.pages.de/~andreas.bombe/
+P: 1024/04880A44 72E5 7031 4414 2EB6 F6B4 4CBD 1181 7032 0488 0A44
+D: IEEE 1394 subsystem rewrite and maintainer
+D: Texas Instruments PCILynx IEEE 1394 driver
+
N: Zoltán Böszörményi
E: zboszor@mail.externet.hu
D: MTRR emulation with Cyrix style ARR registers, Athlon MTRR support
@@ -1312,6 +1319,14 @@ S: Post Office Box 371
S: North Little Rock, Arkansas 72115
S: USA
+N: Stephan Linz
+E: linz@mazet.de
+E: Stephan.Linz@gmx.de
+W: http://www.crosswinds.net/~tuxer
+D: PCILynx patch to work with 1394a PHY and without local RAM
+S: (ask for current address)
+S: Germany
+
N: Siegfried "Frieder" Loeffler (dg1sek)
E: floeff@tunix.mathematik.uni-stuttgart.de, fl@LF.net
W: http://www.mathematik.uni-stuttgart.de/~floeff
@@ -1514,13 +1529,14 @@ S: 7546 JA Enschede
S: Netherlands
N: David S. Miller
-E: davem@dm.cobaltmicro.com
+E: davem@redhat.com
D: Sparc and blue box hacker
D: Vger Linux mailing list co-maintainer
D: Linux Emacs elf/qmagic support + other libc/gcc things
D: Yee bore de yee bore! ;-)
-S: 331 Santa Rosa Drive
-S: Los Gatos, California 95032
+S: 750 N. Shoreline Blvd.
+S: Apt. #111
+S: Mountain View, California 94043
S: USA
N: Rick Miller
@@ -1708,6 +1724,13 @@ S: Demonstratsii 8-382
S: Tula 300000
S: Russia
+N: Gordon Peters
+E: GordPeters@smarttech.com
+D: Isochronous receive for IEEE 1394 driver (OHCI module).
+D: Bugfixes for the aforementioned.
+S: Calgary, Alberta
+S: Canada
+
N: Johnnie Peters
E: jpeters@phx.mcd.mot.com
D: Motorola PowerPC changes for PReP
@@ -1742,6 +1765,12 @@ S: M"ullerstr. 69
S: 13349 Berlin
S: Germany
+N: Emanuel Pirker
+E: epirker@edu.uni-klu.ac.at
+D: AIC5800 IEEE 1394, RAW I/O on 1394
+D: Starter of Linux1394 effort
+S: ask per mail for current address
+
N: Ken Pizzini
E: ken@halcyon.com
D: CDROM driver "sonycd535" (Sony CDU-535/531)
@@ -1858,6 +1887,13 @@ S: 21 Rue Carnot
S: 95170 Deuil La Barre
S: France
+N: Sebastien Rougeaux
+E: Sebastien.Rougeaux@syseng.anu.edu.au
+D: IEEE 1394 OHCI module
+S: Research School of Information Science and Engineering
+S: The Australian National University, ACT 0200
+S: Australia
+
N: Alessandro Rubini
E: rubini@ipvvis.unipv.it
D: the gpm mouse server and kernel support for it
diff --git a/Documentation/Configure.help b/Documentation/Configure.help
index 701089489..52b6a3981 100644
--- a/Documentation/Configure.help
+++ b/Documentation/Configure.help
@@ -7598,14 +7598,16 @@ CONFIG_IBMOL
Linux Token Ring Project site for the latest information at
http://www.linuxtr.net
-Generic TMS380 Token Ring ISA/PCI adapter support
+Generic TMS380 Token Ring ISA/PCI/MCA/EISA adapter support
CONFIG_TMS380TR
This driver provides generic support for token ring adapters
based on the Texas Instruments TMS380 series chipsets. This
includes the SysKonnect TR4/16(+) ISA (SK-4190), SysKonnect
TR4/16(+) PCI (SK-4590), SysKonnect TR4/16 PCI (SK-4591),
- Compaq 4/16 PCI, Thomas-Conrad TC4048 4/16 PCI, and Intel
- TokenExpress 4/16 and PRO ISA adapters.
+ Compaq 4/16 PCI, Thomas-Conrad TC4048 4/16 PCI, and several
+ Madge adapters. If selected, you will be asked to select
+ which cards to support below. If you're using modules, each
+ class of card will be supported by a seperate module.
If you have such an adapter and would like to use it, say Y or M and
read the Token-Ring mini-HOWTO, available from
@@ -7614,9 +7616,28 @@ CONFIG_TMS380TR
Also read the file linux/Documentation/networking/tms380tr.txt or check
http://www.auk.cx/tms380tr/
+Generic TMS380 PCI support
+CONFIG_TMSPCI
+ This tms380 module supports generic TMS380-based PCI cards.
+
+ These cards are known to work:
+ - Compaq 4/16 TR PCI
+ - SysKonnect TR4/16 PCI (SK-4590/SK-4591)
+ - Thomas-Conrad TC4048 PCI 4/16
+ - 3Com Token Link Velocity
+
+Madge Smart 16/4 PCI Mk2 support
+CONFIG_ABYSS
+ This tms380 module supports the Madge Smart 16/4 PCI Mk2 cards (51-02).
+
+Madge Smart 16/4 Ringode MicroChannel
+CONFIG_MADGEMC
+ This tms380 module supports the Madge Smart 16/4 MC16 and MC32
+ MicroChannel adapters
+
SMC ISA TokenRing adapter support
CONFIG_SMCTR
- This is support for the ISA SMC Token Ring cards, specifically
+ This is support for the ISA and MCA SMC Token Ring cards, specifically
SMC TokenCard Elite (8115T) and SMC TokenCard Elite/A (8115T/A) adapters.
If you have such an adapter and would like to use it, say Y or M and
@@ -8022,6 +8043,25 @@ CONFIG_USB_UHCI
The module will be called usb-uhci.o. If you want to compile it as a
module, say M here and read Documentation/modules.txt.
+UHCI (intel PIIX4, VIA, ...) alternate (JE) support?
+CONFIG_USB_UHCI_ALT
+ This is an alternate driver for UHCI support. It has been commonly
+ been referred to as the "JE driver".
+
+ The Universal Host Controller Interface is a standard by Intel for
+ accessing the USB hardware in the PC (which is also called the USB
+ host controller). If your USB host controller conforms to this
+ standard, say Y. All recent boards with Intel PCI chipsets (like
+ intel 430TX, 440FX, 440LX, 440BX, i810, i820) conform to this standard.
+ Also all VIA PCI chipsets (like VIA VP2, VP3, MVP3, Apollo Pro, Apollo
+ Pro II or Apollo Pro 133).
+ If unsure, say Y.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called uhci.o. If you want to compile it as a
+ module, say M here and read Documentation/modules.txt.
+
OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support?
CONFIG_USB_OHCI
The Open Host Controller Interface is a standard by
@@ -8829,6 +8869,30 @@ CONFIG_AUTOFS_FS
If you are not a part of a fairly large, distributed network, you
probably do not need an automounter, and can say N here.
+ If you want to use the newer version of autofs with more features,
+ say N here and select automounter v4.
+
+Kernel automounter v4 support
+CONFIG_AUTOFS4_FS
+ The automounter is a tool to automatically mount remote filesystems
+ on demand. This implementation is partially kernel-based to reduce
+ overhead in the already-mounted case; this is unlike the BSD
+ automounter (amd), which is a pure user space daemon.
+
+ To use the automounter you need the user-space tools from
+ ftp://ftp.kernel.org/pub/linux/daemons/autofs/testing-v4 ; you also
+ want to answer Y to "NFS filesystem support", below.
+
+ If you want to compile this as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+ say M here and read Documentation/modules.txt. The module will be
+ called autofs4.o. You will need to add "alias autofs autofs4" to
+ your modules configuration file.
+
+ If you are not a part of a fairly large, distributed network or don't
+ have a laptop which needs to dynamically reconfigure to the local
+ network, you probably do not need an automounter, and can say N here.
+
EFS filesystem support (read only) (EXPERIMENTAL)
CONFIG_EFS_FS
EFS is an older filesystem used for non-ISO9660 CDROMs and hard disk
@@ -10959,20 +11023,6 @@ CONFIG_SOUND_SB
You can say M here to compile this driver as a module; the module is
called sb.o.
-Generic OPL2/OPL3 FM synthesizer support
-CONFIG_SOUND_ADLIB
- Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
- Answering Y is usually a safe and recommended choice, however some
- cards may have software (TSR) FM emulation. Enabling FM support with
- these cards may cause trouble (I don't currently know of any such
- cards, however).
-
- Please read the file Documentation/sound/OPL3 if your card has an
- OPL3 chip.
-
- If unsure, say Y.
-
-
#Loopback MIDI device support
#CONFIG_SOUND_VMIDI
###
@@ -11248,8 +11298,16 @@ CONFIG_SOUND_MIDI
FM synthesizer (YM3812/OPL-3) support
CONFIG_SOUND_YM3812
- Answer Y here, unless you know you will not need the option.
+ Answer Y if your card has a FM chip made by Yamaha (OPL2/OPL3/OPL4).
+ Answering Y is usually a safe and recommended choice, however some
+ cards may have software (TSR) FM emulation. Enabling FM support with
+ these cards may cause trouble (I don't currently know of any such
+ cards, however).
+ Please read the file Documentation/sound/OPL3 if your card has an
+ OPL3 chip.
+ If unsure, say Y.
+
Sun Audio support
CONFIG_SUN_AUDIO
This is support for the sound cards on Sun workstations. The code
@@ -11417,6 +11475,20 @@ CONFIG_SOUND_SONICVIBES
differs slightly from OSS/Free, so PLEASE READ
Documentation/sound/sonicvibes.
+Trident 4DWave DX/NX or SiS 7018 PCI Audio Core
+CONFIG_SOUND_TRIDENT
+ Say Y or M if you have a PCI sound card utilizing the Trident
+ 4DWave-DX/NX chipset or your mother board chipset has SiS 7018
+ built-in. The SiS 7018 PCI Audio Core is embedded in SiS960
+ Super South Bridge and SiS540/630 Single Chipset.
+
+ Use lspci -n to find out if your sound card or chipset uses
+ Trident 4DWave or SiS 7018. PCI ID 1023:2000 or 1023:2001 stands
+ for Trident 4Dwave. PCI ID 1039:7018 stands for SiS7018.
+
+ This driver differs slightly from OSS/Free, so PLEASE READ the
+ comments at of driver/sound/trident.c
+
Rockwell WaveArtist
CONFIG_SOUND_WAVEARTIST
Say Y here to include support for the Rockwell WaveArtist sound
@@ -13295,8 +13367,7 @@ CONFIG_IRCOMM
and makes it possible to use all existing applications that
understands TTY's with an infrared link. Thus you should be able to
use application like PPP, minicom and others. Enabling this option
- will create two modules called ircomm and ircomm_tty. For more
- information go to http://www.pluto.dti.ne.jp/~thiguchi/irda/
+ will create two modules called ircomm and ircomm-tty.
IrTTY IrDA Device Driver
CONFIG_IRTTY_SIR
@@ -13346,11 +13417,10 @@ CONFIG_WINBOND_FIR
NSC PC87108 IrDA Device Driver
CONFIG_NSC_FIR
- Say Y here if you want to build support for the NSC PC87108 IrDA
- chipset. If you want to compile it as a module, say M here and
- read Documentation/modules.txt. This drivers currently only supports
- the ACTiSYS IR2000B ISA card and supports SIR, MIR and FIR (4Mbps)
- speeds.
+ Say Y here if you want to build support for the NSC PC87108 and
+ PC87338 IrDA chipsets. If you want to compile it as a module, say M
+ here and read Documentation/modules.txt. This driver supports SIR,
+ MIR and FIR (4Mbps) speeds.
Toshiba Type-O IR Port Device Driver
CONFIG_TOSHIBA_FIR
@@ -13366,7 +13436,7 @@ CONFIG_ESI_DONGLE
and read Documentation/modules.txt. The ESI dongle attaches to the
normal 9-pin serial port connector, and can currently only be used
by IrTTY. To activate support for ESI dongles you will have to
- insert "irattach -d esi" in the /etc/irda/drivers script.
+ start irattach like this: "irattach -d esi".
ACTiSYS IR-220L and IR220L+ dongle
CONFIG_ACTISYS_DONGLE
@@ -13375,8 +13445,8 @@ CONFIG_ACTISYS_DONGLE
say M here and read Documentation/modules.txt. The ACTiSYS dongles
attaches to the normal 9-pin serial port connector, and can
currently only be used by IrTTY. To activate support for ACTiSYS
- dongles you will have to insert "irattach -d actisys" or
- "irattach -d actisys_plus" in the/etc/irda/drivers script.
+ dongles you will have to start irattach like this:
+ "irattach -d actisys" or "irattach -d actisys+".
Tekram IrMate 210B dongle
CONFIG_TEKRAM_DONGLE
@@ -13385,7 +13455,7 @@ CONFIG_TEKRAM_DONGLE
and read Documentation/modules.txt. The Tekram dongle attaches to
the normal 9-pin serial port connector, and can currently only be
used by IrTTY. To activate support for Tekram dongles you will have
- to insert "irattach -d tekram" in the /etc/irda/drivers script.
+ to start irattach like this: "irattach -d tekram".
Greenwich GIrBIL dongle
CONFIG_GIRBIL_DONGLE
@@ -13403,17 +13473,7 @@ CONFIG_LITELINK_DONGLE
Documentation/modules.txt. The Parallax dongle attaches to the
normal 9-pin serial port connector, and can currently only be used
by IrTTY. To activate support for Parallax dongles you will have to
- insert "irattach -d litelink" in the /etc/irda/drivers script.
-
-Adaptec Airport 1000 and 2000 dongle
-CONFIG_AIRPORT_DONGLE
- Say Y here if you want to build support for the Adaptec Airport 1000
- and 2000 dongles. If you want to compile it as a module, say M here
- and read Documentation/modules.txt. The module will be called
- airport.o. The Airport dongle attaches to the normal 9-pin serial
- port connector, and can currently only be used by IrTTY. To activate
- support for Airport dongles you will have to insert "irattach -d
- airport" in the /etc/irda/drivers script.
+ start irattach like this "irattach -d litelink".
VME (Motorola and BVM) support
CONFIG_VME
@@ -13531,6 +13591,7 @@ CONFIG_KHTTPD
The kHTTPd is experimental. Be careful when using it on a production
machine. Also note that kHTTPd doesn't support virtual servers yet.
+#
I2C support
CONFIG_I2C
I2C (pronounce: I-square-C) is a slow bus protocol developed by
@@ -13583,7 +13644,6 @@ CONFIG_I2C_CHARDEV
files, usually found in the /dev directory on your system. They
make it possible to have user-space programs use the I2C bus.
-#
# A couple of things I keep forgetting:
# capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
# Intel, IRQ, Linux, MSDOS, NetWare, NetWinder, NFS,
diff --git a/MAINTAINERS b/MAINTAINERS
index f053d2aae..96b0c60b9 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -456,6 +456,41 @@ M: Gadi Oxman <gadio@netvision.net.il>
L: linux-kernel@vger.rutgers.edu
S: Maintained
+IEEE 1394 SUBSYSTEM
+P: Andreas Bombe
+M: andreas.bombe@munich.netsurf.de
+L: linux1394-devel@eclipt.uni-klu.ac.at
+W: http://eclipt.uni-klu.ac.at/ieee1394
+S: Maintained
+
+IEEE 1394 AIC5800 DRIVER
+P: Emanuel Pirker
+M: epirker@edu.uni-klu.ac.at
+L: linux1394-devel@eclipt.uni-klu.ac.at
+W: http://eclipt.uni-klu.ac.at/ieee1394
+S: Maintained
+
+IEEE 1394 OHCI DRIVER
+P: Sebastien Rougeaux
+M: sebastien.rougeaux@anu.edu.au
+L: linux1394-devel@eclipt.uni-klu.ac.at
+W: http://eclipt.uni-klu.ac.at/ieee1394
+S: Maintained
+
+IEEE 1394 PCILYNX DRIVER
+P: Andreas Bombe
+M: andreas.bombe@munich.netsurf.de
+L: linux1394-devel@eclipt.uni-klu.ac.at
+W: http://eclipt.uni-klu.ac.at/ieee1394
+S: Maintained
+
+IEEE 1394 RAW I/O DRIVER
+P: Andreas Bombe
+M: andreas.bombe@munich.netsurf.de
+L: linux1394-devel@eclipt.uni-klu.ac.at
+W: http://eclipt.uni-klu.ac.at/ieee1394
+S: Maintained
+
INTEL APIC/IOAPIC, LOWLEVEL X86 SMP SUPPORT
P: Ingo Molnar
M: mingo@redhat.com
@@ -936,6 +971,12 @@ L: linux-net@vger.rutgers.edu
L: linux-tr@linuxtr.net
S: Maintained
+TRIDENT 4DWAVE/SIS 7018 PCI AUDIO CORE
+P: Ollie Lho
+M: ollie@sis.com.tw
+L: linux-kernel@vger.rutgers.edu
+S: Supported
+
TMS380 TOKEN-RING NETWORK DRIVER
P: Adam Fritzler
M: mid@auk.cx
diff --git a/Makefile b/Makefile
index cb2ca29a9..bccfeb59c 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 2
PATCHLEVEL = 3
-SUBLEVEL = 41
+SUBLEVEL = 42
EXTRAVERSION =
ARCH = mips
diff --git a/arch/alpha/lib/csum_ipv6_magic.S b/arch/alpha/lib/csum_ipv6_magic.S
index d9ddb6e74..495375a1a 100644
--- a/arch/alpha/lib/csum_ipv6_magic.S
+++ b/arch/alpha/lib/csum_ipv6_magic.S
@@ -4,7 +4,7 @@
*
* unsigned short csum_ipv6_magic(struct in6_addr *saddr,
* struct in6_addr *daddr,
- * __u16 len,
+ * __u32 len,
* unsigned short proto,
* unsigned int csum);
*/
@@ -18,54 +18,74 @@ csum_ipv6_magic:
ldq $0,0($16) # e0 : load src & dst addr words
zapnot $20,15,$20 # .. e1 : zero extend incoming csum
- extwh $18,7,$4 # e0 : byte swap len & proto while we wait
+ extqh $18,7,$4 # e0 : byte swap len & proto while we wait
ldq $1,8($16) # .. e1 :
- extbl $18,1,$18 # e0 :
+
+ extbl $18,1,$5 # e0 :
ldq $2,0($17) # .. e1 :
- extwh $19,7,$5 # e0 :
+ extbl $18,2,$6 # e0 :
ldq $3,8($17) # .. e1 :
- extbl $19,1,$19 # e0 :
- or $18,$4,$18 # .. e1 :
- addq $20,$0,$20 # e0 : begin summing the words
- or $19,$5,$19 # .. e1 :
- sll $18,48,$18 # e0 :
+
+ extbl $18,3,$18 # e0 :
+ sra $4,32,$4 # e0 :
+ sll $5,16,$5 # e0 :
+ addq $20,$0,$20 # .. e1 : begin summing the words
+
+ sll $6,8,$6 # e0 :
cmpult $20,$0,$0 # .. e1 :
+ extwh $19,7,$7 # e0 :
+ or $4,$18,$18 # .. e1 :
+
+ extbl $19,1,$19 # e0 :
+ or $5,$6,$5 # .. e1 :
+ or $18,$5,$18 # e0 : len complete
+ or $19,$7,$19 # .. e1 :
+
sll $19,48,$19 # e0 :
addq $20,$1,$20 # .. e1 :
- sra $18,32,$18 # e0 : len complete
- cmpult $20,$1,$1 # .. e1 :
sra $19,32,$19 # e0 : proto complete
+ cmpult $20,$1,$1 # .. e1 :
+
+ nop # e0 :
addq $20,$2,$20 # .. e1 :
cmpult $20,$2,$2 # e0 :
addq $20,$3,$20 # .. e1 :
+
cmpult $20,$3,$3 # e0 :
addq $20,$18,$20 # .. e1 :
cmpult $20,$18,$18 # e0 :
addq $20,$19,$20 # .. e1 :
+
cmpult $20,$19,$19 # e0 :
addq $0,$1,$0 # .. e1 : merge the carries back into the csum
addq $2,$3,$2 # e0 :
addq $18,$19,$18 # .. e1 :
+
addq $0,$2,$0 # e0 :
addq $20,$18,$20 # .. e1 :
addq $0,$20,$0 # e0 :
unop # :
+
extwl $0,2,$2 # e0 : begin folding the 64-bit value
zapnot $0,3,$3 # .. e1 :
extwl $0,4,$1 # e0 :
addq $2,$3,$3 # .. e1 :
+
extwl $0,6,$0 # e0 :
addq $3,$1,$3 # .. e1 :
addq $0,$3,$0 # e0 :
unop # :
+
extwl $0,2,$1 # e0 : fold 18-bit value
zapnot $0,3,$0 # .. e1 :
addq $0,$1,$0 # e0 :
unop # :
+
extwl $0,2,$1 # e0 : fold 17-bit value
zapnot $0,3,$0 # .. e1 :
addq $0,$1,$0 # e0 :
not $0,$0 # e1 : and compliment.
+
zapnot $0,3,$0 # e0 :
ret # .. e1 :
diff --git a/arch/i386/config.in b/arch/i386/config.in
index 0dda4d49f..2377c24b7 100644
--- a/arch/i386/config.in
+++ b/arch/i386/config.in
@@ -22,7 +22,7 @@ choice 'Processor family' \
586/K5/5x86/6x86 CONFIG_M586 \
Pentium/TSC CONFIG_M586TSC \
PPro/6x86MX CONFIG_M686 \
- K6/II/II CONFIG_MK6 \
+ K6/II/III CONFIG_MK6 \
Athlon CONFIG_MK7" PPro
#
# Define implied options from the CPU selection here
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 3ff5cc002..50b743a99 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -710,7 +710,8 @@ extern unsigned long cpu_hz;
static void smp_tune_scheduling (void)
{
- unsigned long cachesize;
+ unsigned long cachesize; /* kB */
+ unsigned long bandwidth = 350; /* MB/s */
/*
* Rough estimation for SMP scheduling, this is the number of
* cycles it takes for a fully memory-limited process to flush
@@ -731,10 +732,12 @@ static void smp_tune_scheduling (void)
return;
} else {
cachesize = boot_cpu_data.x86_cache_size;
- if (cachesize == -1)
- cachesize = 8; /* Pentiums */
+ if (cachesize == -1) {
+ cachesize = 16; /* Pentiums, 2x8kB cache */
+ bandwidth = 100;
+ }
- cacheflush_time = cpu_hz/1024*cachesize/5000;
+ cacheflush_time = (cpu_hz>>20) * (cachesize<<10) / bandwidth;
}
printk("per-CPU timeslice cutoff: %ld.%02ld usecs.\n",
diff --git a/arch/m68k/amiga/amiints.c b/arch/m68k/amiga/amiints.c
index 209813dfb..099119178 100644
--- a/arch/m68k/amiga/amiints.c
+++ b/arch/m68k/amiga/amiints.c
@@ -364,7 +364,7 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server)
intena = ami_intena_vals[irq];
custom.intreq = intena;
- /* serve first fast handlers - there can only be one of these */
+ /* serve fast handler if present - there can only be one of these */
node = ami_irq_list[irq];
/*
@@ -392,7 +392,11 @@ void amiga_do_irq_list(int irq, struct pt_regs *fp, struct irq_server *server)
*/
custom.intena = intena;
save_flags(flags);
+#if 0 /* def CPU_M68060_ONLY */
sti();
+#else
+ restore_flags((flags & ~0x0700) | (fp->sr & 0x0700));
+#endif
slow_nodes = node;
for (;;) {
diff --git a/arch/m68k/atari/debug.c b/arch/m68k/atari/debug.c
index e14c97e42..e30cb4e55 100644
--- a/arch/m68k/atari/debug.c
+++ b/arch/m68k/atari/debug.c
@@ -311,10 +311,6 @@ void atari_init_midi_port( int cflag )
void __init atari_debug_init(void)
{
-#ifdef CONFIG_KGDB
- /* the m68k_debug_device is used by the GDB stub, do nothing here */
- return;
-#endif
if (!strcmp( m68k_debug_device, "ser" )) {
/* defaults to ser2 for a Falcon and ser1 otherwise */
strcpy( m68k_debug_device, MACH_IS_FALCON ? "ser2" : "ser1" );
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index bbe808d3f..b1b245ec2 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -132,6 +132,7 @@ void __init config_bvme6000(void)
bvme6000_set_vectors();
#endif
+ mach_max_dma_address = 0xffffffff;
mach_sched_init = bvme6000_sched_init;
mach_keyb_init = bvme6000_keyb_init;
mach_kbdrate = bvme6000_kbdrate;
diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c
index 555b39612..d795c71ad 100644
--- a/arch/m68k/kernel/signal.c
+++ b/arch/m68k/kernel/signal.c
@@ -37,6 +37,7 @@
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/stddef.h>
+#include <linux/highuid.h>
#include <asm/setup.h>
#include <asm/uaccess.h>
@@ -1048,6 +1049,7 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs)
info.si_code = SI_USER;
info.si_pid = current->p_pptr->pid;
info.si_uid = current->p_pptr->uid;
+ info.si_uid16 = high2lowuid(current->p_pptr->uid);
}
/* If the (new) signal is now blocked, requeue it. */
diff --git a/arch/m68k/kernel/traps.c b/arch/m68k/kernel/traps.c
index db298c997..5fd9dc0a7 100644
--- a/arch/m68k/kernel/traps.c
+++ b/arch/m68k/kernel/traps.c
@@ -37,9 +37,6 @@
#include <asm/pgtable.h>
#include <asm/machdep.h>
#include <asm/siginfo.h>
-#ifdef CONFIG_KGDB
-#include <asm/kgdb.h>
-#endif
/* assembler routines */
asmlinkage void system_call(void);
@@ -766,11 +763,6 @@ int kstack_depth_to_print = 48;
static void dump_stack(struct frame *fp)
{
-#ifdef CONFIG_KGDB
- /* This will never return to here, if kgdb has been initialized. And if
- * it returns from there, then to where the error happened... */
- enter_kgdb( &fp->ptregs );
-#else
unsigned long *stack, *endstack, addr, module_start, module_end;
extern char _start, _etext;
int i;
@@ -868,15 +860,10 @@ static void dump_stack(struct frame *fp)
for (i = 0; i < 10; i++)
printk("%04x ", 0xffff & ((short *) fp->ptregs.pc)[i]);
printk ("\n");
-#endif
}
void bad_super_trap (struct frame *fp)
{
-#ifdef CONFIG_KGDB
- /* Save the register dump if we'll enter kgdb anyways */
- if (!kgdb_initialized) {
-#endif
console_verbose();
if (fp->ptregs.vector < 4*sizeof(vec_names)/sizeof(vec_names[0]))
printk ("*** %s *** FORMAT=%X\n",
@@ -906,9 +893,6 @@ void bad_super_trap (struct frame *fp)
fp->ptregs.pc);
}
printk ("Current process id is %d\n", current->pid);
-#ifdef CONFIG_KGDB
- }
-#endif
die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
}
@@ -1037,10 +1021,6 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr)
if (!(fp->sr & PS_S))
return;
-#ifdef CONFIG_KGDB
- /* Save the register dump if we'll enter kgdb anyways */
- if (!kgdb_initialized) {
-#endif
console_verbose();
printk("%s: %08x\n",str,nr);
printk("PC: [<%08lx>]\nSR: %04x SP: %p a2: %08lx\n",
@@ -1052,9 +1032,6 @@ void die_if_kernel (char *str, struct pt_regs *fp, int nr)
printk("Process %s (pid: %d, stackpage=%08lx)\n",
current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
-#ifdef CONFIG_KGDB
- }
-#endif
dump_stack((struct frame *)fp);
do_exit(SIGSEGV);
}
diff --git a/arch/m68k/mac/debug.c b/arch/m68k/mac/debug.c
index 98cb2a695..fa3910b5e 100644
--- a/arch/m68k/mac/debug.c
+++ b/arch/m68k/mac/debug.c
@@ -397,10 +397,6 @@ void mac_init_sccb_port( int cflag )
void __init mac_debug_init(void)
{
-#ifdef CONFIG_KGDB
- /* the m68k_debug_device is used by the GDB stub, do nothing here */
- return;
-#endif
#ifdef DEBUG_SERIAL
if ( !strcmp( m68k_debug_device, "ser" )
|| !strcmp( m68k_debug_device, "ser1" )) {
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index c27a18279..d48a0201b 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -101,6 +101,7 @@ static int mvme147_get_hardware_list(char *buffer)
void __init config_mvme147(void)
{
+ mach_max_dma_address = 0x01000000;
mach_sched_init = mvme147_sched_init;
mach_keyb_init = mvme147_keyb_init;
mach_kbdrate = mvme147_kbdrate;
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index 3c93562f9..83a0d5297 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -145,6 +145,7 @@ void __init config_mvme16x(void)
p_bdid p = &mvme_bdid;
char id[40];
+ mach_max_dma_address = 0xffffffff;
mach_sched_init = mvme16x_sched_init;
mach_keyb_init = mvme16x_keyb_init;
mach_kbdrate = mvme16x_kbdrate;
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index cb7ab8775..dec2105d8 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.44 1999/08/19 06:22:20 jj Exp $
+# $Id: Makefile,v 1.45 2000/01/29 01:08:48 anton Exp $
# sparc/Makefile
#
# Makefile for the architecture dependent flags and dependencies on the
@@ -44,14 +44,6 @@ CORE_FILES := arch/sparc/kernel/kernel.o arch/sparc/mm/mm.o $(CORE_FILES) \
LIBS := $(TOPDIR)/lib/lib.a $(LIBS) $(TOPDIR)/arch/sparc/prom/promlib.a \
$(TOPDIR)/arch/sparc/lib/lib.a
-ifdef CONFIG_AP1000
-SUBDIRS := $(SUBDIRS) arch/sparc/ap1000 mpp
-CORE_FILES := $(TOPDIR)/arch/sparc/ap1000/ap1000lib.o \
- $(TOPDIR)/mpp/mpplib.o $(CORE_FILES)
-DRIVERS := $(DRIVERS) drivers/ap1000/ap1000.a
-CFLAGS := $(CFLAGS) -D__MPP__=1
-endif
-
# This one has to come last
SUBDIRS += arch/sparc/boot
CORE_FILES_NO_BTFIX := $(CORE_FILES)
diff --git a/arch/sparc/ap1000/Makefile b/arch/sparc/ap1000/Makefile
deleted file mode 100644
index f070f7675..000000000
--- a/arch/sparc/ap1000/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-# Makefile for the AP1000 files in the Linux kernel
-#
-# Note! Dependencies are done automagically by 'make dep', which also
-# removes any old dependencies. DON'T put your own dependencies here
-# unless it's something special (ie not a .c file).
-#
-
-.S.s:
- $(CPP) -D__ASSEMBLY__ $(AFLAGS) -ansi $< -o $*.s
-.S.o:
- $(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o
-
-all: ap1000lib.o
-
-O_TARGET := ap1000lib.o
-O_OBJS := bnet.o timer.o util.o dma.o kgdb.o irq.o \
- msc.o hw.o tnet.o sync.o mpp.o \
- apmmu.o aplib.o approm.o
-
-include $(TOPDIR)/Rules.make
diff --git a/arch/sparc/ap1000/apinline.h b/arch/sparc/ap1000/apinline.h
deleted file mode 100644
index d8170b59e..000000000
--- a/arch/sparc/ap1000/apinline.h
+++ /dev/null
@@ -1,86 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/* inline utilities to support the AP1000 code */
-
-#if 0
-/* MMU bypass access */
-
-static inline unsigned long phys_9_in(unsigned long paddr)
-{
- unsigned long word;
-
- __asm__ __volatile__("lda [%1] %2, %0\n\t" :
- "=r" (word) :
- "r" (paddr), "i" (0x29) :
- "memory");
- return word;
-}
-
-static inline void phys_9_out(unsigned long paddr, unsigned long word)
-{
- __asm__ __volatile__("sta %0, [%1] %2\n\t" : :
- "r" (word), "r" (paddr), "i" (0x29) :
- "memory");
-}
-
-static inline unsigned long phys_b_in(unsigned long paddr)
-{
- unsigned long word;
-
- __asm__ __volatile__("lda [%1] %2, %0\n\t" :
- "=r" (word) :
- "r" (paddr), "i" (0x2b) :
- "memory");
- return word;
-}
-
-static inline void phys_b_out(unsigned long paddr, unsigned long word)
-{
- __asm__ __volatile__("sta %0, [%1] %2\n\t" : :
- "r" (word), "r" (paddr), "i" (0x2b) :
- "memory");
-}
-
-static inline unsigned long phys_c_in(unsigned long paddr)
-{
- unsigned long word;
-
- __asm__ __volatile__("lda [%1] %2, %0\n\t" :
- "=r" (word) :
- "r" (paddr), "i" (0x2b) :
- "memory");
- return word;
-}
-
-static inline void phys_c_out(unsigned long paddr, unsigned long word)
-{
- __asm__ __volatile__("sta %0, [%1] %2\n\t" : :
- "r" (word), "r" (paddr), "i" (0x2b) :
- "memory");
-}
-
-#undef BIF_IN
-#undef BIF_OUT
-#undef DMA_IN
-#undef DMA_OUT
-#undef MSC_IN
-#undef MSC_OUT
-#undef MC_IN
-#undef MC_OUT
-
-#define BIF_IN(reg) phys_9_in(reg)
-#define BIF_OUT(reg,v) phys_9_out(reg,v)
-#define DMA_IN(reg) phys_9_in(reg)
-#define DMA_OUT(reg,v) phys_9_out(reg,v)
-#define MC_IN(reg) phys_b_in((reg) - MC_BASE0)
-#define MC_OUT(reg,v) phys_b_out((reg) - MC_BASE0,v)
-#define MSC_IN(reg) phys_c_in((reg) - MSC_BASE0)
-#define MSC_OUT(reg,v) phys_c_out((reg) - MSC_BASE0,v)
-#endif
-
-
diff --git a/arch/sparc/ap1000/aplib.c b/arch/sparc/ap1000/aplib.c
deleted file mode 100644
index 4e476aba3..000000000
--- a/arch/sparc/ap1000/aplib.c
+++ /dev/null
@@ -1,496 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-
-/* kernel based aplib.
-
- This was initially implemented in user space, but we eventually
- relented when we discovered some really nasty MSC hardware bugs and
- decided to disallow access to the device registers by users. Pity :-(
-
- Andrew Tridgell, November 1996
-*/
-
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/malloc.h>
-#include <linux/mm.h>
-
-#include <asm/page.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
-
- #include <asm/ap1000/pgtapmmu.h>
-#include <asm/ap1000/apreg.h>
-#include <asm/ap1000/apservice.h>
-#include <asm/ap1000/aplib.h>
-
-
-extern int *tnet_rel_cid_table;
-extern unsigned _cid, _ncel, _ncelx, _ncely, _cidx, _cidy;
-
-
-/* this is used to stop the task hogging the MSC while paging in data */
-static inline void page_in(char *addr,long size)
-{
- unsigned sum = 0;
- while (size > 0) {
- sum += *(volatile char *)addr;
- addr += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
-}
-
-
-/* this sets up the aplib structures using info passed in from user space
- it should only be called once, and should be the first aplib call
- it should be followed by APLIB_SYNC
- */
-static inline int aplib_init(struct aplib_init *init)
-{
- struct aplib_struct *aplib;
- int error,i;
- int old_uid;
-
- error = verify_area(VERIFY_READ,init,sizeof(*init));
- if (error) return error;
- error = verify_area(VERIFY_READ,init->phys_cells,
- sizeof(int)*init->numcells);
- if (error) return error;
- error = verify_area(VERIFY_WRITE,
- init->ringbuffer,
- init->ringbuf_size * sizeof(int));
- if (error) return error;
- error = verify_area(VERIFY_WRITE,
- (char *)APLIB_PAGE_BASE,
- APLIB_PAGE_LEN);
- if (error) return error;
-
- if (!MPP_IS_PAR_TASK(current->taskid))
- return -EINVAL;
-
- if (current->aplib)
- return -EINVAL;
-
- aplib = current->aplib = (struct aplib_struct *)APLIB_PAGE_BASE;
-
- /* lock the aplib structure in memory */
- old_uid = current->euid;
- current->euid = 0;
- memset(aplib,0,APLIB_PAGE_LEN);
- error = sys_mlock(aplib,APLIB_PAGE_LEN);
- current->euid = old_uid;
- if (error) {
- printk("mlock1 failed\n");
- return error;
- }
-
- /* lock the ringbuffer in memory */
- old_uid = current->euid;
- current->euid = 0;
- memset(init->ringbuffer,0,init->ringbuf_size*4);
- error = sys_mlock(init->ringbuffer,init->ringbuf_size*4);
- current->euid = old_uid;
- if (error) {
- printk("mlock2 failed\n");
- return error;
- }
-
- aplib->ringbuf = init->ringbuffer;
- aplib->ringbuf_size = init->ringbuf_size;
- aplib->numcells = init->numcells;
- aplib->cid = init->cid;
- aplib->tid = current->taskid;
- aplib->numcells_x = init->numcells_x;
- aplib->numcells_y = init->numcells_y;
- aplib->cidx = init->cid % init->numcells_x;
- aplib->cidy = init->cid / init->numcells_x;
-
- aplib->physical_cid = (unsigned *)(aplib+1);
- aplib->rel_cid = aplib->physical_cid + init->numcells;
-
- if ((char *)(aplib->rel_cid + init->numcells) >
- (char *)(APLIB_PAGE_BASE + APLIB_PAGE_LEN)) {
- return -ENOMEM;
- }
-
- memcpy(aplib->physical_cid,init->phys_cells,
- sizeof(int)*init->numcells);
-
- /* initialise the relative cid table */
- for (i=0;i<aplib->numcells;i++)
- aplib->rel_cid[i] =
- tnet_rel_cid_table[aplib->physical_cid[i]];
-
- return 0;
-}
-
-
-/* n == which sync line (ignored)
- returns logical or of the stat values across the cells (1 bit resolution)
-
- This has to be done very carefully as the tasks can startup on the cells
- in any order, so we don't know which tasks have started up when this
- is called
-*/
-static inline int aplib_sync(int n,int stat)
-{
- struct aplib_struct *aplib = current->aplib;
- static int sync_flags[MPP_NUM_TASKS];
- int i,err;
- int tsk = current->taskid;
-
- stat &= 1;
-
- if (aplib->numcells < 2)
- return stat;
-
- tsk -= MPP_TASK_BASE;
-
- if (aplib->cid == 0) {
- if ((err=wait_on_int(&sync_flags[tsk],
- aplib->numcells-1,5)))
- return err;
- sync_flags[tsk] = 0;
- if (aplib->numcells == _ncel) {
- ap_bput(0,0,0,(u_long)&sync_flags[tsk],0);
- } else {
- for (i=1;i<aplib->numcells;i++)
- ap_put(aplib->physical_cid[i],
- 0,0,0,(u_long)&sync_flags[tsk],0);
- }
- } else {
- ap_put(aplib->physical_cid[0],
- 0,0,0,(u_long)&sync_flags[tsk],0);
- if ((err=wait_on_int(&sync_flags[tsk],1,5)))
- return err;
- sync_flags[tsk] = 0;
- }
-
- /* I haven't written the xy_ calls yet ... */
- /* aplib_xy_ior(stat,&stat); */
-
- return stat;
-}
-
-
-
-static inline void _putget(unsigned q,
- unsigned rcell,
- unsigned *src_addr,
- unsigned size,unsigned *dest_addr,
- unsigned *dest_flag,unsigned *src_flag)
-{
- unsigned flags;
- volatile unsigned *entry = (volatile unsigned *)q;
-
- save_flags(flags); cli();
-
- *entry = rcell;
- *entry = size;
- *entry = (unsigned)dest_addr;
- *entry = 0;
- *entry = (unsigned)dest_flag;
- *entry = (unsigned)src_flag;
- *entry = (unsigned)src_addr;
- *entry = 0;
-
- restore_flags(flags);
-}
-
-
-/* a basic put() operation. Note the avoidance of odd word boundaries
- and transfers sizes beyond what the hardware can deal with */
-static inline int aplib_put(struct aplib_putget *put)
-{
- int error;
- struct aplib_struct *aplib = current->aplib;
-
- error = verify_area(VERIFY_WRITE,put,sizeof(*put));
- if (error) return error;
-
- if (put->cid >= aplib->numcells)
- return -EINVAL;
-
- do {
- int n;
-
- if (put->size && (((unsigned)put->src_addr) & 4)) {
- n = 1;
- } else if (put->size > MAX_PUT_SIZE) {
- n = MAX_PUT_SIZE;
- } else {
- n = put->size;
- }
-
- put->size -= n;
-
- page_in((char *)put->src_addr,n<<2);
-
- _putget(MSC_PUT_QUEUE,
- aplib->rel_cid[put->cid],
- put->src_addr,
- n,
- put->dest_addr,
- put->size?0:put->dest_flag,
- put->size?0:put->src_flag);
-
- put->dest_addr += n;
- put->src_addr += n;
- } while (put->size);
-
- if (put->ack) {
- aplib->ack_request++;
- _putget(MSC_GET_QUEUE,
- aplib->rel_cid[put->cid],
- 0, 0, 0,
- &aplib->ack_flag, 0);
- }
-
- return 0;
-}
-
-
-/* a basic get() operation */
-static inline int aplib_get(struct aplib_putget *get)
-{
- struct aplib_struct *aplib = current->aplib;
- int error = verify_area(VERIFY_WRITE,get,sizeof(*get));
- if (error) return error;
-
- if (get->cid >= aplib->numcells)
- return -EINVAL;
-
- do {
- int n;
-
- if (get->size && (((unsigned)get->src_addr) & 4)) {
- n = 1;
- } else if (get->size > MAX_PUT_SIZE) {
- n = MAX_PUT_SIZE;
- } else {
- n = get->size;
- }
-
- get->size -= n;
-
- page_in((char *)get->dest_addr,n<<2);
-
- _putget(MSC_GET_QUEUE,
- aplib->rel_cid[get->cid],
- get->src_addr,
- n,
- get->dest_addr,
- get->size?0:get->dest_flag,
- get->size?0:get->src_flag);
-
- get->dest_addr += n;
- get->src_addr += n;
- } while (get->size);
-
- return 0;
-}
-
-
-/* we have received a protocol message - now do the get
- This function is called from interrupt level with interrupts
- disabled
-
- note that send->size is now in words
-*/
-void aplib_bigrecv(unsigned *msgp)
-{
- struct aplib_struct *aplib;
- struct aplib_send *send = (struct aplib_send *)(msgp+2);
- unsigned tid = (msgp[1]&0x3FF);
- unsigned cid = (msgp[0]>>22)&0x1FF;
- unsigned octx, ctx;
- struct task_struct *tsk;
- unsigned room;
-
- tsk = task[tid];
- if (!tsk || !tsk->aplib)
- return;
-
- octx = apmmu_get_context();
- ctx = MPP_TASK_TO_CTX(tid);
- if (octx != ctx)
- apmmu_set_context(ctx);
- aplib = tsk->aplib;
-
- if (aplib->write_pointer < aplib->read_pointer)
- room = aplib->read_pointer - (aplib->write_pointer+1);
- else
- room = aplib->ringbuf_size -
- ((aplib->write_pointer+1)-aplib->read_pointer);
-
- if (room < (send->size+2)) {
- send_sig(SIGLOST,tsk,1);
- goto finished;
- }
-
- aplib->ringbuf[aplib->write_pointer++] = send->info1;
- aplib->ringbuf[aplib->write_pointer++] = send->info2;
-
- /* now finally do the get() */
- _putget(MSC_GET_QUEUE,
- aplib->rel_cid[cid],
- send->src_addr,
- send->size,
- &aplib->ringbuf[aplib->write_pointer],
- &aplib->rbuf_flag2,
- send->flag_addr);
-
- aplib->write_pointer += send->size;
- if (aplib->write_pointer >= aplib->ringbuf_size)
- aplib->write_pointer -= aplib->ringbuf_size;
-
-finished:
- if (octx != ctx)
- apmmu_set_context(octx);
-}
-
-
-/* note the 8 byte alignment fix for the MSC bug */
-static inline int aplib_send(struct aplib_send *send)
-{
- struct aplib_struct *aplib = current->aplib;
- int wordSize;
- int byteAlign, byteFix;
- u_long src;
- u_long info1, info2;
- volatile unsigned *q = (volatile unsigned *)MSC_SEND_QUEUE_S;
- extern long system_recv_flag;
- int error;
- unsigned flags, rcell;
- unsigned flag_ptr;
-
- error = verify_area(VERIFY_WRITE,send,sizeof(*send));
- if (error) return error;
-
- if (send->cid >= aplib->numcells)
- return -EINVAL;
-
- if (send->tag == RBUF_SYSTEM || send->tag == RBUF_BIGSEND)
- return -EINVAL;
-
- error = verify_area(VERIFY_READ,(char *)send->src_addr,send->size);
- if (error) return error;
-
- page_in((char *)send->src_addr,send->size);
-
- rcell = aplib->rel_cid[send->cid];
-
- byteAlign = send->src_addr & 0x3;
- byteFix = send->size & 0x3;
-
- wordSize = (send->size + byteAlign + 3) >> 2;
-
- src = send->src_addr & ~3;
-
- /* this handles the MSC alignment bug */
- if (wordSize > 1 &&
- (src & 4)) {
- info1 |= 0x80000000;
- src -= 4;
- wordSize++;
- }
-
- info1 = (aplib->cid<<22) | (byteFix<<20) | wordSize;
- info2 = (send->tag<<28) | (byteAlign<<26) |
- (send->type<<10) | aplib->tid;
- flag_ptr = (unsigned)&send->flag;
-
- if (send->size > SMALL_SEND_THRESHOLD) {
- send->info1 = info1;
- send->info2 = info2;
- send->size = wordSize;
- send->src_addr = src;
- send->flag_addr = (unsigned)&send->flag;
- flag_ptr = 0;
-
- wordSize = sizeof(*send)>>2;
- src = (unsigned)send;
-
- info1 = (aplib->cid<<22) | wordSize;
- info2 = (RBUF_BIGSEND<<28) | aplib->tid;
- }
-
- save_flags(flags); cli();
-
- *q = rcell;
- *q = wordSize;
- *q = (u_long)&system_recv_flag;
- *q = flag_ptr;
- *q = (u_long)src;
- *q = 0;
- *q = info1;
- *q = info2;
-
- restore_flags(flags);
-
- return 0;
-}
-
-
-static inline int aplib_probe(void)
-{
- tnet_check_completion();
- return 0;
-}
-
-static inline int aplib_poll(unsigned counter)
-{
- struct aplib_struct *aplib = current->aplib;
-
- while (counter == aplib->rbuf_flag1 + aplib->rbuf_flag2) {
- tnet_check_completion();
- if (current->need_resched)
- break;
- if (signal_pending(current)) break;
- }
- return 0;
-}
-
-int sys_aplib(unsigned call,int a1,int a2,int a3,int a4)
-{
-
- if (!current->aplib && call != APLIB_INIT)
- return -EINVAL;
-
- switch (call) {
- case APLIB_INIT:
- return aplib_init((struct aplib_init *)a1);
-
- case APLIB_SYNC:
- return aplib_sync(a1,a2);
-
- case APLIB_PUT:
- return aplib_put((struct aplib_putget *)a1);
-
- case APLIB_GET:
- return aplib_get((struct aplib_putget *)a1);
-
- case APLIB_SEND:
- return aplib_send((struct aplib_send *)a1);
-
- case APLIB_PROBE:
- return aplib_probe();
-
- case APLIB_POLL:
- return aplib_poll((unsigned)a1);
- }
-
- return -EINVAL;
-}
-
-
diff --git a/arch/sparc/ap1000/apmmu.c b/arch/sparc/ap1000/apmmu.c
deleted file mode 100644
index 425f23b8c..000000000
--- a/arch/sparc/ap1000/apmmu.c
+++ /dev/null
@@ -1,1144 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * apmmu.c: mmu routines for the AP1000
- *
- * based on srmmu.c
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/malloc.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/io.h>
-#include <asm/kdebug.h>
-#include <asm/vaddrs.h>
-#include <asm/traps.h>
-#include <asm/smp.h>
-#include <asm/mbus.h>
-#include <asm/cache.h>
-#include <asm/oplib.h>
-#include <asm/sbus.h>
-#include <asm/iommu.h>
-#include <asm/asi.h>
-#include <asm/msi.h>
-#include <asm/a.out.h>
-#include <asm/ap1000/pgtapmmu.h>
-#include <asm/viking.h>
-
-
-extern void mc_tlb_flush_all(void);
-
-static void poke_viking(void);
-static void viking_flush_tlb_page_for_cbit)(unsigned long page);
-
-static struct apmmu_stats {
- int invall;
- int invpg;
- int invrnge;
- int invmm;
-} module_stats;
-
-static char *apmmu_name;
-
-static ctxd_t *apmmu_ctx_table_phys;
-static ctxd_t *apmmu_context_table;
-
-static unsigned long ap_mem_size;
-static unsigned long mempool;
-
-
-static inline unsigned long apmmu_v2p(unsigned long vaddr)
-{
- if (KERNBASE <= vaddr &&
- (KERNBASE + ap_mem_size > vaddr)) {
- return (vaddr - KERNBASE);
- }
- return 0xffffffffUL;
-}
-
-static inline unsigned long apmmu_p2v(unsigned long paddr)
-{
- if (ap_mem_size > paddr)
- return (paddr + KERNBASE);
- return 0xffffffffUL;
-}
-
-/* In general all page table modifications should use the V8 atomic
- * swap instruction. This insures the mmu and the cpu are in sync
- * with respect to ref/mod bits in the page tables.
- */
-static inline unsigned long apmmu_swap(unsigned long *addr, unsigned long value)
-{
- /* the AP1000 has its memory on bus 8, not 0 like suns do */
- if ((value&0xF0000000) == 0)
- value |= MEM_BUS_SPACE<<28;
- __asm__ __volatile__("swap [%2], %0\n\t" :
- "=&r" (value) :
- "0" (value), "r" (addr));
- return value;
-}
-
-/* Functions really use this, not apmmu_swap directly. */
-#define apmmu_set_entry(ptr, newentry) \
- apmmu_swap((unsigned long *) (ptr), (newentry))
-
-
-/* The very generic APMMU page table operations. */
-static unsigned int apmmu_pmd_align(unsigned int addr) { return APMMU_PMD_ALIGN(addr); }
-static unsigned int apmmu_pgdir_align(unsigned int addr) { return APMMU_PGDIR_ALIGN(addr); }
-
-static inline int apmmu_device_memory(unsigned long x)
-{
- return ((x & 0xF0000000) != 0);
-}
-
-static unsigned long apmmu_pgd_page(pgd_t pgd)
-{ return apmmu_device_memory(pgd_val(pgd))?~0:apmmu_p2v((pgd_val(pgd) & APMMU_PTD_PMASK) << 4); }
-
-static unsigned long apmmu_pmd_page(pmd_t pmd)
-{ return apmmu_device_memory(pmd_val(pmd))?~0:apmmu_p2v((pmd_val(pmd) & APMMU_PTD_PMASK) << 4); }
-
-static unsigned long apmmu_pte_page(pte_t pte)
-{ return apmmu_device_memory(pte_val(pte))?~0:apmmu_p2v((pte_val(pte) & APMMU_PTE_PMASK) << 4); }
-
-static int apmmu_pte_none(pte_t pte)
-{ return !(pte_val(pte) & 0xFFFFFFF); }
-
-static int apmmu_pte_present(pte_t pte)
-{ return ((pte_val(pte) & APMMU_ET_MASK) == APMMU_ET_PTE); }
-
-static void apmmu_pte_clear(pte_t *ptep) { set_pte(ptep, __pte(0)); }
-
-static int apmmu_pmd_none(pmd_t pmd)
-{ return !(pmd_val(pmd) & 0xFFFFFFF); }
-
-static int apmmu_pmd_bad(pmd_t pmd)
-{ return (pmd_val(pmd) & APMMU_ET_MASK) != APMMU_ET_PTD; }
-
-static int apmmu_pmd_present(pmd_t pmd)
-{ return ((pmd_val(pmd) & APMMU_ET_MASK) == APMMU_ET_PTD); }
-
-static void apmmu_pmd_clear(pmd_t *pmdp) { set_pte((pte_t *)pmdp, __pte(0)); }
-
-static int apmmu_pgd_none(pgd_t pgd)
-{ return !(pgd_val(pgd) & 0xFFFFFFF); }
-
-static int apmmu_pgd_bad(pgd_t pgd)
-{ return (pgd_val(pgd) & APMMU_ET_MASK) != APMMU_ET_PTD; }
-
-static int apmmu_pgd_present(pgd_t pgd)
-{ return ((pgd_val(pgd) & APMMU_ET_MASK) == APMMU_ET_PTD); }
-
-static void apmmu_pgd_clear(pgd_t * pgdp) { set_pte((pte_t *)pgdp, __pte(0)); }
-
-static pte_t apmmu_pte_mkwrite(pte_t pte) { return __pte(pte_val(pte) | APMMU_WRITE);}
-static pte_t apmmu_pte_mkdirty(pte_t pte) { return __pte(pte_val(pte) | APMMU_DIRTY);}
-static pte_t apmmu_pte_mkyoung(pte_t pte) { return __pte(pte_val(pte) | APMMU_REF);}
-
-/*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
- */
-static pte_t apmmu_mk_pte(unsigned long page, pgprot_t pgprot)
-{ return __pte(((apmmu_v2p(page)) >> 4) | pgprot_val(pgprot)); }
-
-static pte_t apmmu_mk_pte_phys(unsigned long page, pgprot_t pgprot)
-{ return __pte(((page) >> 4) | pgprot_val(pgprot)); }
-
-static pte_t apmmu_mk_pte_io(unsigned long page, pgprot_t pgprot, int space)
-{
- return __pte(((page) >> 4) | (space << 28) | pgprot_val(pgprot));
-}
-
-static void apmmu_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp)
-{
- set_pte((pte_t *)ctxp, (APMMU_ET_PTD | (apmmu_v2p((unsigned long) pgdp) >> 4)));
-}
-
-static void apmmu_pgd_set(pgd_t * pgdp, pmd_t * pmdp)
-{
- set_pte((pte_t *)pgdp, (APMMU_ET_PTD | (apmmu_v2p((unsigned long) pmdp) >> 4)));
-}
-
-static void apmmu_pmd_set(pmd_t * pmdp, pte_t * ptep)
-{
- set_pte((pte_t *)pmdp, (APMMU_ET_PTD | (apmmu_v2p((unsigned long) ptep) >> 4)));
-}
-
-static pte_t apmmu_pte_modify(pte_t pte, pgprot_t newprot)
-{
- return __pte((pte_val(pte) & APMMU_CHG_MASK) | pgprot_val(newprot));
-}
-
-/* to find an entry in a top-level page table... */
-static pgd_t *apmmu_pgd_offset(struct mm_struct * mm, unsigned long address)
-{
- return mm->pgd + ((address >> APMMU_PGDIR_SHIFT) & (APMMU_PTRS_PER_PGD - 1));
-}
-
-/* Find an entry in the second-level page table.. */
-static pmd_t *apmmu_pmd_offset(pgd_t * dir, unsigned long address)
-{
- return (pmd_t *) apmmu_pgd_page(*dir) + ((address >> APMMU_PMD_SHIFT) & (APMMU_PTRS_PER_PMD - 1));
-}
-
-/* Find an entry in the third-level page table.. */
-static pte_t *apmmu_pte_offset(pmd_t * dir, unsigned long address)
-{
- return (pte_t *) apmmu_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (APMMU_PTRS_PER_PTE - 1));
-}
-
-/* This must update the context table entry for this process. */
-static void apmmu_update_rootmmu_dir(struct task_struct *tsk, pgd_t *pgdp)
-{
- if(tsk->mm->context != NO_CONTEXT) {
- flush_cache_mm(current->mm);
- apmmu_ctxd_set(&apmmu_context_table[tsk->mm->context], pgdp);
- flush_tlb_mm(current->mm);
- }
-}
-
-
-/* Accessing the MMU control register. */
-static inline unsigned int apmmu_get_mmureg(void)
-{
- unsigned int retval;
- __asm__ __volatile__("lda [%%g0] %1, %0\n\t" :
- "=r" (retval) :
- "i" (ASI_M_MMUREGS));
- return retval;
-}
-
-static inline void apmmu_set_mmureg(unsigned long regval)
-{
- __asm__ __volatile__("sta %0, [%%g0] %1\n\t" : :
- "r" (regval), "i" (ASI_M_MMUREGS) : "memory");
-
-}
-
-static inline void apmmu_set_ctable_ptr(unsigned long paddr)
-{
- paddr = ((paddr >> 4) & APMMU_CTX_PMASK);
- paddr |= (MEM_BUS_SPACE<<28);
- __asm__ __volatile__("sta %0, [%1] %2\n\t" : :
- "r" (paddr), "r" (APMMU_CTXTBL_PTR),
- "i" (ASI_M_MMUREGS) :
- "memory");
-}
-
-static inline void apmmu_flush_whole_tlb(void)
-{
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
- "r" (0x400), /* Flush entire TLB!! */
- "i" (ASI_M_FLUSH_PROBE) : "memory");
-
-}
-
-/* These flush types are not available on all chips... */
-static inline void apmmu_flush_tlb_ctx(void)
-{
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
- "r" (0x300), /* Flush TLB ctx.. */
- "i" (ASI_M_FLUSH_PROBE) : "memory");
-
-}
-
-static inline void apmmu_flush_tlb_region(unsigned long addr)
-{
- addr &= APMMU_PGDIR_MASK;
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
- "r" (addr | 0x200), /* Flush TLB region.. */
- "i" (ASI_M_FLUSH_PROBE) : "memory");
-
-}
-
-
-static inline void apmmu_flush_tlb_segment(unsigned long addr)
-{
- addr &= APMMU_PMD_MASK;
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
- "r" (addr | 0x100), /* Flush TLB segment.. */
- "i" (ASI_M_FLUSH_PROBE) : "memory");
-
-}
-
-static inline void apmmu_flush_tlb_page(unsigned long page)
-{
- page &= PAGE_MASK;
- __asm__ __volatile__("sta %%g0, [%0] %1\n\t": :
- "r" (page), /* Flush TLB page.. */
- "i" (ASI_M_FLUSH_PROBE) : "memory");
-
-}
-
-static inline unsigned long apmmu_hwprobe(unsigned long vaddr)
-{
- unsigned long retval;
-
- vaddr &= PAGE_MASK;
- __asm__ __volatile__("lda [%1] %2, %0\n\t" :
- "=r" (retval) :
- "r" (vaddr | 0x400), "i" (ASI_M_FLUSH_PROBE));
-
- return retval;
-}
-
-static inline void apmmu_uncache_page(unsigned long addr)
-{
- pgd_t *pgdp = apmmu_pgd_offset(&init_mm, addr);
- pmd_t *pmdp;
- pte_t *ptep;
-
- if((pgd_val(*pgdp) & APMMU_ET_MASK) == APMMU_ET_PTE) {
- ptep = (pte_t *) pgdp;
- } else {
- pmdp = apmmu_pmd_offset(pgdp, addr);
- if((pmd_val(*pmdp) & APMMU_ET_MASK) == APMMU_ET_PTE) {
- ptep = (pte_t *) pmdp;
- } else {
- ptep = apmmu_pte_offset(pmdp, addr);
- }
- }
-
- set_pte(ptep, __pte((pte_val(*ptep) & ~APMMU_CACHE)));
- viking_flush_tlb_page_for_cbit(addr);
-}
-
-static inline void apmmu_recache_page(unsigned long addr)
-{
- pgd_t *pgdp = apmmu_pgd_offset(&init_mm, addr);
- pmd_t *pmdp;
- pte_t *ptep;
-
- if((pgd_val(*pgdp) & APMMU_ET_MASK) == APMMU_ET_PTE) {
- ptep = (pte_t *) pgdp;
- } else {
- pmdp = apmmu_pmd_offset(pgdp, addr);
- if((pmd_val(*pmdp) & APMMU_ET_MASK) == APMMU_ET_PTE) {
- ptep = (pte_t *) pmdp;
- } else {
- ptep = apmmu_pte_offset(pmdp, addr);
- }
- }
- set_pte(ptep, __pte((pte_val(*ptep) | APMMU_CACHE)));
- viking_flush_tlb_page_for_cbit(addr);
-}
-
-static inline unsigned long apmmu_getpage(void)
-{
- unsigned long page = get_free_page(GFP_KERNEL);
-
- return page;
-}
-
-static inline void apmmu_putpage(unsigned long page)
-{
- free_page(page);
-}
-
-/* The easy versions. */
-#define NEW_PGD() (pgd_t *) apmmu_getpage()
-#define NEW_PMD() (pmd_t *) apmmu_getpage()
-#define NEW_PTE() (pte_t *) apmmu_getpage()
-#define FREE_PGD(chunk) apmmu_putpage((unsigned long)(chunk))
-#define FREE_PMD(chunk) apmmu_putpage((unsigned long)(chunk))
-#define FREE_PTE(chunk) apmmu_putpage((unsigned long)(chunk))
-
-static pte_t *apmmu_get_pte_fast(void)
-{
- return (pte_t *)0;
-}
-
-static pmd_t *apmmu_get_pmd_fast(void)
-{
- return (pmd_t *)0;
-}
-
-static pgd_t *apmmu_get_pgd_fast(void)
-{
- return (pgd_t *)0;
-}
-
-static void apmmu_free_pte_slow(pte_t *pte)
-{
-/* TBD */
-}
-
-static void apmmu_free_pmd_slow(pmd_t *pmd)
-{
-/* TBD */
-}
-
-static void apmmu_free_pgd_slow(pgd_t *pgd)
-{
-/* TBD */
-}
-
-
-/*
- * Allocate and free page tables. The xxx_kernel() versions are
- * used to allocate a kernel page table - this turns on ASN bits
- * if any, and marks the page tables reserved.
- */
-static void apmmu_pte_free_kernel(pte_t *pte)
-{
- FREE_PTE(pte);
-}
-
-static pte_t *apmmu_pte_alloc_kernel(pmd_t *pmd, unsigned long address)
-{
- address = (address >> PAGE_SHIFT) & (APMMU_PTRS_PER_PTE - 1);
- if(apmmu_pmd_none(*pmd)) {
- pte_t *page = NEW_PTE();
- if(apmmu_pmd_none(*pmd)) {
- if(page) {
- apmmu_pmd_set(pmd, page);
- return page + address;
- }
- apmmu_pmd_set(pmd, BAD_PAGETABLE);
- return NULL;
- }
- FREE_PTE(page);
- }
- if(apmmu_pmd_bad(*pmd)) {
- printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
- apmmu_pmd_set(pmd, BAD_PAGETABLE);
- return NULL;
- }
- return (pte_t *) apmmu_pmd_page(*pmd) + address;
-}
-
-static void apmmu_pmd_free_kernel(pmd_t *pmd)
-{
- FREE_PMD(pmd);
-}
-
-static pmd_t *apmmu_pmd_alloc_kernel(pgd_t *pgd, unsigned long address)
-{
- address = (address >> APMMU_PMD_SHIFT) & (APMMU_PTRS_PER_PMD - 1);
- if(apmmu_pgd_none(*pgd)) {
- pmd_t *page;
- page = NEW_PMD();
- if(apmmu_pgd_none(*pgd)) {
- if(page) {
- pgd_set(pgd, page);
- return page + address;
- }
- pgd_set(pgd, (pmd_t *) BAD_PAGETABLE);
- return NULL;
- }
- FREE_PMD(page);
- }
- if(apmmu_pgd_bad(*pgd)) {
- printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
- pgd_set(pgd, (pmd_t *) BAD_PAGETABLE);
- return NULL;
- }
- return (pmd_t *) pgd_page(*pgd) + address;
-}
-
-static void apmmu_pte_free(pte_t *pte)
-{
- FREE_PTE(pte);
-}
-
-static pte_t *apmmu_pte_alloc(pmd_t * pmd, unsigned long address)
-{
- address = (address >> PAGE_SHIFT) & (APMMU_PTRS_PER_PTE - 1);
- if(apmmu_pmd_none(*pmd)) {
- pte_t *page = NEW_PTE();
- if(apmmu_pmd_none(*pmd)) {
- if(page) {
- apmmu_pmd_set(pmd, page);
- return page + address;
- }
- apmmu_pmd_set(pmd, BAD_PAGETABLE);
- return NULL;
- }
- FREE_PTE(page);
- }
- if(apmmu_pmd_bad(*pmd)) {
- printk("Bad pmd in pte_alloc: %08lx\n", pmd_val(*pmd));
- apmmu_pmd_set(pmd, BAD_PAGETABLE);
- return NULL;
- }
- return ((pte_t *) apmmu_pmd_page(*pmd)) + address;
-}
-
-/* Real three-level page tables on APMMU. */
-static void apmmu_pmd_free(pmd_t * pmd)
-{
- FREE_PMD(pmd);
-}
-
-static pmd_t *apmmu_pmd_alloc(pgd_t * pgd, unsigned long address)
-{
- address = (address >> APMMU_PMD_SHIFT) & (APMMU_PTRS_PER_PMD - 1);
- if(apmmu_pgd_none(*pgd)) {
- pmd_t *page = NEW_PMD();
- if(apmmu_pgd_none(*pgd)) {
- if(page) {
- pgd_set(pgd, page);
- return page + address;
- }
- pgd_set(pgd, (pmd_t *) BAD_PAGETABLE);
- return NULL;
- }
- FREE_PMD(page);
- }
- if(apmmu_pgd_bad(*pgd)) {
- printk("Bad pgd in pmd_alloc: %08lx\n", pgd_val(*pgd));
- pgd_set(pgd, (pmd_t *) BAD_PAGETABLE);
- return NULL;
- }
- return (pmd_t *) apmmu_pgd_page(*pgd) + address;
-}
-
-static void apmmu_pgd_free(pgd_t *pgd)
-{
- FREE_PGD(pgd);
-}
-
-static pgd_t *apmmu_pgd_alloc(void)
-{
- return NEW_PGD();
-}
-
-static void apmmu_pgd_flush(pgd_t *pgdp)
-{
-}
-
-static void apmmu_set_pte_cacheable(pte_t *ptep, pte_t pteval)
-{
- apmmu_set_entry(ptep, pte_val(pteval));
-}
-
-static void apmmu_quick_kernel_fault(unsigned long address)
-{
- printk("Kernel faults at addr=0x%08lx\n", address);
- printk("PTE=%08lx\n", apmmu_hwprobe((address & PAGE_MASK)));
- die_if_kernel("APMMU bolixed...", current->thread.kregs);
-}
-
-static inline void alloc_context(struct task_struct *tsk)
-{
- struct mm_struct *mm = tsk->mm;
- struct ctx_list *ctxp;
-
- if (tsk->taskid >= MPP_TASK_BASE) {
- mm->context = MPP_CONTEXT_BASE + (tsk->taskid - MPP_TASK_BASE);
- return;
- }
-
- ctxp = ctx_free.next;
- if(ctxp != &ctx_free) {
- remove_from_ctx_list(ctxp);
- add_to_used_ctxlist(ctxp);
- mm->context = ctxp->ctx_number;
- ctxp->ctx_mm = mm;
- return;
- }
- ctxp = ctx_used.next;
- if(ctxp->ctx_mm == current->mm)
- ctxp = ctxp->next;
- if(ctxp == &ctx_used)
- panic("out of mmu contexts");
- flush_cache_mm(ctxp->ctx_mm);
- flush_tlb_mm(ctxp->ctx_mm);
- remove_from_ctx_list(ctxp);
- add_to_used_ctxlist(ctxp);
- ctxp->ctx_mm->context = NO_CONTEXT;
- ctxp->ctx_mm = mm;
- mm->context = ctxp->ctx_number;
-}
-
-static inline void free_context(int context)
-{
- struct ctx_list *ctx_old;
-
- if (context >= MPP_CONTEXT_BASE)
- return; /* nothing to do! */
-
- ctx_old = ctx_list_pool + context;
- remove_from_ctx_list(ctx_old);
- add_to_free_ctxlist(ctx_old);
-}
-
-
-static void apmmu_switch_to_context(struct task_struct *tsk)
-{
- if(tsk->mm->context == NO_CONTEXT) {
- alloc_context(tsk);
- flush_cache_mm(current->mm);
- apmmu_ctxd_set(&apmmu_context_table[tsk->mm->context], tsk->mm->pgd);
- flush_tlb_mm(current->mm);
- }
- apmmu_set_context(tsk->mm->context);
-}
-
-static char *apmmu_lockarea(char *vaddr, unsigned long len)
-{
- return vaddr;
-}
-
-static void apmmu_unlockarea(char *vaddr, unsigned long len)
-{
-}
-
-struct task_struct *apmmu_alloc_task_struct(void)
-{
- return (struct task_struct *) kmalloc(sizeof(struct task_struct), GFP_KERNEL);
-}
-
-static void apmmu_free_task_struct(struct task_struct *tsk)
-{
- kfree(tsk);
-}
-
-static void apmmu_null_func(void)
-{
-}
-
-static inline void mc_tlb_flush_all(void)
-{
- unsigned long long *tlb4k;
- int i;
-
- tlb4k = (unsigned long long *)MC_MMU_TLB4K;
- for (i = MC_MMU_TLB4K_SIZE/4; i > 0; --i) {
- tlb4k[0] = 0;
- tlb4k[1] = 0;
- tlb4k[2] = 0;
- tlb4k[3] = 0;
- tlb4k += 4;
- }
-}
-
-static inline void mc_tlb_flush_page(unsigned vaddr,int ctx)
-{
- if (ctx == SYSTEM_CONTEXT || MPP_IS_PAR_CTX(ctx)) {
- *(((unsigned long long *)MC_MMU_TLB4K) + ((vaddr>>12)&0xFF)) = 0;
- }
-}
-
-static inline void mc_tlb_flush_ctx(int ctx)
-{
- unsigned long long *tlb4k = (unsigned long long *)MC_MMU_TLB4K;
- if (ctx == SYSTEM_CONTEXT || MPP_IS_PAR_CTX(ctx)) {
- int i;
- for (i=0; i<MC_MMU_TLB4K_SIZE;i++)
- if (((tlb4k[i] >> 5) & 0xFFF) == ctx) tlb4k[i] = 0;
- }
-}
-
-static inline void mc_tlb_flush_region(unsigned start,int ctx)
-{
- mc_tlb_flush_ctx(ctx);
-}
-
-static inline void mc_tlb_flush_segment(unsigned start,int ctx)
-{
- mc_tlb_flush_ctx(ctx);
-}
-
-static void viking_flush_tlb_all(void)
-{
- module_stats.invall++;
- flush_user_windows();
- apmmu_flush_whole_tlb();
- mc_tlb_flush_all();
-}
-
-static void viking_flush_tlb_mm(struct mm_struct *mm)
-{
- int octx;
-
- module_stats.invmm++;
-
- if(mm->context != NO_CONTEXT) {
- flush_user_windows();
- octx = apmmu_get_context();
- if (octx != mm->context)
- apmmu_set_context(mm->context);
- apmmu_flush_tlb_ctx();
- mc_tlb_flush_ctx(mm->context);
- if (octx != mm->context)
- apmmu_set_context(octx);
- }
-}
-
-static void viking_flush_tlb_range(struct mm_struct *mm, unsigned long start, unsigned long end)
-{
- int octx;
-
- module_stats.invrnge++;
-
- if(mm->context != NO_CONTEXT) {
- flush_user_windows();
- octx = apmmu_get_context();
- if (octx != mm->context)
- apmmu_set_context(mm->context);
- if((end - start) < APMMU_PMD_SIZE) {
- start &= PAGE_MASK;
- while(start < end) {
- apmmu_flush_tlb_page(start);
- mc_tlb_flush_page(start,mm->context);
- start += PAGE_SIZE;
- }
- } else if((end - start) < APMMU_PGDIR_SIZE) {
- start &= APMMU_PMD_MASK;
- while(start < end) {
- apmmu_flush_tlb_segment(start);
- mc_tlb_flush_segment(start,mm->context);
- start += APMMU_PMD_SIZE;
- }
- } else {
- start &= APMMU_PGDIR_MASK;
- while(start < end) {
- apmmu_flush_tlb_region(start);
- mc_tlb_flush_region(start,mm->context);
- start += APMMU_PGDIR_SIZE;
- }
- }
- if (octx != mm->context)
- apmmu_set_context(octx);
- }
-}
-
-static void viking_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
-{
- int octx;
- struct mm_struct *mm = vma->vm_mm;
-
- module_stats.invpg++;
- if(mm->context != NO_CONTEXT) {
- flush_user_windows();
- octx = apmmu_get_context();
- if (octx != mm->context)
- apmmu_set_context(mm->context);
- apmmu_flush_tlb_page(page);
- mc_tlb_flush_page(page,mm->context);
- if (octx != mm->context)
- apmmu_set_context(octx);
- }
-}
-
-static void viking_flush_tlb_page_for_cbit(unsigned long page)
-{
- apmmu_flush_tlb_page(page);
- mc_tlb_flush_page(page,apmmu_get_context());
-}
-
-/* Some dirty hacks to abstract away the painful boot up init. */
-static inline unsigned long apmmu_early_paddr(unsigned long vaddr)
-{
- return (vaddr - KERNBASE);
-}
-
-static inline void apmmu_early_pgd_set(pgd_t *pgdp, pmd_t *pmdp)
-{
- set_pte((pte_t *)pgdp, __pte((APMMU_ET_PTD | (apmmu_early_paddr((unsigned long) pmdp) >> 4))));
-}
-
-static inline void apmmu_early_pmd_set(pmd_t *pmdp, pte_t *ptep)
-{
- set_pte((pte_t *)pmdp, __pte((APMMU_ET_PTD | (apmmu_early_paddr((unsigned long) ptep) >> 4))));
-}
-
-static inline unsigned long apmmu_early_pgd_page(pgd_t pgd)
-{
- return ((pgd_val(pgd) & APMMU_PTD_PMASK) << 4) + KERNBASE;
-}
-
-static inline unsigned long apmmu_early_pmd_page(pmd_t pmd)
-{
- return ((pmd_val(pmd) & APMMU_PTD_PMASK) << 4) + KERNBASE;
-}
-
-static inline pmd_t *apmmu_early_pmd_offset(pgd_t *dir, unsigned long address)
-{
- return (pmd_t *) apmmu_early_pgd_page(*dir) + ((address >> APMMU_PMD_SHIFT) & (APMMU_PTRS_PER_PMD - 1));
-}
-
-static inline pte_t *apmmu_early_pte_offset(pmd_t *dir, unsigned long address)
-{
- return (pte_t *) apmmu_early_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (APMMU_PTRS_PER_PTE - 1));
-}
-
-static inline void __init apmmu_allocate_ptable_skeleton(unsigned long start, unsigned long end)
-{
- pgd_t *pgdp;
- pmd_t *pmdp;
- pte_t *ptep;
-
- while(start < end) {
- pgdp = apmmu_pgd_offset(&init_mm, start);
- if(apmmu_pgd_none(*pgdp)) {
- pmdp = sparc_init_alloc(&mempool, APMMU_PMD_TABLE_SIZE);
- apmmu_early_pgd_set(pgdp, pmdp);
- }
- pmdp = apmmu_early_pmd_offset(pgdp, start);
- if(apmmu_pmd_none(*pmdp)) {
- ptep = sparc_init_alloc(&mempool, APMMU_PTE_TABLE_SIZE);
- apmmu_early_pmd_set(pmdp, ptep);
- }
- start = (start + APMMU_PMD_SIZE) & APMMU_PMD_MASK;
- }
-}
-
-
-static void __init make_page(unsigned virt_page, unsigned phys_page, unsigned prot)
-{
- pgd_t *pgdp;
- pmd_t *pmdp;
- pte_t *ptep;
- unsigned start = virt_page<<12;
-
- pgdp = apmmu_pgd_offset(&init_mm, start);
- if(apmmu_pgd_none(*pgdp)) {
- pmdp = sparc_init_alloc(&mempool, APMMU_PMD_TABLE_SIZE);
- apmmu_early_pgd_set(pgdp, pmdp);
- }
- pmdp = apmmu_early_pmd_offset(pgdp, start);
- if(apmmu_pmd_none(*pmdp)) {
- ptep = sparc_init_alloc(&mempool, APMMU_PTE_TABLE_SIZE);
- apmmu_early_pmd_set(pmdp, ptep);
- }
- ptep = apmmu_early_pte_offset(pmdp, start);
- *ptep = __pte((phys_page<<8) | prot);
-}
-
-
-static void __init make_large_page(unsigned virt_page, unsigned phys_page, unsigned prot)
-{
- pgd_t *pgdp;
- unsigned start = virt_page<<12;
-
- pgdp = apmmu_pgd_offset(&init_mm, start);
- *pgdp = __pgd((phys_page<<8) | prot);
-}
-
-
-static void __init ap_setup_mappings(void)
-{
- unsigned Srwe = APMMU_PRIV | APMMU_VALID;
- unsigned SrweUr = 0x14 | APMMU_VALID; /* weird! */
-
- /* LBus */
- make_large_page(0xfb000,0x9fb000,Srwe);
- make_large_page(0xff000,0x9ff000,SrweUr);
- make_large_page(0xfc000,0x911000,Srwe);
-
- /* MC Register */
- make_page(0xfa000,0xb00000,SrweUr);
- make_page(0xfa001,0xb00001,Srwe);
- make_page(0xfa002,0xb00002,Srwe);
- make_page(0xfa003,0xb00003,Srwe);
- make_page(0xfa004,0xb00004,Srwe);
- make_page(0xfa005,0xb00005,Srwe);
- make_page(0xfa006,0xb00006,Srwe);
- make_page(0xfa007,0xb00007,Srwe);
-
- /* MSC+ Register */
- make_page(0xfa008,0xc00000,SrweUr);
- make_page(0xfa009,0xc00001,Srwe);
- make_page(0xfa00a,0xc00002,Srwe);
- make_page(0xfa00b,0xc00003,Srwe);
- make_page(0xfa00c,0xc00004,Srwe);
- make_page(0xfa00d,0xc00005,Srwe); /* RBMPR 0 */
- make_page(0xfa00e,0xc00006,Srwe); /* RBMPR 1 */
- make_page(0xfa00f,0xc00007,Srwe); /* RBMPR 2 */
-
- /* user queues */
- make_page(MSC_PUT_QUEUE>>PAGE_SHIFT, 0xa00000,Srwe);
- make_page(MSC_GET_QUEUE>>PAGE_SHIFT, 0xa00001,Srwe);
- make_page(MSC_SEND_QUEUE>>PAGE_SHIFT, 0xa00040,Srwe);
- make_page(MSC_XY_QUEUE>>PAGE_SHIFT, 0xa00640,Srwe);
- make_page(MSC_X_QUEUE>>PAGE_SHIFT, 0xa00240,Srwe);
- make_page(MSC_Y_QUEUE>>PAGE_SHIFT, 0xa00440,Srwe);
- make_page(MSC_XYG_QUEUE>>PAGE_SHIFT, 0xa00600,Srwe);
- make_page(MSC_XG_QUEUE>>PAGE_SHIFT, 0xa00200,Srwe);
- make_page(MSC_YG_QUEUE>>PAGE_SHIFT, 0xa00400,Srwe);
- make_page(MSC_CSI_QUEUE>>PAGE_SHIFT, 0xa02004,Srwe);
- make_page(MSC_FOP_QUEUE>>PAGE_SHIFT, 0xa02005,Srwe);
-
- /* system queues */
- make_page(MSC_PUT_QUEUE_S>>PAGE_SHIFT, 0xa02000,Srwe); /* system put */
- make_page(MSC_CPUT_QUEUE_S>>PAGE_SHIFT, 0xa02020,Srwe); /* system creg put */
- make_page(MSC_GET_QUEUE_S>>PAGE_SHIFT, 0xa02001,Srwe); /* system get */
- make_page(MSC_CGET_QUEUE_S>>PAGE_SHIFT, 0xa02021,Srwe); /* system creg get */
- make_page(MSC_SEND_QUEUE_S>>PAGE_SHIFT, 0xa02040,Srwe); /* system send */
- make_page(MSC_BSEND_QUEUE_S>>PAGE_SHIFT,0xa02640,Srwe); /* system send broad */
- make_page(MSC_XYG_QUEUE_S>>PAGE_SHIFT, 0xa02600,Srwe); /* system put broad */
- make_page(MSC_CXYG_QUEUE_S>>PAGE_SHIFT, 0xa02620,Srwe); /* system put broad */
-
- /* Direct queue access entries for refilling the MSC send queue */
- make_page(MSC_SYSTEM_DIRECT>>PAGE_SHIFT, 0xa08000,Srwe);
- make_page(MSC_USER_DIRECT>>PAGE_SHIFT, 0xa08001,Srwe);
- make_page(MSC_REMOTE_DIRECT>>PAGE_SHIFT, 0xa08002,Srwe);
- make_page(MSC_REPLY_DIRECT>>PAGE_SHIFT, 0xa08003,Srwe);
- make_page(MSC_REMREPLY_DIRECT>>PAGE_SHIFT, 0xa08004,Srwe);
-
- /* As above with end-bit set */
- make_page(MSC_SYSTEM_DIRECT_END>>PAGE_SHIFT, 0xa0c000,Srwe);
- make_page(MSC_USER_DIRECT_END>>PAGE_SHIFT, 0xa0c001,Srwe);
- make_page(MSC_REMOTE_DIRECT_END>>PAGE_SHIFT, 0xa0c002,Srwe);
- make_page(MSC_REPLY_DIRECT_END>>PAGE_SHIFT, 0xa0c003,Srwe);
- make_page(MSC_REMREPLY_DIRECT_END>>PAGE_SHIFT, 0xa0c004,Srwe);
-}
-
-static void __init map_kernel(void)
-{
- int phys;
-
- /* the AP+ only ever has one bank of memory starting at address 0 */
- ap_mem_size = sp_banks[0].num_bytes;
- for (phys=0; phys < sp_banks[0].num_bytes; phys += APMMU_PGDIR_SIZE)
- make_large_page((KERNBASE+phys)>>12,
- (phys>>12),
- APMMU_CACHE|APMMU_PRIV|APMMU_VALID);
- init_mm.mmap->vm_start = PAGE_OFFSET;
-}
-
-extern unsigned long free_area_init(unsigned long, unsigned long);
-extern unsigned long sparc_context_init(unsigned long, int);
-
-extern int physmem_mapped_contig;
-extern int linux_num_cpus;
-
-unsigned long __init apmmu_paging_init(unsigned long start_mem, unsigned long end_mem)
-{
- int i;
-
- physmem_mapped_contig = 1; /* for init.c:taint_real_pages() */
-
- num_contexts = AP_NUM_CONTEXTS;
- mempool = PAGE_ALIGN(start_mem);
- memset(swapper_pg_dir, 0, PAGE_SIZE);
-
- apmmu_allocate_ptable_skeleton(KERNBASE, end_mem);
- mempool = PAGE_ALIGN(mempool);
- map_kernel();
- ap_setup_mappings();
-
- /* the MSC wants this aligned on a 16k boundary */
- apmmu_context_table =
- sparc_init_alloc(&mempool,
- num_contexts*sizeof(ctxd_t)<0x4000?
- 0x4000:
- num_contexts*sizeof(ctxd_t));
- apmmu_ctx_table_phys = (ctxd_t *) apmmu_v2p((unsigned long) apmmu_context_table);
- for(i = 0; i < num_contexts; i++)
- apmmu_ctxd_set(&apmmu_context_table[i], swapper_pg_dir);
-
- start_mem = PAGE_ALIGN(mempool);
-
- flush_cache_all();
- apmmu_set_ctable_ptr((unsigned long) apmmu_ctx_table_phys);
- flush_tlb_all();
- poke_viking();
-
- /* on the AP we don't put the top few contexts into the free
- context list as these are reserved for parallel tasks */
- start_mem = sparc_context_init(start_mem, MPP_CONTEXT_BASE);
- start_mem = free_area_init(start_mem, end_mem);
-
- return PAGE_ALIGN(start_mem);
-}
-
-static int apmmu_mmu_info(char *buf)
-{
- return sprintf(buf,
- "MMU type\t: %s\n"
- "invall\t\t: %d\n"
- "invmm\t\t: %d\n"
- "invrnge\t\t: %d\n"
- "invpg\t\t: %d\n"
- "contexts\t: %d\n"
- , apmmu_name,
- module_stats.invall,
- module_stats.invmm,
- module_stats.invrnge,
- module_stats.invpg,
- num_contexts
- );
-}
-
-static void apmmu_update_mmu_cache(struct vm_area_struct * vma, unsigned long address, pte_t pte)
-{
-}
-
-static void __init poke_viking(void)
-{
- unsigned long mreg = apmmu_get_mmureg();
-
- mreg |= VIKING_SPENABLE;
- mreg |= (VIKING_ICENABLE | VIKING_DCENABLE);
- mreg &= ~VIKING_ACENABLE;
- mreg &= ~VIKING_SBENABLE;
- mreg |= VIKING_TCENABLE;
- apmmu_set_mmureg(mreg);
-}
-
-static void __init init_viking(void)
-{
- apmmu_name = "TI Viking/AP1000";
-
- BTFIXUPSET_CALL(flush_cache_all, apmmu_null_func, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(flush_cache_mm, apmmu_null_func, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(flush_cache_page, apmmu_null_func, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(flush_cache_range, apmmu_null_func, BTFIXUPCALL_NOP);
-
- BTFIXUPSET_CALL(flush_tlb_all, viking_flush_tlb_all, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_mm, viking_flush_tlb_mm, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_page, viking_flush_tlb_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(flush_tlb_range, viking_flush_tlb_range, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(flush_page_to_ram, apmmu_null_func, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(flush_sig_insns, apmmu_null_func, BTFIXUPCALL_NOP);
-}
-
-
-extern unsigned long spwin_mmu_patchme, fwin_mmu_patchme,
- tsetup_mmu_patchme, rtrap_mmu_patchme;
-
-extern unsigned long spwin_srmmu_stackchk, srmmu_fwin_stackchk,
- tsetup_srmmu_stackchk, srmmu_rett_stackchk;
-
-extern unsigned long srmmu_fault;
-
-#define PATCH_BRANCH(insn, dest) do { \
- iaddr = &(insn); \
- daddr = &(dest); \
- *iaddr = SPARC_BRANCH((unsigned long) daddr, (unsigned long) iaddr); \
- } while(0);
-
-static void __init patch_window_trap_handlers(void)
-{
- unsigned long *iaddr, *daddr;
-
- PATCH_BRANCH(spwin_mmu_patchme, spwin_srmmu_stackchk);
- PATCH_BRANCH(fwin_mmu_patchme, srmmu_fwin_stackchk);
- PATCH_BRANCH(tsetup_mmu_patchme, tsetup_srmmu_stackchk);
- PATCH_BRANCH(rtrap_mmu_patchme, srmmu_rett_stackchk);
- PATCH_BRANCH(sparc_ttable[SP_TRAP_TFLT].inst_three, srmmu_fault);
- PATCH_BRANCH(sparc_ttable[SP_TRAP_DFLT].inst_three, srmmu_fault);
- PATCH_BRANCH(sparc_ttable[SP_TRAP_DACC].inst_three, srmmu_fault);
-}
-
-/* Load up routines and constants for apmmu */
-void __init ld_mmu_apmmu(void)
-{
- /* First the constants */
- BTFIXUPSET_SIMM13(pmd_shift, APMMU_PMD_SHIFT);
- BTFIXUPSET_SETHI(pmd_size, APMMU_PMD_SIZE);
- BTFIXUPSET_SETHI(pmd_mask, APMMU_PMD_MASK);
- BTFIXUPSET_SIMM13(pgdir_shift, APMMU_PGDIR_SHIFT);
- BTFIXUPSET_SETHI(pgdir_size, APMMU_PGDIR_SIZE);
- BTFIXUPSET_SETHI(pgdir_mask, APMMU_PGDIR_MASK);
-
- BTFIXUPSET_SIMM13(ptrs_per_pte, APMMU_PTRS_PER_PTE);
- BTFIXUPSET_SIMM13(ptrs_per_pmd, APMMU_PTRS_PER_PMD);
- BTFIXUPSET_SIMM13(ptrs_per_pgd, APMMU_PTRS_PER_PGD);
-
- BTFIXUPSET_INT(page_none, pgprot_val(APMMU_PAGE_NONE));
- BTFIXUPSET_INT(page_shared, pgprot_val(APMMU_PAGE_SHARED));
- BTFIXUPSET_INT(page_copy, pgprot_val(APMMU_PAGE_COPY));
- BTFIXUPSET_INT(page_readonly, pgprot_val(APMMU_PAGE_RDONLY));
- BTFIXUPSET_INT(page_kernel, pgprot_val(APMMU_PAGE_KERNEL));
- pg_iobits = APMMU_VALID | APMMU_WRITE | APMMU_REF;
-
- /* Functions */
- BTFIXUPSET_CALL(get_pte_fast, apmmu_get_pte_fast, BTFIXUPCALL_RETINT(0));
- BTFIXUPSET_CALL(get_pmd_fast, apmmu_get_pmd_fast, BTFIXUPCALL_RETINT(0));
- BTFIXUPSET_CALL(get_pgd_fast, apmmu_get_pgd_fast, BTFIXUPCALL_RETINT(0));
- BTFIXUPSET_CALL(free_pte_slow, apmmu_free_pte_slow, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(free_pmd_slow, apmmu_free_pmd_slow, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(free_pgd_slow, apmmu_free_pgd_slow, BTFIXUPCALL_NOP);
-
- BTFIXUPSET_CALL(set_pte, apmmu_set_pte_cacheable, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(switch_to_context, apmmu_switch_to_context, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(pte_page, apmmu_pte_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_page, apmmu_pmd_page, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_page, apmmu_pgd_page, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(sparc_update_rootmmu_dir, apmmu_update_rootmmu_dir, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_SETHI(none_mask, 0xF0000000);
-
- BTFIXUPSET_CALL(pte_present, apmmu_pte_present, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_clear, apmmu_pte_clear, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(pmd_bad, apmmu_pmd_bad, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_present, apmmu_pmd_present, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_clear, apmmu_pmd_clear, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(pgd_none, apmmu_pgd_none, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_bad, apmmu_pgd_bad, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_present, apmmu_pgd_present, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_clear, apmmu_pgd_clear, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(mk_pte, apmmu_mk_pte, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mk_pte_phys, apmmu_mk_pte_phys, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mk_pte_io, apmmu_mk_pte_io, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_set, apmmu_pgd_set, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_INT(pte_modify_mask, APMMU_CHG_MASK);
- BTFIXUPSET_CALL(pgd_offset, apmmu_pgd_offset, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_offset, apmmu_pmd_offset, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_offset, apmmu_pte_offset, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_free_kernel, apmmu_pte_free_kernel, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_free_kernel, apmmu_pmd_free_kernel, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_alloc_kernel, apmmu_pte_alloc_kernel, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_alloc_kernel, apmmu_pmd_alloc_kernel, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_free, apmmu_pte_free, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_alloc, apmmu_pte_alloc, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_free, apmmu_pmd_free, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pmd_alloc, apmmu_pmd_alloc, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_free, apmmu_pgd_free, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_alloc, apmmu_pgd_alloc, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pgd_flush, apmmu_pgd_flush, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_HALF(pte_writei, APMMU_WRITE);
- BTFIXUPSET_HALF(pte_dirtyi, APMMU_DIRTY);
- BTFIXUPSET_HALF(pte_youngi, APMMU_REF);
- BTFIXUPSET_HALF(pte_wrprotecti, APMMU_WRITE);
- BTFIXUPSET_HALF(pte_mkcleani, APMMU_DIRTY);
- BTFIXUPSET_HALF(pte_mkoldi, APMMU_REF);
- BTFIXUPSET_CALL(pte_mkwrite, apmmu_pte_mkwrite, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_mkdirty, apmmu_pte_mkdirty, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(pte_mkyoung, apmmu_pte_mkyoung, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(update_mmu_cache, apmmu_update_mmu_cache, BTFIXUPCALL_NOP);
-
- BTFIXUPSET_CALL(mmu_lockarea, apmmu_lockarea, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mmu_unlockarea, apmmu_unlockarea, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(mmu_get_scsi_one, apmmu_null_func, BTFIXUPCALL_RETO0);
- BTFIXUPSET_CALL(mmu_get_scsi_sgl, apmmu_null_func, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(mmu_release_scsi_one, apmmu_null_func, BTFIXUPCALL_NOP);
- BTFIXUPSET_CALL(mmu_release_scsi_sgl, apmmu_null_func, BTFIXUPCALL_NOP);
-
- BTFIXUPSET_CALL(mmu_info, apmmu_mmu_info, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mmu_v2p, apmmu_v2p, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(mmu_p2v, apmmu_p2v, BTFIXUPCALL_NORM);
-
- /* Task struct and kernel stack allocating/freeing. */
- BTFIXUPSET_CALL(alloc_task_struct, apmmu_alloc_task_struct, BTFIXUPCALL_NORM);
- BTFIXUPSET_CALL(free_task_struct, apmmu_free_task_struct, BTFIXUPCALL_NORM);
-
- BTFIXUPSET_CALL(quick_kernel_fault, apmmu_quick_kernel_fault, BTFIXUPCALL_NORM);
-
- init_viking();
- patch_window_trap_handlers();
-}
diff --git a/arch/sparc/ap1000/approm.c b/arch/sparc/ap1000/approm.c
deleted file mode 100644
index 4fe956bcb..000000000
--- a/arch/sparc/ap1000/approm.c
+++ /dev/null
@@ -1,148 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * fake a really simple Sun prom for the AP+
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <asm/oplib.h>
-#include <asm/idprom.h>
-#include <asm/machines.h>
-#include <asm/ap1000/apservice.h>
-
-static struct linux_romvec ap_romvec;
-static struct idprom ap_idprom;
-
-struct property {
- char *name;
- char *value;
- int length;
-};
-
-struct node {
- int level;
- struct property *properties;
-};
-
-struct property null_properties = { NULL, NULL, -1 };
-
-struct property root_properties[] = {
- {"device_type", "cpu", 4},
- {"idprom", (char *)&ap_idprom, sizeof(ap_idprom)},
- {"banner-name", "Fujitsu AP1000+", 16},
- {NULL, NULL, -1}
-};
-
-struct node nodes[] = {
- { 0, &null_properties },
- { 0, root_properties },
- { -1,&null_properties }
-};
-
-
-static int no_nextnode(int node)
-{
- if (nodes[node].level == nodes[node+1].level)
- return node+1;
- return -1;
-}
-
-static int no_child(int node)
-{
- if (nodes[node].level == nodes[node+1].level-1)
- return node+1;
- return -1;
-}
-
-static struct property *find_property(int node,char *name)
-{
- struct property *prop = &nodes[node].properties[0];
- while (prop && prop->name) {
- if (strcmp(prop->name,name) == 0) return prop;
- prop++;
- }
- return NULL;
-}
-
-static int no_proplen(int node,char *name)
-{
- struct property *prop = find_property(node,name);
- if (prop) return prop->length;
- return -1;
-}
-
-static int no_getprop(int node,char *name,char *value)
-{
- struct property *prop = find_property(node,name);
- if (prop) {
- memcpy(value,prop->value,prop->length);
- return 1;
- }
- return -1;
-}
-
-static int no_setprop(int node,char *name,char *value,int len)
-{
- return -1;
-}
-
-static char *no_nextprop(int node,char *name)
-{
- struct property *prop = find_property(node,name);
- if (prop) return prop[1].name;
- return NULL;
-}
-
-
-static struct linux_nodeops ap_nodeops = {
- no_nextnode,
- no_child,
- no_proplen,
- no_getprop,
- no_setprop,
- no_nextprop
-};
-
-
-
-static unsigned char calc_idprom_cksum(struct idprom *idprom)
-{
- unsigned char cksum, i, *ptr = (unsigned char *)idprom;
-
- for (i = cksum = 0; i <= 0x0E; i++)
- cksum ^= *ptr++;
-
- return cksum;
-}
-
-static int synch_hook;
-
-
-struct linux_romvec *ap_prom_init(void)
-{
- memset(&ap_romvec,0,sizeof(ap_romvec));
-
- ap_romvec.pv_romvers = 42;
- ap_romvec.pv_nodeops = &ap_nodeops;
- ap_romvec.pv_reboot = ap_reboot;
- ap_romvec.pv_synchook = &synch_hook;
-
- ap_idprom.id_format = 1;
- ap_idprom.id_sernum = mpp_cid();
- ap_idprom.id_machtype = SM_SUN4M_OBP;
- ap_idprom.id_cksum = calc_idprom_cksum(&ap_idprom);
-
- return &ap_romvec;
-}
-
-
-
-
-
diff --git a/arch/sparc/ap1000/bnet.c b/arch/sparc/ap1000/bnet.c
deleted file mode 100644
index e87d01181..000000000
--- a/arch/sparc/ap1000/bnet.c
+++ /dev/null
@@ -1,1205 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/* routines to control the AP1000 bif interface. This is the interface
- used to talk to the front end processor */
-
-#include <linux/sched.h>
-#include <asm/ap1000/apservice.h>
-#include <asm/ap1000/apreg.h>
-#include <linux/mm.h>
-#include <linux/malloc.h>
-#include <asm/irq.h>
-#include <linux/skbuff.h>
-
-#define NET_DEBUG 0
-
-#define DUMMY_MSG_LEN 100
-#define DUMMY_MSG_WAIT 30
-
-#define MAX_CELLS 128
-
-#define HAVE_BIF() (BIF_IN(BIF_SDCSR) & BIF_SDCSR_BG)
-#define BIF_BUSY() (BIF_IN(BIF_SDCSR) & BIF_SDCSR_BB)
-
-#define SNET_ARBITRATION 0
-#define TOKEN_ARBITRATION 1
-
-#define DEBUG(x)
-
-#if TOKEN_ARBITRATION
-static int have_token = 0;
-#endif
-
-extern struct cap_init cap_init;
-
-static int interrupt_driven = 0;
-static int use_dma = 0;
-struct pt_regs *bif_pt_regs = NULL;
-enum dma_state {DMA_IDLE,DMA_INCOMING,DMA_OUTGOING};
-static enum dma_state dma_state = DMA_IDLE;
-
-static int net_started = 0;
-static int waiting_for_bif = 0;
-static int queue_length = 0;
-
-static int drop_ip_packets = 0;
-
-#define DMA_THRESHOLD 64
-
-static struct cap_request bread_req;
-
-int tnet_ip_enabled = 1;
-
-#define BIF_DATA_WAITING() (BIF_IN(BIF_SDCSR) & BIF_SDCSR_RB)
-
-#define ROUND4(x) (((x) + 3) & -4)
-
-static void bif_intr_receive(struct cap_request *req1);
-
-
-/* read some data from the bif */
-void read_bif(char *buf,int size)
-{
- unsigned *ibuf = (unsigned *)buf;
- unsigned avail;
-
- DEBUG(("|read_bif %d\n",size));
-
- if (dma_state != DMA_IDLE) ap_dma_wait(DMA_CH2);
-
- size = (size+3) >> 2;
-
- while (size > 4) {
- while (!(avail=(BIF_IN(BIF_SDCSR) >> BIF_SDCSR_RB_SHIFT) & 7))
- ;
- if (avail & 4) {
- ibuf[0] = BIF_IN(BIF_DATA);
- ibuf[1] = BIF_IN(BIF_DATA);
- ibuf[2] = BIF_IN(BIF_DATA);
- ibuf[3] = BIF_IN(BIF_DATA);
- size -= 4; ibuf += 4;
- continue;
- }
-
- if (avail & 2) {
- ibuf[0] = BIF_IN(BIF_DATA);
- ibuf[1] = BIF_IN(BIF_DATA);
- size -= 2; ibuf += 2;
- continue;
- }
- *ibuf++ = BIF_IN(BIF_DATA);
- size--;
- }
-
- while (size--) {
- while (!(BIF_IN(BIF_SDCSR) & BIF_SDCSR_RB)) ;
- *ibuf++ = BIF_IN(BIF_DATA);
- }
-
- DEBUG(("|read bif done\n"));
-}
-
-/* throw out some data from the bif. This is usually called when we
- don't have the resources to handle it immediately */
-void bif_toss(int size)
-{
- unsigned flags;
- save_flags(flags); cli();
-
- DEBUG(("|bif toss %d\n",size));
-
- while (size>0) {
- while (!BIF_DATA_WAITING());
- BIF_IN(BIF_DATA);
- size -= 4;
- }
-
- DEBUG(("|bif toss done\n"));
-
- restore_flags(flags);
-}
-
-
-static void bif_reset_interrupts(void)
-{
- BIF_OUT(BIF_INTR,AP_INTR_WENABLE << BIF_INTR_GET_SH);
- BIF_OUT(BIF_INTR,AP_INTR_WENABLE << BIF_INTR_HEADER_SH);
-}
-
-static void bif_mask_interrupts(void)
-{
- BIF_OUT(BIF_INTR,(AP_INTR_MASK|AP_INTR_WENABLE) << BIF_INTR_GET_SH);
- BIF_OUT(BIF_INTR,(AP_INTR_MASK|AP_INTR_WENABLE) << BIF_INTR_HEADER_SH);
-}
-
-static void attn_enable(void)
-{
- BIF_OUT(BIF_INTR,AP_INTR_WENABLE << BIF_INTR_ATTN_SH);
-}
-
-static void attn_mask(void)
-{
- BIF_OUT(BIF_INTR,(AP_INTR_MASK|AP_INTR_WENABLE) << BIF_INTR_ATTN_SH);
-}
-
-
-void ap_bif_status(void)
-{
- static int bif_sdcsr;
- static int bif_intr;
- static int bif_mhocr;
- static int bif_x0sk;
- static int bif_xsk;
- static int bif_xsz;
- static int bif_y0sk;
- static int bif_ysk;
- static int bif_ysz;
- static int bif_cx0sk;
- static int bif_cxsk;
- static int bif_cxsz;
- static int bif_cy0sk;
- static int bif_cysk;
- static int bif_cysz;
- static int bif_ttl;
- static int bif_cttl;
- static int bif_header;
-
- bif_sdcsr = BIF_IN(BIF_SDCSR);
- bif_intr = BIF_IN(BIF_INTR);
- bif_mhocr = BIF_IN(BIF_MHOCR);
-
- bif_x0sk = BIF_IN(BIF_X0SK);
- bif_xsk = BIF_IN(BIF_XSK);
- bif_xsz = BIF_IN(BIF_XSZ);
- bif_y0sk = BIF_IN(BIF_Y0SK);
- bif_ysk = BIF_IN(BIF_YSK);
- bif_ysz = BIF_IN(BIF_YSZ);
-
- bif_cx0sk = BIF_IN(BIF_CX0SK);
- bif_cxsk = BIF_IN(BIF_CXSK);
- bif_cxsz = BIF_IN(BIF_CXSZ);
- bif_cy0sk = BIF_IN(BIF_CY0SK);
- bif_cysk = BIF_IN(BIF_CYSK);
- bif_cysz = BIF_IN(BIF_CYSZ);
-
- bif_ttl = BIF_IN(BIF_TTL);
- bif_cttl = BIF_IN(BIF_CTTL);
- bif_header = BIF_IN(BIF_HEADER);
-
- printk("|\t***** BIF REG. *****\n");
- printk("|\tBIF_SDCSR = %08x ", bif_sdcsr);
- if(bif_sdcsr & BIF_SDCSR_CN) printk("|<BUS DISCONNECT>");
- if(bif_sdcsr & BIF_SDCSR_FN) printk("|<SC/GA ENABLE>");
- if(bif_sdcsr & BIF_SDCSR_DE) printk("|<DMA ENABLE>");
- if(bif_sdcsr & BIF_SDCSR_DR) printk("|<GATHER>");
- if(bif_sdcsr & BIF_SDCSR_BB) printk("|<BUS BSY>");
- if(bif_sdcsr & BIF_SDCSR_BR) printk("|<BUS REQ>");
- if(bif_sdcsr & BIF_SDCSR_BG) printk("|<BUS GET>");
- if(bif_sdcsr & BIF_SDCSR_ER) printk("|<ERROR:");
- if(bif_sdcsr & BIF_SDCSR_SP) printk("|SYNC PARITY:");
- if(bif_sdcsr & BIF_SDCSR_LP) printk("|LBUS PARITY:");
- if(bif_sdcsr & BIF_SDCSR_LR) printk("|READ EMPTY FIFO:");
- if(bif_sdcsr & BIF_SDCSR_LW) printk("|WRITE FULL FIFO:");
- if(bif_sdcsr & BIF_SDCSR_AL) printk("|READ ENDBIT:");
- if(bif_sdcsr & BIF_SDCSR_SS) printk("|SET MASK SSTAT:");
- if(bif_sdcsr & BIF_SDCSR_SC) printk("|CLR SSYNC ILLEGALLY:");
- if(bif_sdcsr & BIF_SDCSR_SY) printk("|REQ SSYNC ILLEGALLY:");
- if(bif_sdcsr & BIF_SDCSR_FS) printk("|SET MASK FSTAT:");
- if(bif_sdcsr & BIF_SDCSR_FC) printk("|CLR FSYNC ILLEGALLY:");
- if(bif_sdcsr & BIF_SDCSR_FY) printk("|REQ FSYNC ILLEGALLY:");
- if(bif_sdcsr & BIF_SDCSR_CP) printk("|BNET PARITY:");
- if(bif_sdcsr & BIF_SDCSR_FP) printk("|FE NOT SET WHEN SC/GA:");
- if(bif_sdcsr & BIF_SDCSR_PS) printk("|RECV PACKET ILLEGALLY:");
- if(bif_sdcsr & BIF_SDCSR_RA) printk("|CHANGE FE ILLEGALLY:");
- if(bif_sdcsr & BIF_SDCSR_PA) printk("|SEND/RECV ILLEGALLY:");
- if(bif_sdcsr & BIF_SDCSR_DL) printk("|DATA LOST:");
- if(bif_sdcsr & BIF_SDCSR_ER) printk("|>");
- if(bif_sdcsr & BIF_SDCSR_PE) printk("|<SYNC PARITY ENABLE>");
- printk("|\n");
- printk("|\tBIF_INTR = %08x\n", bif_intr);
- printk("|\tBIF_MHOCR = %08x\n", bif_mhocr);
-
- printk("|\tBIF_X0SK = %08x\n", bif_x0sk);
- printk("|\tBIF_XSK = %08x\n", bif_xsk);
- printk("|\tBIF_XSZ = %08x\n", bif_xsz);
- printk("|\tBIF_Y0SK = %08x\n", bif_y0sk);
- printk("|\tBIF_YSK = %08x\n", bif_ysk);
- printk("|\tBIF_YSZ = %08x\n", bif_ysz);
- printk("|\tBIF_CX0SK = %08x\n", bif_cx0sk);
- printk("|\tBIF_CXSK = %08x\n", bif_cxsk);
- printk("|\tBIF_CXSZ = %08x\n", bif_cxsz);
- printk("|\tBIF_CY0SK = %08x\n", bif_cy0sk);
- printk("|\tBIF_CYSK = %08x\n", bif_cysk);
- printk("|\tBIF_CYSZ = %08x\n", bif_cysz);
-
- printk("|\tBIF_TTL = %08x\n", bif_ttl);
- printk("|\tBIF_CTTL = %08x\n", bif_cttl);
- printk("|\tBIF_HEADER = %08x\n", bif_header);
-}
-
-
-void bif_led_status(void)
-{
-#if 1
- static int i = 0;
- unsigned char res = 0;
-
- switch (i) {
- case 0:
- case 2:
- res = 0xff;
- break;
- case 1:
- case 3:
- res = 0;
- break;
- default:
- res = 0xFF & (BIF_IN(BIF_SDCSR) >> (((i-4)/4)*8));
- }
- i = (i+1) % 20;
-
- ap_led(res);
-#endif
-}
-
-static void get_bif(void)
-{
- if (HAVE_BIF())
- return;
-
- drop_ip_packets = 1;
-
- DEBUG(("|get_bif started\n"));
-
- if (dma_state != DMA_IDLE)
- ap_dma_wait(DMA_CH2);
-
-#if SNET_ARBITRATION
- /* wait till the host doesn't want the BIF anymore, tossing
- any data that arrives */
- while (BIF_IN(FSTT_CLR) & HOST_STATUS_BIT)
- if (BIF_IN(BIF_SDCSR) & BIF_SDCSR_RB)
- bif_intr_receive(NULL);
- waiting_for_bif = 0;
-#endif
-
-#if TOKEN_ARBITRATION
- BIF_OUT(FSTT_CLR,HOST_STATUS_BIT);
-#endif
-
- /* request the BIF */
- BIF_OUT(BIF_SDCSR,BIF_SDCSR_BR);
-
- /* loop waiting for us to get the BIF, tossing any data */
- while (!HAVE_BIF())
- if (BIF_IN(BIF_SDCSR) & BIF_SDCSR_RB)
- bif_intr_receive(NULL);
-
- bif_reset_interrupts();
- if (!interrupt_driven)
- bif_mask_interrupts();
-
- drop_ip_packets = 0;
-
-#if TOKEN_ARBITRATION
- BIF_OUT(FSTT_SET,HOST_STATUS_BIT);
-#endif
-
- DEBUG(("|get_bif done\n"));
-}
-
-
-/* write a message to the front end over the Bnet. This can be in
- multiple parts, as long as the first part sets "start" and the last
- part sets "end". The bus will be grabbed while this is going on
- */
-static void write_bif(char *buf,int size,int start,int end)
-{
- unsigned *ibuf;
- unsigned avail;
-
- DEBUG(("|write_bif %d %d %d\n",size,start,end));
-
- if (start) {
- /* a dma op may be in progress */
- if (dma_state != DMA_IDLE) ap_dma_wait(DMA_CH2);
- }
-
- size = (size+3) >> 2;
- ibuf = (unsigned *)buf;
- if (end) size--;
-
- while (size > 4) {
- while (!(avail=(BIF_IN(BIF_SDCSR) >> BIF_SDCSR_TB_SHIFT) & 7))
- ;
- if (avail & 4) {
- BIF_OUT(BIF_DATA,ibuf[0]);
- BIF_OUT(BIF_DATA,ibuf[1]);
- BIF_OUT(BIF_DATA,ibuf[2]);
- BIF_OUT(BIF_DATA,ibuf[3]);
- size -= 4; ibuf += 4;
- continue;
- }
-
- if (avail & 2) {
- BIF_OUT(BIF_DATA,ibuf[0]);
- BIF_OUT(BIF_DATA,ibuf[1]);
- size -= 2; ibuf += 2;
- continue;
- }
- BIF_OUT(BIF_DATA,ibuf[0]);
- ibuf++; size--;
- }
-
- while (size--) {
- while (!(BIF_IN(BIF_SDCSR) & BIF_SDCSR_TB)) ;
- BIF_OUT(BIF_DATA,ibuf[0]);
- ibuf++;
- }
-
- if (end) {
- while (!(BIF_IN(BIF_SDCSR) & BIF_SDCSR_TB)) ;
- BIF_OUT(BIF_EDATA,*ibuf);
- }
-
- DEBUG(("|write bif done\n"));
-}
-
-#if TOKEN_ARBITRATION
-static void forward_token(void)
-{
- struct cap_request req;
- req.cid = mpp_cid();
- req.type = REQ_BIF_TOKEN;
- req.size = sizeof(req);
- if (req.cid == cap_init.numcells - 1)
- req.header = MAKE_HEADER(HOST_CID);
- else
- req.header = MAKE_HEADER(req.cid + 1);
-
- write_bif((char *)&req,sizeof(req),1,1);
- have_token = 0;
-}
-#endif
-
-static void release_bif(void)
-{
- static int dummy[DUMMY_MSG_LEN];
-
- waiting_for_bif = 0;
-
-#if SNET_ARBITRATION
- /* mask the attention interrupt */
- attn_mask();
-#endif
-
- /* maybe we don't have it?? */
- if (!HAVE_BIF())
- return;
-
- DEBUG(("|release bif started\n"));
-
- if (dma_state != DMA_IDLE) ap_dma_wait(DMA_CH2);
-
-#if TOKEN_ARBITRATION
- if (have_token)
- forward_token();
-#endif
-
-#if 1
- /* send a dummy message to ensure FIFO flushing
- (suggestion from woods to overcome bif release
- hardware bug) */
- dummy[0] = 0xEEEE4000;
- write_bif((char *)dummy,DUMMY_MSG_LEN,1,1);
-#endif
- /* wait till the send FIFO is completely empty */
- while (!((BIF_IN(BIF_SDCSR) & BIF_SDCSR_TB) == BIF_SDCSR_TB)) ;
-
- /* wait another few us */
- udelay(DUMMY_MSG_WAIT);
-
- /* send release-data */
- BIF_OUT(BIF_DATA,BIF_HEADER_RS);
-
- /* wait until we don't have the bus */
- while (HAVE_BIF()) ;
-
- DEBUG(("|release bif done\n"));
-}
-
-
-/* wait for a particular request type - throwing away anything else! */
-void ap_wait_request(struct cap_request *req,int type)
-{
- drop_ip_packets = 1;
- do {
- while (!BIF_DATA_WAITING())
- if (HAVE_BIF()) release_bif();
- read_bif((char *)req,sizeof(*req));
- if (req->type != type) {
- bif_intr_receive(req);
- }
- } while (req->type != type);
- drop_ip_packets = 0;
-}
-
-
-void write_bif_polled(char *buf1,int len1,char *buf2,int len2)
-{
- unsigned flags;
- save_flags(flags); cli();
-
- get_bif();
- write_bif(buf1,len1,1,(buf2&&len2)?0:1);
- if (buf2 && len2)
- write_bif(buf2,len2,0,1);
- release_bif();
- restore_flags(flags);
-}
-
-static void want_bif(void)
-{
- unsigned flags;
-
- save_flags(flags); cli();
-
- /* maybe we've already got it */
- if (HAVE_BIF()) {
- waiting_for_bif = 0;
- restore_flags(flags);
- return;
- }
-
-#if SNET_ARBITRATION
- if (interrupt_driven)
- attn_enable();
-
- /* check if the host wants it */
- if (BIF_IN(FSTT_CLR) & HOST_STATUS_BIT) {
- /* the host wants it - don't get it yet */
- waiting_for_bif = 1;
- } else {
- /* the host doesn't want it - just set bus request */
- waiting_for_bif = 0;
- BIF_OUT(BIF_SDCSR,BIF_SDCSR_BR);
- while (!HAVE_BIF() && !BIF_BUSY()) ;
- DEBUG(("|set bif request\n"));
- }
- restore_flags(flags);
- return;
-#endif
-
-#if TOKEN_ARBITRATION
- if (net_started && !have_token) {
- BIF_OUT(FSTT_CLR,HOST_STATUS_BIT);
- restore_flags(flags);
- return;
- }
- BIF_OUT(FSTT_SET,HOST_STATUS_BIT);
-#endif
-
- BIF_OUT(BIF_SDCSR,BIF_SDCSR_BR);
- restore_flags(flags);
-}
-
-#define BIF_NOCOPY (1<<0)
-
-/* a queue of requests that need to be sent over the bif. Needs to be
-modified sometime to allow the direct queueing of skb's */
-struct bif_queue {
- volatile struct bif_queue *next;
- struct cap_request req;
- char *data;
- int data_size;
- int flags;
-};
-
-static volatile struct bif_queue *bif_queue_top = NULL;
-static volatile struct bif_queue *bif_queue_end = NULL;
-
-static struct sk_buff *skb_out = NULL;
-static struct sk_buff *skb_in = NULL;
-static char *bif_dma_data = NULL;
-static int bif_dma_out_size = 0;
-
-
-/* send waiting elements. Called mainly when we get a bif "bus get"
- interrupt to say we now have the bus */
-static void bif_intr_runqueue(void)
-{
- unsigned flags;
-
- /* if I don't have the bus then return */
- if (!HAVE_BIF())
- return;
-
- if (dma_state != DMA_IDLE) return;
-
- save_flags(flags); cli();
-
- while (bif_queue_top) {
- volatile struct bif_queue *q = bif_queue_top;
- bif_queue_top = q->next;
-
- /* printk("|queue run (length=%d)\n",queue_length); */
- queue_length--;
-
- if (!q->data) {
- /* use programmed IO for small requests */
- write_bif((char *)&q->req,sizeof(q->req),1,1);
- kfree_s((char *)q,sizeof(*q));
- continue;
- }
-
- if (q->flags & BIF_NOCOPY) {
- write_bif((char *)&q->req,sizeof(q->req),1,0);
- }
-
- if (use_dma && q->data_size > DMA_THRESHOLD) {
- dma_state = DMA_OUTGOING;
- if (q->req.type == REQ_IP) {
- skb_out = (struct sk_buff *)q->data;
- ap_dma_go(DMA_CH2,(unsigned)skb_out->data,
- q->data_size,DMA_DCMD_TD_MD);
- } else {
- if (!(q->flags & BIF_NOCOPY)) {
- bif_dma_data = q->data;
- bif_dma_out_size = q->data_size;
- }
- ap_dma_go(DMA_CH2,(unsigned)q->data,
- q->data_size,DMA_DCMD_TD_MD);
- }
- kfree_s((char *)q,sizeof(*q));
- restore_flags(flags);
- return; /* wait for DMA to complete */
- }
-
- if (q->req.type == REQ_IP) {
- struct sk_buff *skb = (struct sk_buff *)q->data;
- write_bif(skb->data,q->data_size,1,1);
- dev_kfree_skb(skb);
- } else {
- write_bif(q->data,q->data_size,1,1);
- if (!(q->flags & BIF_NOCOPY))
- kfree_s(q->data,q->data_size);
- }
- kfree_s((char *)q,sizeof(*q));
- }
-
- /* I don't want the bus now */
- release_bif();
- restore_flags(flags);
-}
-
-
-static void queue_attach(struct bif_queue *q)
-{
- unsigned flags;
- save_flags(flags); cli();
-
- /* attach it to the end of the queue */
- if (!bif_queue_top) {
- bif_queue_top = q;
- } else {
- bif_queue_end->next = q;
- }
- bif_queue_end = q;
-
- queue_length++;
-
- /* printk("|queue add (length=%d)\n",queue_length); */
-
- /* tell the bus we want access */
- want_bif();
-
- restore_flags(flags);
-}
-
-
-/* queue an element for sending over the bif. */
-int bif_queue(struct cap_request *req,char *buf,int bufsize)
-{
- struct bif_queue *q;
-
- if (req->header == 0)
- req->header = MAKE_HEADER(HOST_CID);
-
- /* if we aren't running interrupt driven then just send it
- immediately */
- if (!interrupt_driven) {
- write_bif_polled((char *)req,sizeof(*req),buf,bufsize);
- return(0);
- }
-
- /* allocate a queue element */
- q = (struct bif_queue *)kmalloc(sizeof(*q), GFP_ATOMIC);
- if (!q) {
- /* yikes! */
- return(-ENOMEM);
- }
-
- q->flags = 0;
- q->data = NULL;
- q->data_size = 0;
-
- if (buf && bufsize>0) {
- q->data_size = bufsize+sizeof(*req);
- q->data = (char *)kmalloc(q->data_size,GFP_ATOMIC);
- if (!q->data) {
- kfree_s(q,sizeof(*q));
- return(-ENOMEM);
- }
- }
-
- q->req = *req;
- if (buf&&bufsize) {
- memcpy(q->data,(char *)req,sizeof(*req));
- memcpy(q->data+sizeof(*req),buf,bufsize);
- }
- q->next = NULL;
-
- queue_attach(q);
-
- return(0);
-}
-
-
-/* queue an element for sending over the bif. */
-int bif_queue_nocopy(struct cap_request *req,char *buf,int bufsize)
-{
- struct bif_queue *q;
-
- if (req->header == 0)
- req->header = MAKE_HEADER(HOST_CID);
-
- /* allocate a queue element */
- q = (struct bif_queue *)kmalloc(sizeof(*q), GFP_ATOMIC);
- if (!q) {
- return(-ENOMEM);
- }
-
- q->data = buf;
- q->data_size = bufsize;
- q->flags = BIF_NOCOPY;
- q->req = *req;
- q->next = NULL;
-
- queue_attach(q);
-
- return(0);
-}
-
-
-/* put an IP packet into the bif queue */
-int bif_send_ip(int cid, struct sk_buff *skb)
-{
- struct cap_request *req = (struct cap_request *)skb->data;
- struct bif_queue *q;
- u_long destip;
-
- destip = *(u_long *)(skb->data+sizeof(*req)+16);
-
- if (cid != -1) {
- req->header = MAKE_HEADER(cid);
- } else if (destip == (cap_init.baseIP | ~cap_init.netmask)) {
- req->header = BIF_HEADER_IN | BIF_HEADER_BR;
- } else {
- req->header = MAKE_HEADER(HOST_CID);
- }
-
- /* allocate a queue element */
- q = (struct bif_queue *)kmalloc(sizeof(*q), GFP_ATOMIC);
- if (!q) {
- /* yikes! */
- dev_kfree_skb(skb);
- return(-ENOMEM);
- }
-
- req->size = ROUND4(skb->len);
- req->cid = mpp_cid();
- req->type = REQ_IP;
-
- q->data = (char *)skb;
- q->data_size = req->size;
- q->next = NULL;
- q->req = *req;
- q->flags = 0;
-
- queue_attach(q);
-
- return(0);
-}
-
-
-/* send an OPENNET request to tell the front end to open the apnet
- network interface */
-void start_apnet(void)
-{
- struct cap_request req;
- req.cid = mpp_cid();
- req.type = REQ_OPENNET;
- req.size = sizeof(req);
- req.header = MAKE_HEADER(HOST_CID);
-
- bif_queue(&req,NULL,0);
- printk("sent start_apnet request\n");
-}
-
-/* we have received an IP packet - pass it to the bif network
- interface code */
-static void reply_ip(struct cap_request *req)
-{
- if (drop_ip_packets ||
- !(skb_in = dev_alloc_skb(req->size - sizeof(*req)))) {
- bif_toss(req->size - sizeof(*req));
- return;
- }
-
- if (use_dma && req->size > DMA_THRESHOLD) {
- dma_state = DMA_INCOMING;
- ap_dma_go(DMA_CH2,
- (unsigned)skb_put(skb_in,req->size - sizeof(*req)),
- req->size - sizeof(*req),DMA_DCMD_TD_DM);
- } else {
- read_bif(skb_put(skb_in,req->size - sizeof(*req)),
- req->size - sizeof(*req));
- bif_rx(skb_in);
- skb_in = NULL;
- }
-}
-
-
-/* we have received a bread block - DMA it in */
-static void reply_bread(struct cap_request *req)
-{
- extern char *ap_buffer(struct cap_request *creq);
- char *buffer;
-
- buffer = ap_buffer(req);
- bread_req = *req;
-
- if (use_dma) {
- dma_state = DMA_INCOMING;
- ap_dma_go(DMA_CH2,
- (unsigned)buffer,req->size - sizeof(*req),
- DMA_DCMD_TD_DM);
- } else {
- read_bif(buffer,req->size - sizeof(*req));
- ap_complete(&bread_req);
- bread_req.type = -1;
- }
-}
-
-
-static struct debug_key {
- struct debug_key *next;
- char key;
- void (*fn)(void);
- char *description;
-} *debug_keys = NULL;
-
-
-void show_debug_keys(void)
-{
- struct debug_key *r;
- for (r=debug_keys;r;r=r->next)
- printk("%c: %s\n",r->key,r->description);
-}
-
-
-void bif_add_debug_key(char key,void (*fn)(void),char *description)
-{
- struct debug_key *r,*r2;
- r = (struct debug_key *)kmalloc(sizeof(*r),GFP_ATOMIC);
- if (r) {
- r->next = NULL;
- r->key = key;
- r->fn = fn;
- r->description = description;
- if (!debug_keys) {
- debug_keys = r;
- } else {
- for (r2=debug_keys;
- r2->next && r2->key != key;r2=r2->next) ;
-
- if (r2->key == key) {
- r2->fn = fn;
- r2->description = description;
- kfree_s(r,sizeof(*r));
- } else {
- r2->next = r;
- }
- }
- }
-}
-
-/* these are very useful for debugging ! */
-static void reply_putchar(struct cap_request *req)
-{
- struct debug_key *r;
-
- char c = req->data[0];
-
- ap_set_user(req->data[1]);
-
- for (r=debug_keys;r;r=r->next)
- if (r->key == c) {
- r->fn();
- break;
- }
- if (!r)
- printk("cell %d got character %d [%c]\n",mpp_cid(),(int)c,c);
-
- ap_set_user(-1);
-}
-
-
-/* send a signal to a task by name or pid */
-static void reply_kill(struct cap_request *req)
-{
- int sig = req->data[0];
- struct task_struct *p;
- int len;
- char name[32];
-
- len = req->size - sizeof(*req);
- if (len == 0) {
- int pid = req->data[1];
- p = find_task_by_pid(pid);
-
- if(p)
- send_sig(sig, p, 1);
- else
- printk("cell %d: no task with pid %d\n",mpp_cid(),pid);
- return;
- }
-
- if (len > sizeof(name)-1) {
- bif_toss(len);
- return;
- }
-
- read_bif(name,len);
- name[len] = 0;
-
- read_lock(&tasklist_lock);
- for_each_task(p)
- if (strcmp(name,p->comm) == 0)
- send_sig(sig,p,1);
- read_unlock(&tasklist_lock);
-}
-
-
-static struct req_list {
- struct req_list *next;
- int type;
- void (*fn)(struct cap_request *);
-} *reg_req_list = NULL;
-
-
-void bif_register_request(int type,void (*fn)(struct cap_request *))
-{
- struct req_list *r,*r2;
- r = (struct req_list *)kmalloc(sizeof(*r),GFP_ATOMIC);
- if (r) {
- r->next = NULL;
- r->type = type;
- r->fn = fn;
- if (!reg_req_list) {
- reg_req_list = r;
- } else {
- for (r2=reg_req_list;
- r2->next && r2->type != type;r2=r2->next) ;
-
- if (r2->type == type) {
- r2->fn = fn;
- kfree_s(r,sizeof(*r));
- } else {
- r2->next = r;
- }
- }
- }
-}
-
-
-
-/* a request has come in on the bif - process it */
-static void bif_intr_receive(struct cap_request *req1)
-{
- struct req_list *r;
- extern void ap_open_reply(struct cap_request *creq);
- struct cap_request req;
-
- if (req1) {
- req = *req1;
- } else {
- /* read the main cap request header */
- read_bif((char *)&req,sizeof(req));
- }
-
- /* service it */
- switch (req.type)
- {
- case REQ_PUTCHAR:
- reply_putchar(&req);
- break;
- case REQ_KILL:
- reply_kill(&req);
- break;
- case REQ_BREAK:
- breakpoint();
- break;
- case REQ_IP:
- reply_ip(&req);
- break;
-#if TOKEN_ARBITRATION
- case REQ_BIF_TOKEN:
- have_token = 1;
- want_bif();
- break;
-#endif
- case REQ_OPENNET:
- net_started = 1;
- break;
- case REQ_BREAD:
- reply_bread(&req);
- break;
- case REQ_BOPEN:
- ap_open_reply(&req);
- break;
- case REQ_BWRITE:
- ap_complete(&req);
- break;
- case REQ_SCHEDULE:
- mpp_schedule(&req);
- break;
-
- default:
- for (r=reg_req_list;r;r=r->next)
- if (r->type == req.type) {
- r->fn(&req);
- return;
- }
- printk("Unknown request %d\n",req.type);
- break;
- }
-}
-
-
-static void bif_dma_complete(void)
-{
- extern int bif_rx(struct sk_buff *skb);
- enum dma_state old_state = dma_state;
- unsigned a;
-
- a = DMA_IN(DMA2_DMST);
-
- if (a & DMA_DMST_AC) return;
-
- DMA_OUT(DMA2_DMST,AP_CLR_INTR_REQ<<DMA_INTR_NORMAL_SH);
- DMA_OUT(DMA2_DMST,AP_CLR_INTR_REQ<<DMA_INTR_ERROR_SH);
-
- if (old_state == DMA_INCOMING) {
- if (skb_in) bif_rx(skb_in);
- skb_in = NULL;
- }
- if (bread_req.type != -1) {
- ap_complete(&bread_req);
- bread_req.type = -1;
- }
-
- if (bif_dma_data) {
- kfree_s(bif_dma_data,bif_dma_out_size);
- bif_dma_data = NULL;
- }
-
- if (skb_out) {
- dev_kfree_skb(skb_out);
- skb_out = NULL;
- }
-
- dma_state = DMA_IDLE;
-
- if (a & (AP_INTR_REQ<<DMA_INTR_ERROR_SH)) {
- printk("BIF: got dma error\n");
- }
-}
-
-
-/* handle bif related interrupts. Currently handles 3 interrupts, the
- bif header interrupt, the bif get interrupt and the dma transfer
- complete interrupt */
-static void bif_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned flags;
-
- bif_pt_regs = regs;
-
- save_flags(flags); cli();
-
- mac_dma_complete();
-
- if (dma_state != DMA_IDLE) {
- bif_dma_complete();
- }
-
- bif_reset_interrupts();
-
- while (dma_state == DMA_IDLE && BIF_DATA_WAITING()) {
- bif_intr_receive(NULL);
- }
-
- if (dma_state != DMA_IDLE) {
- bif_dma_complete();
- }
-
- if (dma_state == DMA_IDLE && bif_queue_top && !HAVE_BIF()) {
- want_bif();
- }
-
- if (dma_state == DMA_IDLE && HAVE_BIF()) {
- waiting_for_bif = 0;
- bif_intr_runqueue();
- }
-
- if (dma_state == DMA_IDLE && HAVE_BIF()) {
- release_bif();
- }
-
- restore_flags(flags);
- bif_pt_regs = NULL;
-}
-
-
-/* handle the attention interrupt - used for BIF arbitration */
-static void attn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned flags;
-
- save_flags(flags); cli();
-
- attn_enable();
-
-#if SNET_ARBITRATION
- attn_mask();
- DEBUG(("|bif attn irq %d\n",irq));
-
- if (waiting_for_bif)
- want_bif();
-
- DEBUG(("|bif attn irq %d done\n",irq));
-#endif
-
- bif_interrupt(irq,dev_id,regs);
- restore_flags(flags);
-}
-
-
-void bif_timer(void)
-{
-#if 1
- if (interrupt_driven)
- bif_interrupt(0,NULL,NULL);
-#endif
-}
-
-static void tnet_ip_enable(void)
-{
- tnet_ip_enabled = 1;
- printk("tnet_ip_enabled=%d\n",tnet_ip_enabled);
-}
-
-static void tnet_ip_disable(void)
-{
- tnet_ip_enabled = 0;
- printk("tnet_ip_enabled=%d\n",tnet_ip_enabled);
-}
-
-/* initialise the bif code */
-void ap_bif_init(void)
-{
- int res;
- unsigned long flags;
- printk("doing ap_bif_init()\n");
-
- bif_add_debug_key('+',tnet_ip_enable,"enable Tnet based IP");
- bif_add_debug_key('-',tnet_ip_disable,"disable Tnet based IP");
-
- save_flags(flags); cli();
-
- /* register the BIF interrupt */
- if ((res=request_irq(APBIF_IRQ, bif_interrupt,
- SA_INTERRUPT, "apbif", NULL))) {
- printk("Failed to install bif interrupt handler\n");
- restore_flags(flags);
- return;
- }
-
- /* and the bus get interrupt */
- if ((res=request_irq(APBIFGET_IRQ, bif_interrupt,
- SA_INTERRUPT, "apbifget", NULL))) {
- printk("Failed to install bifget interrupt handler\n");
- restore_flags(flags);
- return;
- }
-
- /* dma complete interrupt */
- if ((res=request_irq(APDMA_IRQ, bif_interrupt, SA_INTERRUPT,
- "apdma", NULL))) {
- printk("Failed to install bifdma interrupt handler\n");
- restore_flags(flags);
- return;
- }
-
- /* attention interrupt */
- if ((res=request_irq(APATTN_IRQ, attn_interrupt, SA_INTERRUPT,
- "apattn", NULL))) {
- printk("Failed to install apattn interrupt handler\n");
- restore_flags(flags);
- return;
- }
-
- printk("Installed bif handlers\n");
-
- /* enable dma-request */
- BIF_OUT(BIF_SDCSR,BIF_SDCSR_DE);
-
- DMA_OUT(DMA2_DCMD,DMA_DCMD_SA);
- DMA_OUT(DMA2_DMST,DMA_DMST_RST);
- DMA_OUT(DMA2_DMST,AP_CLR_INTR_REQ<<DMA_INTR_NORMAL_SH);
- DMA_OUT(DMA2_DMST,AP_CLR_INTR_MASK<<DMA_INTR_NORMAL_SH);
- DMA_OUT(DMA2_DMST,AP_CLR_INTR_REQ<<DMA_INTR_ERROR_SH);
- DMA_OUT(DMA2_DMST,AP_CLR_INTR_MASK<<DMA_INTR_ERROR_SH);
-
- /* enable the attention interrupt */
- attn_enable();
-
- DMA_OUT(DMA_BIF_BCMD,DMA_BCMD_SA);
- DMA_OUT(DMA_BIF_BRST,DMA_DMST_RST);
-
- /* from now on we are interrupt driven */
- bread_req.type = -1;
- dma_state = DMA_IDLE;
- interrupt_driven = 1;
- use_dma = 1;
- bif_reset_interrupts();
-
- /* if theres something in the queue then we also want the bus */
- if (bif_queue_top)
- want_bif();
-
- /* tell the host that networking is now OK */
- start_apnet();
-
- printk("bif initialised\n");
-
- restore_flags(flags);
-}
-
-
diff --git a/arch/sparc/ap1000/dma.c b/arch/sparc/ap1000/dma.c
deleted file mode 100644
index e445b7fdd..000000000
--- a/arch/sparc/ap1000/dma.c
+++ /dev/null
@@ -1,74 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/* dma routines for the AP1000 */
-#include <asm/ap1000/apservice.h>
-#include <asm/ap1000/apreg.h>
-#include <linux/mm.h>
-#include <linux/malloc.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-
-#define DMA_MAX_TRANS_SIZE2 (0xfffffc)
-
-int ap_dma_wait(int ch)
-{
- int i = 0;
- while (DMA_IN(ch+DMA_DMST) & DMA_DMST_AC) i++;
- return i;
-}
-
-/* send some data out a dma channel */
-int ap_dma_go(unsigned long ch,unsigned int p,int size,unsigned long cmd)
-{
- int rest;
-
- p = mmu_v2p(p);
-
- cmd |= DMA_DCMD_ST | DMA_DCMD_TYP_AUTO;
-
-#if 0
- if (ap_dma_wait(ch)) {
- printk("WARNING: dma started when not complete\n");
- }
-
- if (cmd == DMA_DCMD_TD_MD && !(BIF_IN(BIF_SDCSR) & BIF_SDCSR_BG)) {
- ap_led(0xAA);
- printk("attempt to dma without holding the bus\n");
- return -1;
- }
-#endif
-
- /* reset the dma system */
- DMA_OUT(ch + DMA_DMST,DMA_DMST_RST);
-
- if (size <= DMA_MAX_TRANS_SIZE) {
- DMA_OUT(ch + DMA_MADDR,(unsigned long)p);
- DMA_OUT(ch + DMA_HSKIP,1);
- DMA_OUT(ch + DMA_VSKIP,1);
- DMA_OUT(ch + DMA_DCMD,cmd | B2W(size));
- return 0;
- }
-
- if (size <= DMA_MAX_TRANS_SIZE2) {
- if(size & 0x3) size += 4;
- rest = (size & (DMA_TRANS_BLOCK_SIZE - 1)) >> 2;
- if (rest) {
- DMA_OUT(ch + DMA_HDRP,(unsigned)p);
- p += rest << 2;
- }
- DMA_OUT(ch + DMA_MADDR,(unsigned)p);
- DMA_OUT(ch + DMA_HSKIP,size >> (2 + 6));
- DMA_OUT(ch + DMA_VSKIP,1);
- DMA_OUT(ch + DMA_DCMD,cmd | (rest << 16) | 64);
- return 0;
- }
-
- printk("AP1000 DMA operation too big (%d bytes) - aborting\n",size);
- return(-1);
-}
-
diff --git a/arch/sparc/ap1000/hw.c b/arch/sparc/ap1000/hw.c
deleted file mode 100644
index aabe15a3b..000000000
--- a/arch/sparc/ap1000/hw.c
+++ /dev/null
@@ -1,200 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * Initialize the AP1000 hardware: BIF, MSC+, MC+, etc.
- */
-
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/malloc.h>
-#include <linux/mpp.h>
-#include <asm/irq.h>
-#include <asm/ap1000/apservice.h>
-#include <asm/ap1000/apreg.h>
-
-#define APLOG 0
-
-/* these make using CellOS code easier */
-int cap_nopt0;
-int cap_cid0;
-int cap_ncel0;
-
-unsigned _cid, _ncel, _ncelx, _ncely, _cidx, _cidy;
-
-/* yuck - needed for sun4c! */
-static unsigned char dummy;
-unsigned char *auxio_register = &dummy;
-
-
-extern struct cap_init cap_init;
-
-static void unexpected_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
- ap_panic("** unexpected interrupt %d **\n",irq);
-}
-
-static void ap_other_irqs(void)
-{
- request_irq(3, unexpected_irq, SA_INTERRUPT, "unused", 0);
- request_irq(5, unexpected_irq, SA_INTERRUPT, "unused", 0);
- request_irq(12, unexpected_irq, SA_INTERRUPT, "unused", 0);
- request_irq(15, unexpected_irq, SA_INTERRUPT, "unused", 0);
-}
-
-int ap_memory_size(void)
-{
- if ((MSC_IN(MSC_SIMMCHK) & MSC_SIMMCHK_MASK) == 0) {
- return 16*1024*1024;
- }
- return 64*1024*1024;
-}
-
-static void show_registers(void)
-{
- extern struct pt_regs *bif_pt_regs;
- if (bif_pt_regs)
- show_regs(bif_pt_regs);
- else
- printk("unable to show registers\n");
-}
-
-
-static void check_alive(void)
-{
- printk("Cell %d is alive\n",mpp_cid());
-}
-
-
-
-static void show_task(struct task_struct *t)
-{
- printk("cell=%3d uid=%5d pid=%5d utime=%3d stime=%3d etime=%3d name=%s\n",
- mpp_cid(),
- t->uid,
- (int)t->pid,
- (int)t->utime,
- (int)t->stime,
- (jiffies - (int)t->start_time) / 100,
- t->comm);
-}
-
-static void show_ptasks(void)
-{
- extern struct task_struct *task[];
- struct task_struct *p;
- int i;
- int count=0;
-
- read_lock(&tasklist_lock);
- for_each_task(p) {
- struct task_struct **tp = p->tarray_ptr;
-
- if(tp >= &task[MPP_TASK_BASE]) {
- show_task(p);
- count++;
- }
- }
- read_unlock(&tasklist_lock);
-
- if (count == 0)
- printk("no parallel tasks on cell %d\n",mpp_cid());
-}
-
-static void show_utasks(void)
-{
- extern struct task_struct *task[];
- struct task_struct *p;
- int i;
- int count=0;
-
- read_lock(&tasklist_lock);
- for_each_task(p) {
- if(p->uid > 1) {
- show_task(task[i]);
- count++;
- }
- }
- read_unlock(&tasklist_lock);
-
- if (count == 0)
- printk("no user tasks on cell %d\n",mpp_cid());
-}
-
-
-static void show_otasks(void)
-{
- extern struct task_struct *task[];
- struct task_struct *p;
- int i;
- int count=0;
- extern int ap_current_uid;
-
- read_lock(&tasklist_lock);
- for_each_task(p) {
- if(p->uid == ap_current_uid) {
- show_task(task[i]);
- count++;
- }
- }
- read_unlock(&tasklist_lock);
-
- if (count == 0)
- printk("no tasks on cell %d\n",mpp_cid());
-}
-
-
-void do_panic(void)
-{
- int *x = 0;
- *x = 1; /* uggh */
-}
-
-
-void mpp_hw_init(void)
-{
- extern void show_state(void);
- extern void breakpoint(void);
- extern void ctrl_alt_del(void);
- extern void mac_print_state(void);
- extern void show_debug_keys(void);
-
- bif_add_debug_key('c',check_alive,"check if a cell is alive");
- bif_add_debug_key('k',show_debug_keys,"show the kernel debug keys");
- bif_add_debug_key('p',show_registers,"show register info");
- bif_add_debug_key('p',show_registers,"show register info");
- bif_add_debug_key('m',show_mem,"detailed memory stats");
- bif_add_debug_key('s',show_state,"detailed process stats");
- bif_add_debug_key('D',ap_start_debugger,"launch the kernel debugger");
- bif_add_debug_key('i',breakpoint,"send a breakpoint");
- bif_add_debug_key('r',ctrl_alt_del,"run shutdown (doesn't work)");
- bif_add_debug_key('P',show_ptasks,"show running parallel tasks");
- bif_add_debug_key('U',show_utasks,"show all user tasks");
- bif_add_debug_key('O',show_otasks,"show own user tasks");
- bif_add_debug_key('^',do_panic,"panic :-)");
-
-
- cap_cid0 = BIF_IN(BIF_CIDR1);
- cap_ncel0 = cap_init.numcells;
-
- _cid = cap_cid0;
- _ncel = cap_ncel0;
- _ncelx = _ncel<8?_ncel:8;
- _ncely = ((_ncel-1) / _ncelx) + 1;
- _cidx = _cid % _ncelx;
- _cidy = _cid / _ncelx;
-
- ap_bif_init();
- ap_msc_init();
- ap_tnet_init();
- ap_profile_init();
- ap_other_irqs();
- ap_ringbuf_init();
-#if APLOG
- ap_log(NULL,-1);
-#endif
-}
diff --git a/arch/sparc/ap1000/irq.c b/arch/sparc/ap1000/irq.c
deleted file mode 100644
index d329faf3a..000000000
--- a/arch/sparc/ap1000/irq.c
+++ /dev/null
@@ -1,64 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/linkage.h>
-#include <linux/kernel_stat.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <linux/malloc.h>
-
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/psr.h>
-#include <asm/vaddrs.h>
-#include <asm/timer.h>
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/traps.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/ap1000/apreg.h>
-
-extern void ap_clear_clock_irq(void);
-extern void ap_init_timers(void);
-
-static void ap_enable_irq(unsigned int irq_nr)
-{
- /* printk("ENABLE IRQ %d IGNORED\n",irq_nr); */
-}
-
-static void ap_disable_irq(unsigned int irq_nr)
-{
- printk("DISABLE IRQ %d IGNORED\n",irq_nr);
-}
-
-static void ap_clear_profile_irq(void)
-{
- MC_OUT(MC_INTR,AP_CLR_INTR_REQ << MC_INTR_ITIM0_SH);
-}
-
-static void ap_load_profile_irq(unsigned limit)
-{
- MC_OUT(MC_ITIMER0,limit);
-}
-
-void ap_init_IRQ(void)
-{
- enable_irq = ap_enable_irq;
- disable_irq = ap_disable_irq;
- clear_clock_irq = ap_clear_clock_irq;
- clear_profile_irq = ap_clear_profile_irq;
- load_profile_irq = ap_load_profile_irq;
- init_timers = ap_init_timers;
-
- sti(); /* the sun4m code does this, so we do too */
-}
diff --git a/arch/sparc/ap1000/kgdb.c b/arch/sparc/ap1000/kgdb.c
deleted file mode 100644
index fa6c65ecd..000000000
--- a/arch/sparc/ap1000/kgdb.c
+++ /dev/null
@@ -1,78 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/* routines to support remote kgdb to Linux/AP+ cells */
-
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/malloc.h>
-#include <asm/ap1000/apservice.h>
-#include <asm/ap1000/apreg.h>
-
-static char out_buf[0x100];
-static int out_buf_pos = 0;
-
-static char in_buf[0x100];
-static int in_buf_pos = 0;
-static int in_buf_count = 0;
-
-static int hash_pos = -1;
-
-void ap_dbg_flush(void)
-{
- struct cap_request req;
-
- if (out_buf_pos == 0) return;
-
- req.cid = mpp_cid();
- req.type = REQ_PUTDEBUGSTRING;
- req.size = sizeof(req) + out_buf_pos;
- req.header = MAKE_HEADER(HOST_CID);
-
- write_bif_polled((char *)&req,sizeof(req),(char *)out_buf,out_buf_pos);
-
- out_buf_pos = 0;
- hash_pos = -1;
-}
-
-/* called by the gdb stuff */
-void putDebugChar(char c)
-{
- if (c == '#') hash_pos = out_buf_pos;
-
- out_buf[out_buf_pos++] = c;
- if (out_buf_pos == sizeof(out_buf)) {
- ap_dbg_flush();
- }
-}
-
-/* used by gdb to get input */
-char getDebugChar(void)
-{
- unsigned flags;
- struct cap_request req;
-
- ap_dbg_flush();
-
- if (in_buf_count == 0) {
- req.cid = mpp_cid();
- req.type = REQ_GETDEBUGCHAR;
- req.size = sizeof(req);
- req.header = MAKE_HEADER(HOST_CID);
-
- save_flags(flags); cli();
- write_bif_polled((char *)&req,sizeof(req),NULL,0);
- ap_wait_request(&req,REQ_GETDEBUGCHAR);
- read_bif(in_buf,req.size - sizeof(req));
- in_buf_pos = 0;
- in_buf_count = req.size - sizeof(req);
- restore_flags(flags);
- }
-
- in_buf_count--;
- return(in_buf[in_buf_pos++]);
-}
diff --git a/arch/sparc/ap1000/mpp.c b/arch/sparc/ap1000/mpp.c
deleted file mode 100644
index 1e6596a07..000000000
--- a/arch/sparc/ap1000/mpp.c
+++ /dev/null
@@ -1,83 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * simple mpp functions for the AP+
- */
-
-#include <asm/ap1000/apreg.h>
-#include <asm/ap1000/apservice.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <asm/pgtable.h>
-
-extern int cap_cid0;
-extern int cap_ncel0;
-extern struct cap_init cap_init;
-
-static volatile int mpp_current_task = 0;
-static int gang_factor = DEF_GANG_FACTOR;
-static int last_task = 0;
-
-
-void mpp_schedule(struct cap_request *req)
-{
- mpp_current_task = req->data[0];
- current->need_resched = 1;
- mark_bh(TQUEUE_BH);
-}
-
-
-void mpp_notify_schedule(struct task_struct *tsk)
-{
- last_task = tsk->taskid;
-
- msc_switch_check(tsk);
-
- if (gang_factor == 0) return;
-
- if (cap_cid0 == cap_init.bootcid &&
- mpp_current_task != tsk->taskid) {
- struct cap_request req;
-
- mpp_current_task = tsk->taskid;
-
- req.cid = mpp_cid();
- req.type = REQ_SCHEDULE;
- req.size = sizeof(req);
- req.header = MAKE_HEADER(-1);
- req.data[0] = mpp_current_task;
-
- bif_queue(&req,NULL,0);
- }
-}
-
-
-int mpp_weight(struct task_struct *tsk)
-{
- extern int block_parallel_tasks;
-
- if (!MPP_IS_PAR_TASK(tsk->taskid)) return 0;
-
- if (block_parallel_tasks) return -1000;
-
- /* XXX task[] fixme */
- if (last_task && last_task != tsk->taskid && task[last_task] &&
- !msc_switch_ok()) return -1000;
-
- if (cap_cid0 != cap_init.bootcid &&
- tsk->taskid != mpp_current_task) {
- return -gang_factor;
- }
- return 0;
-}
-
-void mpp_set_gang_factor(int factor)
-{
- gang_factor = factor;
-}
diff --git a/arch/sparc/ap1000/msc.c b/arch/sparc/ap1000/msc.c
deleted file mode 100644
index 088df765c..000000000
--- a/arch/sparc/ap1000/msc.c
+++ /dev/null
@@ -1,1262 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * Routines to control the AP1000+ Message Controller (MSC+)
- * and Memory Controller (MC+).
- *
- */
-#define _APLIB_
-#include <asm/ap1000/apreg.h>
-#include <linux/mm.h>
-#include <linux/malloc.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/ap1000/pgtapmmu.h>
-#include <linux/threads.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-
-static void msc_interrupt_9(int irq, void *dev_id, struct pt_regs *regs);
-static void msc_interrupt_11(int irq, void *dev_id, struct pt_regs *regs);
-static void msc_set_ringbuf(int context);
-static void msc_update_read_ptr(int context,int overflow);
-static void fail_write(int context,int intr,unsigned vaddr);
-static void fail_read(int context,int intr,unsigned vaddr);
-static void msc_switch_from_check(struct task_struct *tsk);
-static void msc_status(void);
-
-#define DEBUG 0
-
-/*
- * This describes how the 5 queues for outgoing requests
- * are mapped into the 256 words of send queue RAM in the MSC+.
- */
-#define NSENDQUEUES 5
-
-static struct send_queues {
- int base; /* must be a multiple of size */
- int size; /* must be 32 or 64 */
-} send_queues[NSENDQUEUES] = {
- {0, 64}, /* System put/send requests */
- {192, 32}, /* Remote read/write requests */
- {64, 64}, /* User put/send requests */
- {224, 32}, /* Remote read replies */
- {128, 64}, /* Get replies */
-};
-
-#define NR_RBUFS MSC_NR_RBUFS
-
-static struct {
- unsigned rbmbwp;
- unsigned rbmmode;
- unsigned rbmrp;
-} ringbufs[MSC_NR_RBUFS] = {
- {MSC_RBMBWP0, MSC_RBMMODE0, MSC_RBMRP0},
- {MSC_RBMBWP1, MSC_RBMMODE1, MSC_RBMRP1},
- {MSC_RBMBWP2, MSC_RBMMODE2, MSC_RBMRP2},
-};
-
-#define CTX_MASK 0xfff
-#define NULL_CONTEXT CTX_MASK
-
-#define QOF_ORDER 3 /* 32kB queue overflow buffer */
-#define QOF_SIZE ((1<<QOF_ORDER)*PAGE_SIZE)
-#define QOF_ELT_SIZE 8 /* size of each queue element */
-#define QOF_REDZONE_SZ 8192 /* 8kB redzone, imposed by hardware */
-#define QOF_NELT (QOF_SIZE / QOF_ELT_SIZE)
-#define QOF_RED_NELT (QOF_REDZONE_SZ / QOF_ELT_SIZE)
-#define QOF_GREEN_NELT ((QOF_SIZE - QOF_REDZONE_SZ) / QOF_ELT_SIZE)
-
-#define MAKE_QBMPTR(qof, size) \
- (MKFIELD((qof) >> 19, MSC_QBMP_BP) \
- + MKFIELD((qof) >> 3, MSC_QBMP_WP) \
- + MKFIELD(((qof) + (size) - 1) >> 13, MSC_QBMP_LIM))
-
-#define QBM_UPDATE_WP(wp) \
- MSC_OUT(MSC_QBMPTR, INSFIELD(MSC_IN(MSC_QBMPTR), (unsigned)(wp) >> 3, \
- MSC_QBMP_WP))
-
-/* Send queue overflow buffer structure */
-struct qof_elt {
- unsigned info;
- unsigned data;
-};
-
-/* Fields in qof_elt.info */
-#define QOF_QUEUE_SH 24 /* queue bits start at bit 24 */
-#define QOF_QUEUE_M 0x1f /* 5 bits wide */
-#define QOF_ENDBIT 1 /* end bit in bit 0 */
-
-static struct qof_elt *qof_base=NULL; /* start of overflow buffer */
-static unsigned long qof_phys; /* physical start adrs of overflow buffer */
-static struct qof_elt *qof_rp; /* read pointer for refills */
-static struct qof_elt *qof_new; /* first element we haven't yet looked at */
-static int qof_present[NSENDQUEUES];/* # elts for each q in [qof_rp,qof_new) */
-
-/* this is used to flag when the msc is blocked, so we can't send
- messages on it without the possability of deadlock */
-int msc_blocked = 0;
-int block_parallel_tasks = 0;
-
-static int qbm_full_counter = 0;
-
-#define INTR_LIMIT 10000
-static int intr_counter = 0;
-static unsigned intr_mask;
-
-#define DUMMY_RINGBUF_ORDER 5
-#define DUMMY_RINGBUF_SIZE ((1<<DUMMY_RINGBUF_ORDER)*PAGE_SIZE)
-
-/*
- * The system ring buffer, used for inter-kernel comms
- */
-struct ringbuf_struct system_ringbuf = {NULL,NULL,SYSTEM_RINGBUF_ORDER,0,0,0,0};
-struct ringbuf_struct dummy_ringbuf = {NULL,NULL,DUMMY_RINGBUF_ORDER,0,0,0,0};
-unsigned system_read_ptr = (SYSTEM_RINGBUF_SIZE>>5)-1;
-unsigned dummy_read_ptr = (DUMMY_RINGBUF_SIZE>>5)-1;
-
-#define SQ_NEW_MODE(mode) do { \
- MSC_OUT(MSC_SQCTRL, ((MSC_IN(MSC_SQCTRL) & ~MSC_SQC_RMODE) \
- | MSC_SQC_RMODE_ ## mode)); \
- while ((MSC_IN(MSC_SQCTRL) & MSC_SQC_MODE) != MSC_SQC_MODE_ ## mode) \
- /* hang */ ; \
-} while (0)
-
-/* Repack the queue overflow buffer if >= this many already-used entries */
-#define REPACK_THRESH 64
-
-
-static void refill_sq(void);
-static void repack_qof(void);
-static void shuffle_qof(void);
-static void async_callback(int, unsigned long, int, int);
-
-
-static void mask_all_interrupts(void)
-{
- /* disable all MSC+ interrupts */
- MSC_OUT(MSC_INTR,
- (AP_SET_INTR_MASK << MSC_INTR_QBMFUL_SH) |
- (AP_SET_INTR_MASK << MSC_INTR_SQFILL_SH) |
- (AP_SET_INTR_MASK << MSC_INTR_RBMISS_SH) |
- (AP_SET_INTR_MASK << MSC_INTR_RBFULL_SH) |
- (AP_SET_INTR_MASK << MSC_INTR_RMASF_SH) |
- (AP_SET_INTR_MASK << MSC_INTR_RMASE_SH) |
- (AP_SET_INTR_MASK << MSC_INTR_SMASF_SH) |
- (AP_SET_INTR_MASK << MSC_INTR_SMASE_SH));
-}
-
-static inline int valid_task(struct task_struct *tsk)
-{
- return(tsk &&
- !((tsk)->flags & PF_EXITING) &&
- tsk->mm &&
- tsk->mm->context != NO_CONTEXT);
-}
-
-static inline unsigned long apmmu_get_raw_ctable_ptr(void)
-{
- unsigned int retval;
-
- __asm__ __volatile__("lda [%1] %2, %0\n\t" :
- "=r" (retval) :
- "r" (APMMU_CTXTBL_PTR),
- "i" (ASI_M_MMUREGS));
- return (retval);
-}
-
-static void mc_tlb_map(unsigned phys_page,unsigned vpage,int context)
-{
- unsigned long long *tlb4k;
- unsigned long long new_entry;
- unsigned long *new_entryp = (unsigned long *)&new_entry;
- tlb4k = ((unsigned long long *)MC_MMU_TLB4K) + (vpage & 0xFF);
- new_entryp[0] = (phys_page&~7) >> 3;
- new_entryp[1] = ((phys_page & 7) << 29) | (((vpage>>8)&0xFFF) << 17) |
- (context << 5) | 0x13;
- tlb4k[0] = new_entry;
-#if DEBUG
- printk("mc_tlb_map(%x,%x,%x) %x %x at %x\n",
- phys_page,vpage,context,new_entryp[0],new_entryp[1],tlb4k);
-#endif
-}
-
-static void mc_tlb_unmap(unsigned vpage)
-{
- unsigned long long *tlb4k = (unsigned long long *)MC_MMU_TLB4K;
- tlb4k = ((unsigned long long *)MC_MMU_TLB4K) + (vpage & 0xFF);
- tlb4k[0] = 0;
-}
-
-void mc_tlb_init(void)
-{
- unsigned long long *tlb256k, *tlb4k;
- int i;
-
- tlb4k = (unsigned long long *)MC_MMU_TLB4K;
- for (i = MC_MMU_TLB4K_SIZE; i > 0; --i)
- *tlb4k++ = 0;
- tlb256k = (unsigned long long *)MC_MMU_TLB256K;
- for (i = MC_MMU_TLB256K_SIZE; i > 0; --i)
- *tlb256k++ = 0;
-}
-
-void ap_msc_init(void)
-{
- int i, flags, res;
- unsigned int qp;
-
- bif_add_debug_key('M',msc_status,"MSC+ status");
-
-#if DEBUG
- printk("MSC+ version %x\n", MSC_IN(MSC_VERSION));
- printk("MC+ version %x\n", MC_IN(MC_VERSION));
-#endif
-
- mc_tlb_init();
-
- /* Set the MC's copy of the context table pointer */
- MC_OUT(MC_CTP, apmmu_get_raw_ctable_ptr());
-
- /* Initialize the send queue pointers */
- qp = MSC_SQPTR0;
- for (i = 0; i < 5; ++i) {
- MSC_OUT(qp, ((send_queues[i].size == 64? MSC_SQP_MODE: 0)
- + ((send_queues[i].base >> 5) << MSC_SQP_BP_SH)));
- qp += (MSC_SQPTR1 - MSC_SQPTR0);
- }
-
- /* Initialize the send queue RAM */
- for (i = 0; i < 256; ++i)
- MSC_OUT(MSC_SQRAM + i * 8, -1);
-
- if (!qof_base) {
- qof_base = (struct qof_elt *) __get_free_pages(GFP_ATOMIC, QOF_ORDER);
- for (i = MAP_NR(qof_base); i <= MAP_NR(((char*)qof_base)+QOF_SIZE-1);++i)
- set_bit(PG_reserved, &mem_map[i].flags);
- }
-
- qof_phys = mmu_v2p((unsigned long) qof_base);
- MSC_OUT(MSC_QBMPTR, MAKE_QBMPTR((unsigned long)qof_base, QOF_SIZE));
- qof_rp = qof_base;
- qof_new = qof_base;
- for (i = 0; i < NSENDQUEUES; ++i)
- qof_present[i] = 0;
-
- SQ_NEW_MODE(NORMAL); /* Set the send queue to normal mode */
-
- /* Register interrupt handler for MSC+ */
- save_flags(flags); cli();
- res = request_irq(APMSC_IRQ, msc_interrupt_11, SA_INTERRUPT,
- "apmsc", NULL);
- if (res != 0)
- printk("couldn't register MSC interrupt 11: error=%d\n", res);
- res = request_irq(APMAS_IRQ, msc_interrupt_9, SA_INTERRUPT,
- "apmas", NULL);
- if (res != 0)
- printk("couldn't register MSC interrupt 9: error=%d\n", res);
- restore_flags(flags);
-
- MSC_OUT(MSC_MASCTRL, 0);
-
- /* Enable all MSC+ interrupts (for now) */
- MSC_OUT(MSC_INTR,
- (AP_CLR_INTR_MASK << MSC_INTR_QBMFUL_SH) |
- (AP_CLR_INTR_MASK << MSC_INTR_SQFILL_SH) |
- (AP_CLR_INTR_MASK << MSC_INTR_RBMISS_SH) |
- (AP_CLR_INTR_MASK << MSC_INTR_RBFULL_SH) |
- (AP_CLR_INTR_MASK << MSC_INTR_RMASF_SH) |
- (AP_CLR_INTR_MASK << MSC_INTR_RMASE_SH) |
- (AP_CLR_INTR_MASK << MSC_INTR_SMASF_SH) |
- (AP_CLR_INTR_MASK << MSC_INTR_SMASE_SH));
-
- /* setup invalid contexts */
- for (i=0; i<MSC_NR_RBUFS; i++)
- MSC_OUT(ringbufs[i].rbmmode, NULL_CONTEXT);
-
- MSC_OUT(MSC_SMASREG,0);
- MSC_OUT(MSC_RMASREG,0);
-
- if (!system_ringbuf.ringbuf) {
- system_ringbuf.ringbuf =
- (void *)__get_free_pages(GFP_ATOMIC,SYSTEM_RINGBUF_ORDER);
- for (i=MAP_NR(system_ringbuf.ringbuf);
- i<=MAP_NR(system_ringbuf.ringbuf+SYSTEM_RINGBUF_SIZE-1);i++)
- set_bit(PG_reserved, &mem_map[i].flags);
- system_ringbuf.write_ptr = mmu_v2p((unsigned)system_ringbuf.ringbuf)<<1;
- }
-
- if (!dummy_ringbuf.ringbuf) {
- dummy_ringbuf.ringbuf =
- (void *)__get_free_pages(GFP_ATOMIC,DUMMY_RINGBUF_ORDER);
- for (i=MAP_NR(dummy_ringbuf.ringbuf);
- i<=MAP_NR(dummy_ringbuf.ringbuf+DUMMY_RINGBUF_SIZE-1);i++)
- set_bit(PG_reserved, &mem_map[i].flags);
- dummy_ringbuf.write_ptr = mmu_v2p((unsigned)dummy_ringbuf.ringbuf)<<1;
- }
-}
-
-
-static inline void qbmfill_interrupt(void)
-{
- MSC_OUT(MSC_INTR, AP_CLR_INTR_MASK << MSC_INTR_QBMFUL_SH);
- intr_mask &= ~(AP_INTR_REQ << MSC_INTR_QBMFUL_SH);
-
- SQ_NEW_MODE(THRU); /* set send queue ctrlr to through mode */
- refill_sq(); /* refill the send queues */
- SQ_NEW_MODE(NORMAL); /* set send queue ctrlr back to normal mode */
- /* dismiss the interrupt */
- MSC_OUT(MSC_INTR, AP_CLR_INTR_REQ << MSC_INTR_SQFILL_SH);
-}
-
-static inline void qbmful_interrupt(void)
-{
- int nvalid, ntot, q;
-
- qbm_full_counter++;
-
-#if DEBUG
- printk("qbm full interrupt\n");
-#endif
-
- SQ_NEW_MODE(THRU); /* set send queue ctrlr to through mode */
- /* stuff as much as we can into the send queue RAM */
- refill_sq();
- /* count how many valid words are left in the qof buffer */
- nvalid = 0;
- for (q = 0; q < NSENDQUEUES; ++q)
- nvalid += qof_present[q];
- if (nvalid >= QOF_GREEN_NELT) {
-#if DEBUG
- printk("send queue overflow buffer overflow\n");
-#endif
- MSC_OUT(MSC_INTR, AP_SET_INTR_MASK << MSC_INTR_QBMFUL_SH);
- intr_mask |= (AP_INTR_REQ << MSC_INTR_QBMFUL_SH);
- current->need_resched = 1;
- block_parallel_tasks = 1;
- mark_bh(TQUEUE_BH);
- }
- ntot = qof_new - qof_rp; /* total # words of qof buf used */
- if (ntot - nvalid >= REPACK_THRESH || ntot >= QOF_GREEN_NELT
- || (ntot > nvalid && nvalid >= QOF_GREEN_NELT - REPACK_THRESH)) {
- repack_qof();
- if (qof_new - qof_rp != nvalid) {
- printk("MSC: qof_present wrong\n");
- }
- } else if (nvalid > 0) {
- shuffle_qof();
- }
- /* N.B. if nvalid == 0, msc_refill_sq has already reset the QBM's WP */
- SQ_NEW_MODE(NORMAL);
-
- /* dismiss the interrupt */
- MSC_OUT(MSC_INTR, AP_CLR_INTR_REQ << MSC_INTR_QBMFUL_SH);
-}
-
-
-static void msc_interrupt_11(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned intr;
- unsigned long flags;
-
- save_flags(flags); cli();
-
- if (intr_counter++ == INTR_LIMIT) {
- mask_all_interrupts();
- printk("too many MSC interrupts\n");
- restore_flags(flags);
- return;
- }
-
- intr = MSC_IN(MSC_INTR);
-
-#if DEBUG
- printk("CID(%d) msc_interrupt_11: intr = %x\n", mpp_cid(), intr);
-#endif
-
- if (intr & (AP_INTR_REQ << MSC_INTR_RBMISS_SH)) {
- int context;
- context = MSC_IN(MSC_RMASREG) >> 20;
-
- msc_set_ringbuf(context);
- MSC_OUT(MSC_INTR, AP_CLR_INTR_REQ << MSC_INTR_RBMISS_SH);
- }
-
- if (intr & (AP_INTR_REQ << MSC_INTR_RBFULL_SH)) {
- int context = MSC_IN(MSC_RMASREG) >> 20;
- msc_update_read_ptr(context,1);
- MSC_OUT(MSC_INTR, AP_CLR_INTR_REQ << MSC_INTR_RBFULL_SH);
- }
-
- if (intr & (AP_INTR_REQ << MSC_INTR_SQFILL_SH)) {
- qbmfill_interrupt();
- }
-
- if (intr & (AP_INTR_REQ << MSC_INTR_QBMFUL_SH)) {
- qbmful_interrupt();
- }
-
- restore_flags(flags);
-}
-
-
-void msc_timer(void)
-{
- /* unmask all the interrupts that are supposed to be unmasked */
- intr_counter = 0;
-}
-
-/* assumes NSENDQUEUES == 5 */
-static int log2tbl[32] = {
- -1, 0, 1, -1, 2, -1, -1, -1,
- 3, -1, -1, -1, -1, -1, -1, -1,
- 4, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1
-};
-
-static unsigned long direct_queues[NSENDQUEUES][2] = {
- { MSC_SYSTEM_DIRECT, MSC_SYSTEM_DIRECT_END },
- { MSC_REMOTE_DIRECT, MSC_REMOTE_DIRECT_END },
- { MSC_USER_DIRECT, MSC_USER_DIRECT_END },
- { MSC_REMREPLY_DIRECT, MSC_REMREPLY_DIRECT_END },
- { MSC_REPLY_DIRECT, MSC_REPLY_DIRECT_END }
-};
-
-/*
- * Copy entries from the queue overflow buffer back to the send queue.
- * This must be called with the send queue controller in THRU mode.
- */
-static void refill_sq(void)
-{
- int notfull, use_old;
- int q, kept_some;
- int sqp, sqc;
- struct qof_elt *rp, *qof_wp;
- int freew[NSENDQUEUES]; /* # free words in each queue */
-
- /* give parallel tasks another chance */
- block_parallel_tasks = 0;
-
- /* get the qbm's write pointer */
- qof_wp = qof_base + (EXTFIELD(MSC_IN(MSC_QBMPTR), MSC_QBMP_WP)
- & ((QOF_SIZE - 1) >> 3));
-#if 0
- printk("refill_sq: rp=%p new=%p wp=%p pres=[",
- qof_rp, qof_new, qof_wp);
- for (q = 0; q < NSENDQUEUES; ++q)
- printk("%d ", qof_present[q]);
- printk("]\n");
-#endif
-
- /* work out which send queues and aren't full */
- notfull = 0;
- use_old = 0;
- for (q = 0; q < NSENDQUEUES; ++q) {
- sqp = MSC_IN(MSC_SQPTR0 + q * 8);
- freew[q] = (EXTFIELD(sqp, MSC_SQP_RP) - EXTFIELD(sqp, MSC_SQP_WP) - 1)
- & ((sqp & MSC_SQP_MODE)? 0x3f: 0x1f);
- if (freew[q] > 0)
- notfull |= 1 << (q + QOF_QUEUE_SH);
- use_old += (freew[q] < qof_present[q])? freew[q]: qof_present[q];
- }
-
- /*
- * If there are useful entries in the old part of the overflow
- * queue, process them.
- */
- kept_some = 0;
- for (rp = qof_rp; rp < qof_new && use_old > 0; ++rp) {
- if (rp->info & notfull) {
- /* Here's one we can stuff back into the send queue */
- q = log2tbl[EXTFIELD(rp->info, QOF_QUEUE)];
- if (q < 0) {
- printk("bad queue bits in qof info (%x) at %p\n",
- rp->info, rp);
- /* XXX just ignore this entry - should never happen */
- rp->info = 0;
- continue;
- }
- MSC_OUT(direct_queues[q][rp->info & QOF_ENDBIT],rp->data);
- if (--freew[q] == 0)
- notfull &= ~(1 << (q + QOF_QUEUE_SH));
- --qof_present[q];
- --use_old;
- rp->info = 0;
- } else if (!kept_some && rp->info != 0) {
- qof_rp = rp;
- kept_some = 1;
- }
- }
-
- /* Trim off any further already-used items. */
- if (!kept_some) {
- for (; rp < qof_new; ++rp) {
- if (rp->info) {
- qof_rp = rp;
- kept_some = 1;
- break;
- }
- }
- }
-
- /*
- * Now process everything that's arrived since we last updated qof_new.
- */
- for (rp = qof_new; rp < qof_wp; ++rp) {
- if (rp->info == 0)
- continue;
- q = log2tbl[EXTFIELD(rp->info, QOF_QUEUE)];
- if (q < 0) {
- printk("bad queue bits in qof info (%x) at %p\n", rp->info, rp);
- /* XXX just ignore this entry - should never happen */
- rp->info = 0;
- continue;
- }
- if (rp->info & notfull) {
- /* Another one to stuff back into the send queue. */
- MSC_OUT(direct_queues[q][rp->info & QOF_ENDBIT],rp->data);
- if (--freew[q] == 0)
- notfull &= ~(1 << (q + QOF_QUEUE_SH));
- rp->info = 0;
- } else {
- ++qof_present[q];
- if (!kept_some) {
- qof_rp = rp;
- kept_some = 1;
- }
- }
- }
-
- /* Update state and the MSC queue-spill flags. */
- if (!kept_some) {
- /* queue is empty; avoid unnecessary overflow interrupt later */
- qof_rp = qof_new = qof_base;
- QBM_UPDATE_WP(mmu_v2p((unsigned long)qof_base));
- } else {
- qof_new = qof_wp;
- }
-
- sqc = MSC_IN(MSC_SQCTRL);
- for (q = 0; q < NSENDQUEUES; ++q)
- if (qof_present[q] == 0 && freew[q] > 0)
- sqc &= ~(1 << (q + MSC_SQC_SPLF_SH));
- MSC_OUT(MSC_SQCTRL, sqc);
-}
-
-/*
- * Copy the valid entries from their current position
- * in the queue overflow buffer to the beginning.
- * This must be called with the send queue controller in THRU or BLOCKING mode.
- */
-static void repack_qof(void)
-{
- struct qof_elt *rp, *wp;
-
- wp = qof_base;
- for (rp = qof_rp; rp < qof_new; ++rp) {
- if (rp->info) {
- if (rp > wp)
- *wp = *rp;
- ++wp;
- }
- }
- qof_rp = qof_base;
- qof_new = wp;
- QBM_UPDATE_WP(wp);
-}
-
-/*
- * Copy all entries from their current position
- * in the queue overflow buffer to the beginning.
- * This must be called with the send queue controller in THRU or BLOCKING mode.
- */
-static void shuffle_qof(void)
-{
- int n;
-
- n = qof_new - qof_rp;
- memmove(qof_base, qof_rp, n * sizeof(struct qof_elt));
- qof_rp = qof_base;
- qof_new = qof_base + n;
- QBM_UPDATE_WP(qof_new);
-}
-
-static inline void handle_signal(int context,unsigned vaddr)
-{
- int signum = (vaddr - MSC_REM_SIGNAL) >> PAGE_SHIFT;
- int taskid = MPP_CTX_TO_TASK(context);
- if (MPP_IS_PAR_TASK(taskid) && valid_task(task[taskid])) {
- send_sig(signum,task[taskid],1);
-#if DEBUG
- printk("CID(%d) sent signal %d to task %d\n",mpp_cid(),signum,taskid);
-#endif
- }
-}
-
-
-/*
- * fail a msc write operation. We use Pauls dirty tlb trick to avoide
- * the msc hardware bugs
- */
-static void fail_write(int context,int intr,unsigned vaddr)
-{
- int tsk = MPP_CTX_TO_TASK(context);
- int vpage = vaddr >> 12;
-#if DEBUG
- printk("fail write tsk=%d intr=%x vaddr=%x RMASREG=%x errproc=%x\n",
- tsk,intr,vaddr,MSC_IN(MSC_RMASREG),MSC_IN(MSC_RHDERRPROC));
-#endif
-
- mc_tlb_map(0x800000 | (mmu_v2p((unsigned)dummy_ringbuf.ringbuf)>>12),
- vpage,context);
- MSC_OUT(MSC_MASCTRL, MSC_IN(MSC_MASCTRL) & ~MSC_MASC_RFEXIT);
- MSC_OUT(MSC_INTR, AP_CLR_INTR_REQ << intr);
-
- mc_tlb_unmap(vpage);
-
- if (MPP_IS_PAR_CTX(context) && valid_task(task[tsk])) {
- if (vaddr - MSC_REM_SIGNAL < _NSIG*PAGE_SIZE) {
- handle_signal(context,vaddr);
- } else {
- task[tsk]->thread.sig_address = vaddr;
- task[tsk]->thread.sig_desc = SUBSIG_NOMAPPING;
- send_sig(SIGSEGV, task[tsk], 1);
- }
- }
-}
-
-/*
- * fail a msc read operation using the tlb trick */
-static void fail_read(int context,int intr,unsigned vaddr)
-{
- int tsk = MPP_CTX_TO_TASK(context);
-#if DEBUG
- printk("fail read tsk=%d intr=%x\n",tsk,intr);
-#endif
-
- mc_tlb_map(0x800000 | (mmu_v2p((unsigned)dummy_ringbuf.ringbuf)>>12),
- vaddr>>12,context);
- MSC_OUT(MSC_MASCTRL, MSC_IN(MSC_MASCTRL) & ~MSC_MASC_SFEXIT);
- MSC_OUT(MSC_INTR, AP_CLR_INTR_REQ << intr);
-
- mc_tlb_unmap(vaddr>>12);
-
- if (MPP_IS_PAR_CTX(context) && valid_task(task[tsk])) {
- if (vaddr - MSC_REM_SIGNAL < _NSIG*PAGE_SIZE) {
- handle_signal(context,vaddr);
- } else {
- task[tsk]->thread.sig_address = vaddr;
- task[tsk]->thread.sig_desc = SUBSIG_NOMAPPING;
- send_sig(SIGSEGV, task[tsk], 1);
- }
- }
-}
-
-static void async_callback(int tsk,unsigned long vaddr,int write,int ret)
-{
- unsigned flags;
- save_flags(flags); cli();
-
- msc_blocked--;
- if (write) {
- intr_mask &= ~(AP_INTR_REQ << MSC_INTR_RMASF_SH);
- if (ret) {
- fail_write(MPP_TASK_TO_CTX(tsk),MSC_INTR_RMASF_SH,vaddr);
- MSC_OUT(MSC_INTR, AP_CLR_INTR_MASK << MSC_INTR_RMASF_SH);
- restore_flags(flags);
- return;
- }
- MSC_OUT(MSC_MASCTRL, MSC_IN(MSC_MASCTRL) & ~MSC_MASC_RFEXIT);
- MSC_OUT(MSC_INTR, AP_CLR_INTR_REQ << MSC_INTR_RMASF_SH);
- MSC_OUT(MSC_INTR, AP_CLR_INTR_MASK << MSC_INTR_RMASF_SH);
- } else {
- intr_mask &= ~(AP_INTR_REQ << MSC_INTR_SMASF_SH);
- if (ret) {
- fail_read(MPP_TASK_TO_CTX(tsk),MSC_INTR_SMASF_SH,vaddr);
- MSC_OUT(MSC_INTR, AP_CLR_INTR_MASK << MSC_INTR_SMASF_SH);
- restore_flags(flags);
- return;
- }
- MSC_OUT(MSC_MASCTRL, MSC_IN(MSC_MASCTRL) & ~MSC_MASC_SFEXIT);
- MSC_OUT(MSC_INTR, AP_CLR_INTR_REQ << MSC_INTR_SMASF_SH);
- MSC_OUT(MSC_INTR, AP_CLR_INTR_MASK << MSC_INTR_SMASF_SH);
- }
- restore_flags(flags);
-}
-
-
-
-static inline void msc_write_fault(void)
-{
- unsigned context = MSC_IN(MSC_RMASREG) >> 20;
- unsigned vaddr = MSC_IN(MSC_RMASTWP)<<12;
-
- if (context == SYSTEM_CONTEXT) {
- fail_write(context,MSC_INTR_RMASF_SH,vaddr);
- show_mapping_ctx(0,context,vaddr);
- printk("ERROR: system write fault at %x\n",vaddr);
- return;
- }
-
- if (vaddr - MSC_REM_SIGNAL < _NSIG*PAGE_SIZE) {
- fail_write(context,MSC_INTR_RMASF_SH,vaddr);
- return;
- }
-
- if (MPP_IS_PAR_CTX(context)) {
- int tsk = MPP_CTX_TO_TASK(context);
- if (valid_task(task[tsk]) && task[tsk]->ringbuf) {
- MSC_OUT(MSC_INTR,
- AP_SET_INTR_MASK << MSC_INTR_RMASF_SH);
- intr_mask |= (AP_INTR_REQ << MSC_INTR_RMASF_SH);
-#if DEBUG
- show_mapping_ctx(0,context,vaddr);
-#endif
- msc_blocked++;
- async_fault(vaddr,1,tsk,async_callback);
- return;
- }
- }
-
-#if DEBUG
- printk("CID(%d) mas write fault context=%x vaddr=%x\n",
- mpp_cid(),context,vaddr);
-#endif
-
- fail_write(context,MSC_INTR_RMASF_SH,vaddr);
-}
-
-
-static inline void msc_read_fault(void)
-{
- unsigned context = MSC_IN(MSC_SMASREG) >> 20;
- unsigned vaddr = MSC_IN(MSC_SMASTWP)<<12;
-
- if (context == SYSTEM_CONTEXT) {
- fail_read(context,MSC_INTR_SMASF_SH,vaddr);
- show_mapping_ctx(0,context,vaddr);
- printk("ERROR: system read fault at %x\n",vaddr);
- return;
- }
-
- if (MPP_IS_PAR_CTX(context)) {
- int tsk = MPP_CTX_TO_TASK(context);
-
- if (vaddr - MSC_REM_SIGNAL < _NSIG*PAGE_SIZE) {
- fail_read(context,MSC_INTR_SMASF_SH,vaddr);
- return;
- }
-
- if (valid_task(task[tsk]) && task[tsk]->ringbuf) {
- MSC_OUT(MSC_INTR, AP_SET_INTR_MASK << MSC_INTR_SMASF_SH);
- intr_mask |= (AP_INTR_REQ << MSC_INTR_SMASF_SH);
- msc_blocked++;
- async_fault(vaddr,0,tsk,async_callback);
- return;
- }
- }
-
-#if DEBUG
- printk("CID(%d) mas read fault context=%x vaddr=%x\n",
- mpp_cid(),context,vaddr);
-#endif
-
- fail_read(context,MSC_INTR_SMASF_SH,vaddr);
-}
-
-
-
-static void msc_interrupt_9(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned long flags;
- unsigned intr, cnt, r;
-
- save_flags(flags); cli();
-
- if (intr_counter++ == INTR_LIMIT) {
- mask_all_interrupts();
- printk("too many MSC interrupts\n");
- restore_flags(flags);
- return;
- }
-
- intr = MSC_IN(MSC_INTR) & ~intr_mask;
-
-#if DEBUG
- printk("CID(%d) msc_interrupt_9: intr = %x\n", mpp_cid(), intr);
-#endif
-
- if (intr & (AP_INTR_REQ << MSC_INTR_RMASF_SH)) {
- msc_write_fault();
- }
-
- if (intr & (AP_INTR_REQ << MSC_INTR_SMASF_SH)) {
- msc_read_fault();
- }
-
- if (intr & (AP_INTR_REQ << MSC_INTR_RMASE_SH)) {
- printk("recv mas error interrupt (write)\n");
- printk("masctrl = %x\n", MSC_IN(MSC_MASCTRL));
- printk("rmasadr = %x %x\n", MSC_IN(MSC_RMASADR),
- MSC_IN(MSC_RMASADR + 4));
- printk("rmastwp = %x\n", MSC_IN(MSC_RMASTWP));
- printk("rmasreg = %x\n", MSC_IN(MSC_RMASREG));
- r = MSC_IN(MSC_RMASREG);
- if ((r & MSC_MASR_AVIO) || (r & MSC_MASR_CMD) != MSC_MASR_CMD_XFER)
- /* throw away the rest of the incoming data */
- MSC_OUT(MSC_RHDERRPROC, 0);
- /* clear the interrupt */
- MSC_OUT(MSC_INTR, AP_CLR_INTR_REQ << MSC_INTR_RMASE_SH);
- }
-
- if (intr & (AP_INTR_REQ << MSC_INTR_SMASE_SH)) {
- printk("send mas error interrupt (read)\n");
- printk("masctrl = %x\n", MSC_IN(MSC_MASCTRL));
- printk("smasadr = %x %x\n", MSC_IN(MSC_SMASADR),
- MSC_IN(MSC_SMASADR + 4));
- printk("smascnt = %x\n", MSC_IN(MSC_SMASCNT));
- printk("smastwp = %x\n", MSC_IN(MSC_SMASTWP));
- printk("smasreg = %x\n", MSC_IN(MSC_SMASREG));
- /* supply dummy data */
- cnt = MSC_IN(MSC_SMASCNT);
- switch (MSC_IN(MSC_SMASREG) & MSC_MASR_CMD) {
- case MSC_MASR_CMD_XFER:
- MSC_OUT(MSC_HDGERRPROC, (EXTFIELD(cnt, MSC_SMCT_MCNT)
- + EXTFIELD(cnt, MSC_SMCT_ICNT)));
- break;
- /* case remote read: */
- case MSC_MASR_CMD_FOP:
- case MSC_MASR_CMD_CSI:
- MSC_OUT(MSC_HDGERRPROC, 1);
- break;
- }
- /* clear interrupt */
- MSC_OUT(MSC_INTR, AP_CLR_INTR_REQ << MSC_INTR_SMASF_SH);
- }
-
- restore_flags(flags);
-}
-
-/*
- * remove access to a tasks ring buffer
- */
-void msc_unset_ringbuf(int i)
-{
- int ctx = MSC_IN(ringbufs[i].rbmmode) & CTX_MASK;
- int tsk = MPP_CTX_TO_TASK(ctx);
- struct ringbuf_struct *rbuf;
-
-#if DEBUG
- printk("msc_unset_ringbuf(%d) %x\n",i,ctx);
-#endif
-
- MSC_OUT(ringbufs[i].rbmmode,NULL_CONTEXT);
- if (ctx == SYSTEM_CONTEXT) {
- rbuf = &system_ringbuf;
- } else if (ctx != NULL_CONTEXT && MPP_IS_PAR_CTX(ctx) &&
- valid_task(task[tsk]) && task[tsk]->ringbuf) {
- rbuf = task[tsk]->ringbuf;
- } else if (ctx != NULL_CONTEXT && MPP_IS_PAR_CTX(ctx) &&
- valid_task(task[tsk]) && task[tsk]->aplib) {
- rbuf = &system_ringbuf;
- } else {
- rbuf = &dummy_ringbuf;
- }
-
- rbuf->write_ptr = MSC_IN(ringbufs[i].rbmbwp);
-}
-
-static void msc_update_read_ptr(int context,int overflow)
-{
- int i;
- unsigned new_read_ptr;
-
- for (i=0;i<NR_RBUFS;i++) {
- if ((MSC_IN(ringbufs[i].rbmmode)&CTX_MASK) == context) break;
- }
- if (i == NR_RBUFS) {
- printk("didn't find context %d in msc_update_read_ptr()\n",
- context);
- return;
- }
-
- if (context == SYSTEM_CONTEXT) {
- tnet_check_completion();
- if (overflow && MSC_IN(ringbufs[i].rbmrp) == system_read_ptr)
- printk("system ringbuffer overflow\n");
- new_read_ptr = system_read_ptr;
- } else if (MPP_IS_PAR_CTX(context) &&
- valid_task(task[MPP_CTX_TO_TASK(context)]) &&
- task[MPP_CTX_TO_TASK(context)]->ringbuf) {
- struct task_struct *tsk = task[MPP_CTX_TO_TASK(context)];
- struct _kernel_cap_shared *_kernel;
- unsigned soft_read_ptr;
- unsigned octx;
-
- octx = apmmu_get_context();
- if (octx != context)
- apmmu_set_context(context);
- _kernel = (struct _kernel_cap_shared *)(RBUF_VBASE + RBUF_SHARED_PAGE_OFF);
- soft_read_ptr = _kernel->rbuf_read_ptr;
- if (octx != context)
- apmmu_set_context(octx);
-
- if (overflow && MSC_IN(ringbufs[i].rbmrp) == soft_read_ptr) {
- /* send them a SIGLOST and wipe their ring buffer */
- printk("ring buffer overflow for %s ctx=%x\n",
- tsk->comm,context);
- send_sig(SIGLOST,tsk,1);
- soft_read_ptr--;
- }
- new_read_ptr = soft_read_ptr;
- } else if (MPP_IS_PAR_CTX(context) &&
- valid_task(task[MPP_CTX_TO_TASK(context)]) &&
- task[MPP_CTX_TO_TASK(context)]->aplib) {
- tnet_check_completion();
- if (overflow && MSC_IN(ringbufs[i].rbmrp) == system_read_ptr)
- printk("system ringbuffer overflow\n");
- new_read_ptr = system_read_ptr;
- } else {
- dummy_read_ptr = MSC_IN(ringbufs[i].rbmrp) - 1;
- new_read_ptr = dummy_read_ptr - 1;
-#if DEBUG
- if (overflow)
- printk("reset dummy ring buffer for context %x\n",
- context);
-#endif
- }
-
-
- MSC_OUT(ringbufs[i].rbmrp,new_read_ptr);
-}
-
-/*
- * give a task one of the system ring buffers
- * this is called on a context miss interrupt, so we can assume that
- * the tasks context is not currently set in one of the ringbufs
- */
-static void msc_set_ringbuf(int context)
-{
- int i;
- int ctx;
- int mode;
- unsigned write_ptr;
- static unsigned next_ctx = 0;
- struct ringbuf_struct *rbuf;
-
- if (context == SYSTEM_CONTEXT) {
- rbuf = &system_ringbuf;
- } else if (MPP_IS_PAR_CTX(context) &&
- valid_task(task[MPP_CTX_TO_TASK(context)]) &&
- task[MPP_CTX_TO_TASK(context)]->ringbuf) {
- struct task_struct *tsk = task[MPP_CTX_TO_TASK(context)];
- rbuf = tsk->ringbuf;
- } else if (MPP_IS_PAR_CTX(context) &&
- valid_task(task[MPP_CTX_TO_TASK(context)]) &&
- task[MPP_CTX_TO_TASK(context)]->aplib) {
- rbuf = &system_ringbuf;
- } else {
- /* use the dummy ring buffer */
- rbuf = &dummy_ringbuf;
- }
-
- for (i=0;i<NR_RBUFS; i++) {
- ctx = MSC_IN(ringbufs[i].rbmmode)&CTX_MASK;
- if (ctx == NULL_CONTEXT) break;
- }
- if (i == NR_RBUFS) {
- i = next_ctx;
- next_ctx = (i+1)%NR_RBUFS;
- }
-
- ctx = MSC_IN(ringbufs[i].rbmmode)&CTX_MASK;
- if (ctx != NULL_CONTEXT) msc_unset_ringbuf(i);
-
- write_ptr = rbuf->write_ptr;
- mode = (rbuf->order - 5) >> 1;
-
- MSC_OUT(ringbufs[i].rbmmode,context | (mode << 12));
- MSC_OUT(ringbufs[i].rbmbwp,write_ptr);
-
- if (rbuf == &system_ringbuf) {
- MSC_OUT(ringbufs[i].rbmrp,system_read_ptr);
- } else {
- msc_update_read_ptr(context,0);
- }
-
-#if DEBUG
- printk("CID(%d) mapped ringbuf for context %d in slot %d\n",
- mpp_cid(),context,i);
-#endif
-}
-
-
-/*
- * this is called when a task exits
-*/
-void exit_msc(struct task_struct *tsk)
-{
- int i;
-
- if (!MPP_IS_PAR_TASK(tsk->taskid))
- return;
-
-#if DEBUG
- printk("exit_msc(%d) ctx=%d\n",tsk->taskid,tsk->mm->context);
-#endif
-
- for (i=0;i<NR_RBUFS; i++) {
- int ctx = MSC_IN(ringbufs[i].rbmmode)&CTX_MASK;
- if (ctx == MPP_TASK_TO_CTX(tsk->taskid))
- msc_unset_ringbuf(i);
- }
- msc_switch_from_check(tsk);
-
- /* stop it receiving new-style messages */
- tsk->aplib = NULL;
-
- exit_ringbuf(tsk);
-}
-
-
-static void msc_sq_pause(void)
-{
- MSC_OUT(MSC_SQCTRL,MSC_IN(MSC_SQCTRL) | MSC_SQC_PAUSE);
- while (!(MSC_IN(MSC_SQCTRL) & MSC_SQC_STABLE)) /* wait for stable bit */ ;
-}
-
-static void msc_sq_resume(void)
-{
- MSC_OUT(MSC_SQCTRL,MSC_IN(MSC_SQCTRL) & ~MSC_SQC_PAUSE);
-}
-
-static void msc_switch_from_check(struct task_struct *tsk)
-{
- int user_count;
- unsigned flags;
- struct ringbuf_struct *rbuf = NULL;
- int octx, ctx;
-
- if (valid_task(tsk) && tsk->ringbuf)
- rbuf = tsk->ringbuf;
-
- /* it doesn't seem obvious why this field should contain count+1,
- but it does */
- user_count = EXTFIELD(MSC_IN(MSC_QWORDCNT),MSC_QWDC_USRCNT) - 1;
-
- /* check if the user queue count is != 0 */
- if (user_count == 0) return;
-
- if (!rbuf)
- printk("switching from dead task\n");
-
-#if 1
- printk("saving %d words MSC_QWORDCNT=%x\n",
- user_count,MSC_IN(MSC_QWORDCNT));
-#endif
-
- /* bugger - we have to do some messy work */
- save_flags(flags); cli();
-
- ctx = MPP_TASK_TO_CTX(tsk->taskid);
- octx = apmmu_get_context();
- if (octx != ctx)
- apmmu_set_context(ctx);
-
- msc_sq_pause();
-
- /* remember the expected length of the command - usually (always?) 8 */
- if (rbuf)
- rbuf->frag_len = EXTFIELD(MSC_IN(MSC_QWORDCNT),MSC_QWDC_USRLEN);
-
- /* pull words from the overflow first */
- if (MSC_IN(MSC_SQCTRL) & MSC_SQC_USERF) {
- /* we have overflowed */
- struct qof_elt *qof_wp = qof_base +
- (EXTFIELD(MSC_IN(MSC_QBMPTR), MSC_QBMP_WP) & ((QOF_SIZE - 1) >> 3));
- while (qof_wp != qof_rp && user_count) {
- qof_wp--;
- /* only grab elements in the user queue */
- if (qof_wp->info && log2tbl[EXTFIELD(qof_wp->info, QOF_QUEUE)] == 2) {
- if (qof_wp->info & 1) {
- printk("MSC: end bit set - yikes!\n");
- }
- qof_wp->info = 0;
- if (rbuf) {
- rbuf->sq_fragment[--user_count] = qof_wp->data;
- rbuf->frag_count++;
- }
- if (qof_wp < qof_new)
- qof_present[2]--;
- }
- }
-#if DEBUG
- if (rbuf)
- printk("pulled %d elements from overflow (%d left)\n",
- rbuf->frag_count,user_count);
-#endif
- }
-
- /* then pull words direct from the msc ram */
- if (user_count) {
- int wp = EXTFIELD(MSC_IN(MSC_SQPTR2),MSC_SQP_WP);
- int i;
- wp -= user_count;
- if (wp < 0) wp += send_queues[2].size;
-
- for (i=0;i<user_count;i++) {
- int wp2 = (wp + i)%send_queues[2].size;
- if (rbuf)
- rbuf->sq_fragment[i + rbuf->frag_count] =
- MSC_IN(MSC_SQRAM + (send_queues[2].base + wp2)*8);
- }
-
- if (rbuf)
- rbuf->frag_count += user_count;
-
- MSC_OUT(MSC_SQPTR2,INSFIELD(MSC_IN(MSC_SQPTR2),wp,MSC_SQP_WP));
-#if DEBUG
- printk("saved %d words from msc ram\n",rbuf->frag_count);
-#endif
- }
-
- /* reset the user count to 1 */
- MSC_OUT(MSC_QWORDCNT,INSFIELD(MSC_IN(MSC_QWORDCNT),1,MSC_QWDC_USRCNT));
-
- msc_sq_resume();
-
- if (octx != ctx)
- apmmu_set_context(octx);
-
- restore_flags(flags);
-}
-
-static void msc_switch_to_check(struct task_struct *tsk)
-{
- int i;
- unsigned flags;
- int octx, ctx;
-
- if (!valid_task(tsk) || !tsk->ringbuf)
- return;
-
- save_flags(flags); cli();
-
-
- ctx = MPP_TASK_TO_CTX(tsk->taskid);
- octx = apmmu_get_context();
- if (octx != ctx)
- apmmu_set_context(ctx);
-
- /* if the task we are switching to has no saved words then
- we're finished */
- if (tsk->ringbuf->frag_count == 0) {
- if (octx != ctx)
- apmmu_set_context(octx);
- restore_flags(flags);
- return;
- }
-
-
-#if 1
- printk("frag fill MSC_QWORDCNT=%x frag_count=%d\n",
- MSC_IN(MSC_QWORDCNT),tsk->ringbuf->frag_count);
-#endif
-
- /* reset the user length */
- MSC_OUT(MSC_QWORDCNT,INSFIELD(MSC_IN(MSC_QWORDCNT),
- tsk->ringbuf->frag_len,
- MSC_QWDC_USRLEN));
-
- /* push the words into the direct queue */
- for (i=0;i<tsk->ringbuf->frag_count;i++)
- MSC_OUT(MSC_USER_DIRECT,tsk->ringbuf->sq_fragment[i]);
-
- /* reset the user count */
- MSC_OUT(MSC_QWORDCNT,INSFIELD(MSC_IN(MSC_QWORDCNT),
- 1+tsk->ringbuf->frag_count,
- MSC_QWDC_USRCNT));
-
-#if DEBUG
- printk("frag fill done MSC_QWORDCNT=%x\n",
- MSC_IN(MSC_QWORDCNT));
-#endif
-
- tsk->ringbuf->frag_count = 0;
- tsk->ringbuf->frag_len = 0;
- if (octx != ctx)
- apmmu_set_context(octx);
- restore_flags(flags);
-}
-
-
-
-void msc_switch_check(struct task_struct *tsk)
-{
- static int last_task = 0;
-
- if (last_task == tsk->taskid) return;
-
- if (MPP_IS_PAR_TASK(last_task))
- msc_switch_from_check(task[last_task]);
-
- msc_switch_to_check(tsk);
-
- last_task = tsk->taskid;
-}
-
-/* we want to try to avoid task switching while there are partial commands
- in the send queues */
-int msc_switch_ok(void)
-{
- if ((EXTFIELD(MSC_IN(MSC_QWORDCNT),MSC_QWDC_USRCNT) - 1))
- return 0;
-
- return 1;
-}
-
-/*
- * print out the state of the msc
-*/
-static void msc_status(void)
-{
- int i;
-
- printk("MSC_SQCTRL=%x\n",MSC_IN(MSC_SQCTRL));
-
- for (i=0;i<5;i++)
- printk("MSC_SQPTR%d=%x\n",i,MSC_IN(MSC_SQPTR0 + 8*i));
- printk("MSC_OPTADR=%x\n",MSC_IN(MSC_OPTADR));
- printk("MSC_MASCTRL=%x\n", MSC_IN(MSC_MASCTRL));
- printk("MSC_SMASADR=%x_%x\n", MSC_IN(MSC_SMASADR),MSC_IN(MSC_SMASADR + 4));
- printk("MSC_RMASADR=%x_%x\n", MSC_IN(MSC_RMASADR),MSC_IN(MSC_RMASADR + 4));
- printk("MSC_PID=%x\n",MSC_IN(MSC_PID));
-
- printk("MSC_QWORDCNT=%x\n",MSC_IN(MSC_QWORDCNT));
-
- printk("MSC_INTR=%x\n",MSC_IN(MSC_INTR));
- printk("MSC_CIDRANGE=%x\n",MSC_IN(MSC_CIDRANGE));
- printk("MSC_QBMPTR=%x\n",MSC_IN(MSC_QBMPTR));
- printk("MSC_SMASTWP=%x\n", MSC_IN(MSC_SMASTWP));
- printk("MSC_RMASTWP=%x\n", MSC_IN(MSC_RMASTWP));
- printk("MSC_SMASREG=%x\n", MSC_IN(MSC_SMASREG));
- printk("MSC_RMASREG=%x\n", MSC_IN(MSC_RMASREG));
- printk("MSC_SMASCNT=%x\n", MSC_IN(MSC_SMASCNT));
- printk("MSC_IRL=%x\n", MSC_IN(MSC_IRL));
- printk("MSC_SIMMCHK=%x\n", MSC_IN(MSC_SIMMCHK));
-
- for (i=0;i<3;i++) {
- printk("RBMBWP%d=%x\n",i,MSC_IN(ringbufs[i].rbmbwp));
- printk("RBMMODE%d=%x\n",i,MSC_IN(ringbufs[i].rbmmode));
- printk("RBMRP%d=%x\n",i,MSC_IN(ringbufs[i].rbmrp));
- }
-
- printk("DMA_GEN=%x\n",MSC_IN(DMA_GEN));
-
- printk("qbm_full_counter=%d\n",qbm_full_counter);
-}
diff --git a/arch/sparc/ap1000/sync.c b/arch/sparc/ap1000/sync.c
deleted file mode 100644
index 2f8a7cd34..000000000
--- a/arch/sparc/ap1000/sync.c
+++ /dev/null
@@ -1,55 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/* sync functions using the Tnet */
-
-#include <asm/ap1000/apreg.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/threads.h>
-
-extern int cap_cid0;
-extern unsigned _ncel, _ncelx, _ncely, _cid;
-
-static volatile int sync_flags[MPP_NUM_TASKS];
-
-
-int ap_sync(int numcells, int *phys_map)
-{
- int basecell;
- int i,err;
- int tsk = current->taskid;
-
- if (numcells < 2) return 0;
-
- if (!MPP_IS_PAR_TASK(tsk)) {
- printk("nonparallel task %d called ap_sync\n",tsk);
- return 0;
- }
- tsk -= MPP_TASK_BASE;
-
- basecell = phys_map[0];
- if (cap_cid0 == basecell) {
- if ((err=wait_on_int(&sync_flags[tsk],numcells-1,5)))
- return err;
- sync_flags[tsk] = 0;
- if (numcells == _ncel) {
- ap_bput(0,0,0,&sync_flags[tsk],0);
- } else {
- for (i=1;i<numcells;i++)
- ap_put(phys_map[i],0,0,0,&sync_flags[tsk],0);
- }
- return 0;
- }
-
- ap_put(basecell,0,0,0,&sync_flags[tsk],0);
- if ((err=wait_on_int(&sync_flags[tsk],1,5)))
- return err;
- sync_flags[tsk] = 0;
- return 0;
-}
-
diff --git a/arch/sparc/ap1000/timer.c b/arch/sparc/ap1000/timer.c
deleted file mode 100644
index 567d24067..000000000
--- a/arch/sparc/ap1000/timer.c
+++ /dev/null
@@ -1,125 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/* routines to control the AP1000 timer chip */
-
-#include <linux/time.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/mm.h>
-#include <linux/malloc.h>
-#include <asm/ap1000/apservice.h>
-#include <asm/ap1000/apreg.h>
-#include <asm/irq.h>
-
-#define INIT_TIM1 (781250/HZ)
-#define INIT_TIM0 (781250/(10*HZ))
-
-static unsigned long last_freerun;
-
-unsigned ap_freerun(void)
-{
- return *((volatile unsigned long *)(MC_FREERUN + 4));
-}
-
-void ap_clear_clock_irq(void)
-{
- MC_OUT(MC_INTR, AP_CLR_INTR_REQ << MC_INTR_ITIM1_SH);
- last_freerun = *((unsigned long *)(MC_FREERUN + 4));
- tnet_check_completion();
-#if 1
- if ((((unsigned)jiffies) % (HZ/4)) == 0) {
- msc_timer();
- ap_xor_led(1);
- bif_timer();
- ap_dbg_flush();
-#if 0
- bif_led_status();
-#endif
- }
-#endif
-}
-
-
-void ap_gettimeofday(struct timeval *xt)
-{
- unsigned long d;
- unsigned v;
- unsigned long new_freerun;
-
- /* this is in 80ns units - we only use the low 32 bits
- as 5mins is plenty for this stuff */
- d = new_freerun = *((unsigned long *)(MC_FREERUN + 4));
-
- if (d < last_freerun) {
- /* wraparound */
- d += ((~0) - last_freerun);
- } else {
- d -= last_freerun;
- }
-
- /* convert to microseconds */
- v = ((d&0xffffff)*10)/125;
-
- /* only want microseconds/HZ */
- v = v%(1000000/HZ);
-
- xt->tv_usec += v;
-
- last_freerun = new_freerun;
-}
-
-static void profile_interrupt(int irq, void *dev_id, struct pt_regs * regs)
-{
- if (prof_buffer && current->pid) {
- extern int _stext;
- unsigned long ip = instruction_pointer(regs);
- ip -= (unsigned long) &_stext;
- ip >>= prof_shift;
- if (ip < prof_len)
- prof_buffer[ip]++;
- }
- MC_OUT(MC_INTR,AP_CLR_INTR_REQ << MC_INTR_ITIM0_SH);
-}
-
-void ap_profile_init(void)
-{
- if (prof_shift) {
- printk("Initialising profiling with prof_shift=%d\n",(int)prof_shift);
- MC_OUT(MC_INTR,AP_CLR_INTR_REQ << MC_INTR_ITIM0_SH);
- MC_OUT(MC_INTR,AP_CLR_INTR_MASK << MC_INTR_ITIM0_SH);
- }
-}
-
-void ap_init_timers(void)
-{
- extern void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs);
- unsigned flags;
-
- printk("Initialising ap1000 timer\n");
-
- save_flags(flags); cli();
-
- request_irq(APTIM1_IRQ,
- timer_interrupt,
- (SA_INTERRUPT | SA_STATIC_ALLOC),
- "timer", NULL);
-
- request_irq(APTIM0_IRQ,
- profile_interrupt,
- (SA_INTERRUPT | SA_STATIC_ALLOC),
- "profile", NULL);
-
- ap_clear_clock_irq();
-
- MC_OUT(MC_ITIMER0,INIT_TIM0);
- MC_OUT(MC_ITIMER1,INIT_TIM1);
- MC_OUT(MC_INTR,AP_CLR_INTR_REQ << MC_INTR_ITIM1_SH);
- MC_OUT(MC_INTR,AP_CLR_INTR_MASK << MC_INTR_ITIM1_SH);
- MC_OUT(MC_INTR,AP_SET_INTR_MASK << MC_INTR_ITIM0_SH);
- restore_flags(flags);
-}
diff --git a/arch/sparc/ap1000/tnet.c b/arch/sparc/ap1000/tnet.c
deleted file mode 100644
index 777f169f8..000000000
--- a/arch/sparc/ap1000/tnet.c
+++ /dev/null
@@ -1,708 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/* routines to control the AP1000 Tnet interface */
-
-#include <asm/ap1000/apreg.h>
-#include <asm/ap1000/aplib.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <asm/pgtable.h>
-#include <asm/pgtsrmmu.h>
-#include <stdarg.h>
-#include <linux/skbuff.h>
-
-
-/* message types for system messages */
-#define TNET_IP 0
-#define TNET_IP_SMALL 1
-#define TNET_RPC 2
-
-static struct {
- int errors;
- int alloc_errors;
- int bytes_received;
- int bytes_sent;
- int packets_received;
- int packets_sent;
- int small_packets_received;
- int small_packets_sent;
-} tnet_stats;
-
-extern int cap_cid0;
-extern int cap_ncel0;
-static u_long xy_global_head;
-
-extern unsigned _ncel, _ncelx, _ncely, _cid, _cidx, _cidy;
-
-extern struct ringbuf_struct system_ringbuf;
-extern u_long system_read_ptr;
-
-u_long system_recv_flag = 0;
-static u_long system_recv_count = 0;
-
-int *tnet_rel_cid_table;
-
-static int dummy=1;
-
-#define TNET_IP_THRESHOLD 100
-
-void tnet_check_completion(void);
-static void reschedule(void);
-static u_long tnet_add_completion(void (*fn)(int a1,...),
- int a1,int a2);
-static void tnet_info(void);
-
-static struct {
- int shift;
- void (*fn)(void);
-} iports[4] = {
- {MC_INTP_0_SH,tnet_check_completion},
- {MC_INTP_1_SH,reschedule},
- {MC_INTP_2_SH,NULL},
- {MC_INTP_3_SH,NULL}};
-
-static inline int rel_cid(unsigned dst)
-{
- unsigned dstx, dsty;
- unsigned dx,dy;
-
- if (dst == _cid) return 0;
-
- dstx = dst % _ncelx;
- dsty = dst / _ncelx;
- if (dstx >= _cidx)
- dx = dstx - _cidx;
- else
- dx = (_ncelx - _cidx) + dstx;
-
- if (dsty >= _cidy)
- dy = dsty - _cidy;
- else
- dy = (_ncely - _cidy) + dsty;
-
- return (dx<<8) | dy;
-}
-
-#define SAVE_PID() \
- unsigned long flags; \
- int saved_pid; \
- save_flags(flags); cli(); \
- saved_pid = MSC_IN(MSC_PID); \
- MSC_OUT(MSC_PID,SYSTEM_CONTEXT);
-
-#define RESTORE_PID() \
- MSC_OUT(MSC_PID,saved_pid); \
- restore_flags(flags);
-
-
-void ap_put(int dest_cell,u_long local_addr,int size,
- u_long remote_addr,u_long dest_flag,u_long local_flag)
-{
- volatile u_long *entry;
- SAVE_PID();
-
- entry = (volatile u_long *)MSC_PUT_QUEUE_S;
-
- *entry = tnet_rel_cid_table[dest_cell];
- *entry = ((size+3) >> 2);
- *entry = (u_long)remote_addr;
- *entry = 0;
- *entry = (u_long)dest_flag;
- *entry = (u_long)local_flag;
- *entry = (u_long)local_addr;
- *entry = 0;
- RESTORE_PID();
-}
-
-/* remote_addr is physical
- local address is virtual
- both flags are virtual */
-void ap_phys_put(int dest_cell,u_long local_addr,int size,
- u_long remote_addr,u_long dest_flag,u_long local_flag)
-{
- volatile u_long *entry;
- SAVE_PID();
-
- entry = (volatile u_long *)MSC_CPUT_QUEUE_S;
-
- *entry = tnet_rel_cid_table[dest_cell];
- *entry = ((size+3) >> 2);
- *entry = (u_long)remote_addr;
- *entry = 0;
- *entry = (u_long)dest_flag;
- *entry = (u_long)local_flag;
- *entry = (u_long)local_addr;
- *entry = 0;
- RESTORE_PID();
-}
-
-
-/* broadcast put - yeah! */
-void ap_bput(u_long local_addr,int size,
- u_long remote_addr,u_long dest_flag,u_long local_flag)
-{
- volatile u_long *entry = (volatile u_long *)MSC_XYG_QUEUE_S;
- SAVE_PID();
-
- *entry = xy_global_head;
- *entry = ((size+3) >> 2);
- *entry = (u_long)remote_addr;
- *entry = 0;
- *entry = (u_long)dest_flag;
- *entry = (u_long)local_flag;
- *entry = (u_long)local_addr;
- *entry = 0;
- RESTORE_PID();
-}
-
-
-/* remote_addr is physical */
-void ap_phys_bput(u_long local_addr,int size,
- u_long remote_addr,u_long dest_flag,u_long local_flag)
-{
- volatile u_long *entry = (volatile u_long *)MSC_CXYG_QUEUE_S;
- SAVE_PID();
-
- *entry = xy_global_head;
- *entry = ((size+3) >> 2);
- *entry = (u_long)remote_addr;
- *entry = 0;
- *entry = (u_long)dest_flag;
- *entry = (u_long)local_flag;
- *entry = (u_long)local_addr;
- *entry = 0;
- RESTORE_PID();
-}
-
-
-
-void ap_get(int dest_cell,u_long local_addr,int size,
- u_long remote_addr,u_long local_flag,u_long dest_flag)
-{
- volatile u_long *entry;
- SAVE_PID();
-
- entry = (u_long *)MSC_GET_QUEUE_S;
-
- *entry = tnet_rel_cid_table[dest_cell];
- *entry = (size+3) >> 2; /* byte --> word */
- *entry = (u_long)local_addr;
- *entry = 0;
- *entry = (u_long)local_flag;
- *entry = (u_long)dest_flag;
- *entry = (u_long)remote_addr;
- *entry = 0;
- RESTORE_PID();
-}
-
-
-/* local_addr is physical
- remote_addr is virtual
- both flags are virtual
-*/
-void ap_phys_get(int dest_cell,u_long local_addr,int size,
- u_long remote_addr,u_long local_flag,u_long dest_flag)
-{
- volatile u_long *entry;
- SAVE_PID();
-
- entry = (u_long *)MSC_CGET_QUEUE_S;
-
- *entry = tnet_rel_cid_table[dest_cell];
- *entry = (size+3) >> 2; /* byte --> word */
- *entry = (u_long)local_addr;
- *entry = 0;
- *entry = (u_long)local_flag;
- *entry = (u_long)dest_flag;
- *entry = (u_long)remote_addr;
- *entry = 0;
- RESTORE_PID();
-}
-
-
-/*
- * copy a message from the ringbuffer - being careful of wraparound
-*/
-static inline void tnet_copyin(unsigned *dest,unsigned *src,int size)
-{
- unsigned *limit = (unsigned *)system_ringbuf.ringbuf +
- (SYSTEM_RINGBUF_SIZE>>2);
- int size1 = limit - src;
-
- if (size < size1)
- size1 = size;
-
- size -= size1;
- while (size1--) {
- *dest++ = *src++;
- }
- src = system_ringbuf.ringbuf;
- while (size--) {
- *dest++ = *src++;
- }
-}
-
-
-/*
- put some data into a tasks ringbuffer. size is in words.
- */
-static inline void memcpy_to_rbuf(unsigned tid,unsigned *msgp,unsigned size)
-{
- struct aplib_struct *aplib;
- unsigned octx, ctx;
- struct task_struct *tsk;
- unsigned room;
-
- tsk = task[tid];
- if (!tsk || !tsk->aplib)
- return;
-
- octx = srmmu_get_context();
- ctx = MPP_TASK_TO_CTX(tid);
- if (octx != ctx)
- srmmu_set_context(ctx);
- aplib = tsk->aplib;
-
- if (aplib->write_pointer < aplib->read_pointer)
- room = aplib->read_pointer - (aplib->write_pointer+1);
- else
- room = aplib->ringbuf_size -
- ((aplib->write_pointer+1)-aplib->read_pointer);
-
- if (room < size) {
- send_sig(SIGLOST,tsk,1);
- goto finished;
- }
-
- tnet_copyin(&aplib->ringbuf[aplib->write_pointer], msgp, size);
-
- aplib->write_pointer += size;
- if (aplib->write_pointer >= aplib->ringbuf_size)
- aplib->write_pointer -= aplib->ringbuf_size;
-
- aplib->rbuf_flag1++;
-
-finished:
- if (octx != ctx)
- srmmu_set_context(octx);
-}
-
-
-
-/* a aplib message has arrived on the system message queue - process
- it immediately and return the number of bytes taken by the message in
- the system ringbuffer
-
- Note that this function may be called from interrupt level
- */
-static inline void aplib_system_recv(unsigned *msgp)
-{
- unsigned tag = msgp[1]>>28;
- unsigned size, tid;
-
- if (tag == RBUF_BIGSEND) {
- aplib_bigrecv(msgp);
- return;
- }
-
- size = (msgp[0]&0xFFFFF);
- tid = (msgp[1]&0x3FF);
-
- memcpy_to_rbuf(tid,msgp,size+2);
-}
-
-
-void tnet_ip_complete(struct sk_buff *skb,int from)
-{
-#if IP_DEBUG
- char *data = skb->data;
- int i;
- printk("CID(%d) tnet ip complete from %d\n",_cid,from);
-
- for (i=0;i<skb->len;i+=4)
- printk("(%08x)%c",*(int *)(data+i),i==32?'\n':' ');
- printk("\n");
-#endif
- /* ap_phys_put(from,(u_long)&dummy,4,MC_INTP_0,0,0); */
- bif_rx(skb);
- tnet_stats.bytes_received += skb->len;
- tnet_stats.packets_received++;
-}
-
-
-static void tnet_ip_recv(int cid,u_long *info)
-{
- u_long flag;
- u_long ipsize = info[1];
- u_long remote_addr = info[0];
- u_long remote_flag = info[2];
- struct sk_buff *skb = dev_alloc_skb(ipsize+8);
- char *p;
-
- if (!skb) {
- ap_put(cid,0,0,0,remote_flag,0);
- ap_phys_put(cid,(u_long)&dummy,4,MC_INTP_0,0,0);
- tnet_stats.alloc_errors++;
- return;
- }
-
- skb_reserve(skb,8); /* align on 16 byte boundary */
-
- flag = tnet_add_completion(tnet_ip_complete,(int)skb,(int)cid);
-
- p = (char *)skb_put(skb,ipsize);
-#if 0
-{
- static unsigned count=0;
- if (count%500 == 0)
- printk("CID(%d) fetching %d bytes from %x to %x\n",
- _cid,ipsize,remote_addr,p);
- count++;
-}
-#endif
- ap_get(cid,p,ipsize,remote_addr,flag,remote_flag);
- ap_phys_get(cid,MC_INTP_0,4,(u_long)&dummy,0,0);
-#if IP_DEBUG
- printk("CID(%d) ip packet of length %ld from %ld\n",_cid,ipsize,cid);
-#endif
-}
-
-
-static void tnet_ip_recv_small(u_long *data,int size)
-{
- struct sk_buff *skb = dev_alloc_skb(size+8);
- if (skb) {
- skb_reserve(skb,8);
- tnet_copyin((unsigned *)skb_put(skb,size),(unsigned *)data,(size+3)>>2);
- bif_rx(skb);
- tnet_stats.bytes_received += size;
- tnet_stats.packets_received++;
- tnet_stats.small_packets_received++;
- } else {
- tnet_stats.alloc_errors++;
- }
-}
-
-
-/* we've got an RPC from a remote cell */
-static void tnet_rpc_recv(u_long *data,int size)
-{
- struct fnp {
- void (*fn)();
- } fnp;
- fnp = *(struct fnp *)data;
- fnp.fn(data,size);
-}
-
-/*
- * receive messages from the system ringbuffer. We don't bother with
- * all the niceities that are done in user space, we just always
- * process the messages in order
- */
-static inline void tnet_recv(void)
-{
- unsigned flags;
- u_long from,*data,fix,align,size1,size,type;
-
- if (system_recv_flag == system_recv_count)
- return;
-
- save_flags(flags); cli();
- while (system_recv_flag != system_recv_count) {
- u_long read_ptr =
- (system_read_ptr + 1) % (SYSTEM_RINGBUF_SIZE>>5);
- u_long *msgp =
- ((u_long *)system_ringbuf.ringbuf) + (read_ptr<<3);
- u_long tag = (msgp[1]>>28) & 0xF;
- size1 = (msgp[0]&0xFFFFF)<<2;
-
- /* move our read pointer past this message */
- system_read_ptr = (system_read_ptr +
- ((size1+8+31)>>5))%(SYSTEM_RINGBUF_SIZE>>5);
- system_recv_count++;
-
-
- if (tag != RBUF_SYSTEM) {
- aplib_system_recv(msgp);
- continue;
- }
-
- from = msgp[0] >> 22;
- data = msgp+2;
- fix = (msgp[0]>>20)&3;
- align = (msgp[1]>>26)&3;
- size = ((size1 - align) & ~3) | fix;
- type = (msgp[1]&0xFF);
-
- switch (type) {
- case TNET_IP:
- tnet_ip_recv(from,data);
- break;
-
- case TNET_IP_SMALL:
- tnet_ip_recv_small(data,size);
- break;
-
- case TNET_RPC:
- tnet_rpc_recv(data,size);
- break;
-
- default:
- tnet_stats.errors++;
- printk("unknown Tnet type %ld\n",type);
- }
-
-#if DEBUG
- printk("CID(%d) recvd %d bytes of type %d read_ptr=%x\n",
- _cid,size,type,system_read_ptr);
-#endif
- }
- restore_flags(flags);
-}
-
-
-#define COMPLETION_LIST_LENGTH 256
-
-static unsigned completion_list_rp = 0;
-static unsigned completion_list_wp = 0;
-
-static volatile struct completion_struct {
- u_long flag;
- void (*fn)(int a1,...);
- u_long args[2];
-} completion_list[COMPLETION_LIST_LENGTH];
-
-
-void tnet_check_completion(void)
-{
- struct completion_struct *cs;
- unsigned flags;
-
- tnet_recv();
-
- if (completion_list[completion_list_rp].flag != 2)
- return;
-
- save_flags(flags); cli();
-
- while (completion_list[completion_list_rp].flag == 2) {
- cs = &completion_list[completion_list_rp];
- cs->flag = 0;
- if (++completion_list_rp == COMPLETION_LIST_LENGTH)
- completion_list_rp = 0;
-
- restore_flags(flags);
-
- cs->fn(cs->args[0],cs->args[1]);
-
- if (completion_list[completion_list_rp].flag != 2)
- return;
-
- save_flags(flags); cli();
- }
-
- restore_flags(flags);
-}
-
-
-static u_long tnet_add_completion(void (*fn)(int a1,...),int a1,int a2)
-{
- unsigned flags;
- struct completion_struct *cs;
-
- save_flags(flags); cli();
-
- while (completion_list[completion_list_wp].flag != 0)
- tnet_check_completion();
-
- cs = &completion_list[completion_list_wp];
-
- if (++completion_list_wp == COMPLETION_LIST_LENGTH)
- completion_list_wp = 0;
-
- restore_flags(flags);
-
- cs->flag = 1;
- cs->fn = fn;
- cs->args[0] = a1;
- cs->args[1] = a2;
-
- return (u_long)&cs->flag;
-}
-
-
-/*
- * send a message to the tnet ringuffer on another cell. When the send has
- * completed call fn with the args supplied
- */
-static void tnet_send(long cid,long type,char *src_addr,long byteSize,
- int immediate,u_long flag)
-{
- int wordSize;
- int byteAlign, byteFix;
- u_long src;
- u_long info1, info2;
- volatile u_long *entry = (volatile u_long *)MSC_SEND_QUEUE_S;
- SAVE_PID();
-
- byteAlign = ((u_long)src_addr) & 0x3;
- byteFix = byteSize & 0x3;
-
- src = (u_long)src_addr & ~3;
-
- wordSize = (byteSize + byteAlign + 3) >> 2;
-
- info1 = (_cid << 22) | (byteFix << 20) | wordSize;
- info2 = (RBUF_SYSTEM<<28) | (byteAlign << 26) | type;
-
- *entry = tnet_rel_cid_table[cid];
- *entry = wordSize;
- *entry = (u_long)&system_recv_flag;
- *entry = flag;
- *entry = (u_long)src;
- *entry = 0;
- *entry = info1;
- *entry = info2;
- RESTORE_PID();
-
- ap_phys_put(cid,(u_long)&dummy,4,MC_INTP_0,0,0);
- if (immediate && flag)
- ap_phys_put(_cid,(u_long)&dummy,4,MC_INTP_0,0,0);
-}
-
-
-static void free_skb(struct sk_buff *skb, int op)
-{
- dev_kfree_skb(skb);
-}
-
-void tnet_send_ip(int cid,struct sk_buff *skb)
-{
- char *data = skb->data + sizeof(struct cap_request);
- int size = skb->len - sizeof(struct cap_request);
- u_long flag;
-#if IP_DEBUG
- int i;
- for (i=0;i<size;i+=4)
- printk("[%08x]%c",*(int *)(data+i),i==32?'\n':' ');
- printk("\n");
-#endif
- if (size > TNET_IP_THRESHOLD) {
- int *info = (int *)skb->data; /* re-use the header */
- info[0] = (int)data;
- info[1] = size;
- info[2] = tnet_add_completion(free_skb, (int)skb, 0);
- tnet_send(cid,TNET_IP,info,sizeof(int)*3,0,0);
- } else {
- flag = tnet_add_completion(free_skb, (int)skb, 0);
- tnet_send(cid,TNET_IP_SMALL,data,size,0,flag);
- tnet_stats.small_packets_sent++;
- }
- tnet_stats.packets_sent++;
- tnet_stats.bytes_sent += size;
-#if IP_DEBUG
- printk("CID(%d) sent IP of size %d to %d\n",_cid,size,cid);
-#endif
-}
-
-static void reschedule(void)
-{
- current->need_resched = 1;
- mark_bh(TQUEUE_BH);
-}
-
-
-/* make a remote procedure call
- If free is set then free the data after sending it
- The first element of data is presumed to be a function pointer
-*/
-int tnet_rpc(int cell,char *data,int size,int free)
-{
- unsigned flag=0;
-
- if (free) {
- flag = tnet_add_completion(kfree,data,0);
- }
-
- tnet_send(cell,TNET_RPC,data,size,0,flag);
- return 0;
-}
-
-
-static void iport_irq(int irq, void *dev_id, struct pt_regs *regs)
-{
- int i;
- u_long intr = MC_IN(MC_INTR_PORT);
-
- for (i=0;i<4;i++) {
- if (intr & (AP_INTR_REQ << iports[i].shift)) {
- MC_OUT(MC_INTR_PORT,AP_CLR_INTR_REQ << iports[i].shift);
- if (iports[i].fn) iports[i].fn();
- }
- }
-}
-
-
-void ap_tnet_init(void)
-{
- int i;
-
- bif_add_debug_key('T',tnet_info,"Tnet status");
-
- memset(completion_list,0,sizeof(completion_list));
-
- request_irq(APIPORT_IRQ, iport_irq, SA_INTERRUPT, "iport", 0);
-
- for (i=0;i<4;i++) {
- MC_OUT(MC_INTR_PORT,AP_CLR_INTR_REQ << iports[i].shift);
- MC_OUT(MC_INTR_PORT,AP_CLR_INTR_MASK << iports[i].shift);
- }
-
-
- tnet_rel_cid_table = (int *)kmalloc(sizeof(int)*_ncel,GFP_ATOMIC);
- for (i=0;i<_ncel;i++)
- tnet_rel_cid_table[i] = rel_cid(i);
-
- if(_cid == 0) {
- xy_global_head = (((_ncelx -1) << 8) & 0xff00) |
- ((_ncely - 1) & 0xff);
- }
- else {
- for(i = 1; i < _ncel; i *= 2){
- if(i & _cid) {
- int rcidx = (_cid-i)%_ncelx - _cid%_ncelx;
- int rcidy = (_cid-i)/_ncelx - _cid/_ncelx;
- xy_global_head = ((rcidx << 8) & 0xff00) |
- (rcidy & 0xff);
- break;
- }
- }
- }
-}
-
-static void tnet_info(void)
-{
- struct completion_struct *cs;
-
- printk(
- "errors=%d alloc_errors=%d
-bytes_received=%d bytes_sent=%d
-packets_received=%d packets_sent=%d
-small_received=%d small_sent=%d
-",
- tnet_stats.errors, tnet_stats.alloc_errors,
- tnet_stats.bytes_received,
- tnet_stats.bytes_sent, tnet_stats.packets_received,
- tnet_stats.packets_sent, tnet_stats.small_packets_received,
- tnet_stats.small_packets_sent);
-
- printk("recv_flag=%d recv_count=%d read_ptr=%d\n",
- system_recv_flag,system_recv_count,system_read_ptr);
- printk("completion_list_rp=%d completion_list_wp=%d\n",
- completion_list_rp,completion_list_wp);
-}
diff --git a/arch/sparc/ap1000/util.c b/arch/sparc/ap1000/util.c
deleted file mode 100644
index 1fe23dc41..000000000
--- a/arch/sparc/ap1000/util.c
+++ /dev/null
@@ -1,436 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/* general utility functions for the AP1000 */
-
-#include <linux/sched.h>
-#include <asm/ap1000/apservice.h>
-#include <asm/ap1000/apreg.h>
-#include <asm/asi.h>
-#include <asm/delay.h>
-#include <asm/pgtable.h>
-#include <linux/malloc.h>
-#include <linux/mm.h>
-#include <linux/mpp.h>
-
-#define APLOG 0
-
-struct cap_init cap_init;
-
-/* find what cell id we are running on */
-int mpp_cid(void)
-{
- return(BIF_IN(BIF_CIDR1));
-}
-
-/* find how many cells there are */
-int mpp_num_cells(void)
-{
- return(cap_init.numcells);
-}
-
-/* this can be used to ensure some data is readable before DMAing
- it. */
-int ap_verify_data(char *d,int len)
-{
- int res = 0;
- while (len--) res += *d++;
- return res;
-}
-
-/* How many BogoMIPS in the entire machine
-Don't worry about float because when it gets this big, it's irrelevant */
-int mpp_agg_bogomips(void)
-{
- return mpp_num_cells()*loops_per_sec/500000; /* cheat in working it out */
-}
-
-/* Puts multiprocessor configuration info into a buffer */
-int get_mppinfo(char *buffer)
-{
- return sprintf(buffer,
- "Machine Type:\t\t: %s\nNumber of Cells\t\t: %d\nAggregate BogoMIPS\t: %d\n",
- "Fujitsu AP1000+",
- mpp_num_cells(),
- mpp_agg_bogomips());
-}
-
-#if APLOG
-static int do_logging = 0;
-
-
-void ap_log(char *buf,int len)
-{
-#define LOG_MAGIC 0x8736526
- static char *logbase;
- static char *logptr;
- static int logsize = 1024;
- int l,i;
-
- if (buf == NULL && len == -1) {
- logbase = kmalloc(logsize + 8,GFP_ATOMIC);
-
- if (!logbase) {
- printk("log init failed\n");
- return;
- }
- for (i=0;i<logsize;i++)
- if (logbase[8+i] == '|')
- logbase[8+i] = '_';
-
- if ((*(int *)logbase) == LOG_MAGIC) {
- int oldoffset = *(int *)(logbase + 4);
- printk("==%3d== START OLD LOG ==\n",mpp_cid());
- ap_write(1,logbase + 8 + oldoffset,logsize - oldoffset);
- ap_write(1,logbase+8,oldoffset);
- printk("==%3d== END OLD LOG ==\n",mpp_cid());
- }
- *(int *)logbase = LOG_MAGIC;
- *(int *)(logbase+4) = 0;
- logbase += 8;
- logptr = logbase;
- memset(logbase,0,logsize);
- do_logging = 1;
- return;
- }
-
- if (!do_logging) return;
-
- while (len) {
- l = logsize - (logptr - logbase);
- if (l > len) l = len;
- memcpy(logptr,buf,l);
- len -= l;
- logptr += l;
- if (logptr == logbase + logsize)
- logptr = logbase;
- }
- *(int *)(logbase - 4) = (logptr - logbase);
-}
-#endif
-
-int ap_current_uid = -1;
-
-/* set output only to a particular uid */
-void ap_set_user(int uid)
-{
- ap_current_uid = uid;
-}
-
-/* write some data to a filedescriptor on the front end */
-int ap_write(int fd,char *buf,int nbytes)
-{
- struct cap_request req;
-
- if (nbytes == 0) return 0;
-
-#if APLOG
- ap_log(buf,nbytes);
-
- if (buf[0] == '|') return nbytes;
-#endif
-
- req.cid = mpp_cid();
- req.type = REQ_WRITE;
- req.size = nbytes + sizeof(req);
- req.data[0] = fd;
- if (ap_current_uid == -1 && current && current->pid) {
- req.data[1] = current->uid;
- } else {
- req.data[1] = ap_current_uid;
- }
- req.header = MAKE_HEADER(HOST_CID);
-
- bif_queue(&req,buf,nbytes);
-
- return(nbytes);
-}
-
-/* write one character to stdout on the front end */
-int ap_putchar(char c)
-{
- struct cap_request req;
-
-#if APLOG
- ap_log(&c,1);
-#endif
-
- req.cid = mpp_cid();
- req.type = REQ_PUTCHAR;
- req.size = sizeof(req);
- req.data[0] = c;
- req.header = MAKE_HEADER(HOST_CID);
-
- bif_queue(&req,0,0);
-
- return(0);
-}
-
-/* start the debugger (kgdb) on this cell */
-void ap_start_debugger(void)
-{
- static int done = 0;
- extern void set_debug_traps(void);
- extern void breakpoint(void);
- if (!done)
- set_debug_traps();
- done = 1;
- breakpoint();
-}
-
-void ap_panic(char *msg,int a1,int a2,int a3,int a4,int a5)
-{
- ap_led(0xAA);
- printk(msg,a1,a2,a3,a4,a5);
- ap_start_debugger();
-}
-
-void ap_printk(char *msg,int a1,int a2,int a3,int a4,int a5)
-{
- printk(msg,a1,a2,a3,a4,a5);
- /* bif_queue_flush(); */
-}
-
-/* get the command line arguments from the front end */
-void ap_getbootargs(char *buf)
-{
- struct cap_request req;
- int size;
-
- req.cid = mpp_cid();
- req.type = REQ_GETBOOTARGS;
- req.size = sizeof(req);
- req.header = MAKE_HEADER(HOST_CID);
-
- write_bif_polled((char *)&req,sizeof(req),NULL,0);
-
- ap_wait_request(&req,REQ_GETBOOTARGS);
-
- size = req.size - sizeof(req);
- if (size == 0)
- buf[0] = '\0';
- else {
- read_bif(buf, size);
- }
-
- req.cid = mpp_cid();
- req.type = REQ_INIT;
- req.size = sizeof(req);
- req.header = MAKE_HEADER(HOST_CID);
-
- write_bif_polled((char *)&req,sizeof(req),NULL,0);
-
- ap_wait_request(&req,REQ_INIT);
-
- if (req.size != sizeof(req))
- read_bif((char *)&cap_init,req.size - sizeof(req));
- if ((req.size - sizeof(req)) != sizeof(cap_init))
- printk("WARNING: Init structure is wrong size, recompile util.c\n");
-
- if (cap_init.gdbcell == mpp_cid())
- ap_start_debugger();
-
- printk("Got command line arguments from server\n");
-}
-
-/* a useful utility for debugging pagetable setups */
-void show_mapping_ctx(unsigned *ctp,int context,unsigned Vm)
-{
- unsigned *pgtable;
- int entry[3];
- int level = 0;
-
- if (!ctp) ctp = (unsigned *)mmu_p2v(srmmu_get_ctable_ptr());
-
- printk("ctp=0x%x ",(int)ctp);
-
- pgtable = ctp + context;
-
- /* get the virtual page */
- Vm = Vm>>12;
-
- printk("Vm page 0x%x is ",Vm);
-
- entry[0] = Vm>>12;
- entry[1] = (Vm>>6) & 0x3f;
- entry[2] = Vm & 0x3f;
-
- while (1) {
-
-#if 1
- printk("(%08x) ",pgtable[0]);
-#endif
-
- if ((pgtable[0] & 3) == 2) {
- printk("mapped at level %d to 0x%x\n",level,pgtable[0]>>8);
- return;
- }
-
- if ((pgtable[0] & 3) == 0) {
- printk("unmapped at level %d\n",level);
- return;
- }
-
- if ((pgtable[0] & 3) == 3) {
- printk("invalid at level %d\n",level);
- return;
- }
-
- if ((pgtable[0] & 3) == 1) {
- pgtable = (unsigned *)(((pgtable[0]>>2)<<6)|0xf0000000);
- pgtable += entry[level];
- level++;
- }
- }
-}
-
-
-
-static unsigned char current_led = 0;
-
-void ap_led(unsigned char d)
-{
- unsigned paddr = 0x1000;
- unsigned word = 0xff & ~d;
- current_led = d;
- __asm__ __volatile__("sta %0, [%1] %2\n\t" : :
- "r" (word), "r" (paddr), "i" (0x2c) :
- "memory");
-}
-
-void ap_xor_led(unsigned char d)
-{
- ap_led(current_led ^ d);
-}
-
-void ap_set_led(unsigned char d)
-{
- ap_led(current_led | d);
-}
-
-void ap_unset_led(unsigned char d)
-{
- ap_led(current_led & ~d);
-}
-
-
-void kbd_put_char(char c)
-{
- ap_putchar(c);
-}
-
-
-void ap_enter_irq(int irq)
-{
- unsigned char v = current_led;
- switch (irq) {
- case 2: v |= (1<<1); break;
- case 4: v |= (1<<2); break;
- case 8: v |= (1<<3); break;
- case 9: v |= (1<<4); break;
- case 10: v |= (1<<5); break;
- case 11: v |= (1<<6); break;
- default: v |= (1<<7); break;
- }
- ap_led(v);
-}
-
-void ap_exit_irq(int irq)
-{
- unsigned char v = current_led;
- switch (irq) {
- case 2: v &= ~(1<<1); break;
- case 4: v &= ~(1<<2); break;
- case 8: v &= ~(1<<3); break;
- case 9: v &= ~(1<<4); break;
- case 10: v &= ~(1<<5); break;
- case 11: v &= ~(1<<6); break;
- default: v &= ~(1<<7); break;
- }
- ap_led(v);
-}
-
-
-static DECLARE_WAIT_QUEUE_HEAD(timer_wait);
-
-static void wait_callback(unsigned long _ignored)
-{
- wake_up(&timer_wait);
-}
-
-/* wait till x == *p */
-int wait_on_int(volatile int *p,int x,int interval)
-{
- struct timer_list *timer = kmalloc(sizeof(*timer),GFP_KERNEL);
- if (!timer) panic("out of memory in wait_on_int()\n");
- timer->next = NULL;
- timer->prev = NULL;
- timer->data = 0;
- timer->function = wait_callback;
- while (*p != x) {
- timer->expires = jiffies + interval;
- add_timer(timer);
- interruptible_sleep_on(&timer_wait);
- del_timer(timer);
- if (signal_pending(current))
- return -EINTR;
- }
- kfree_s(timer,sizeof(*timer));
- return 0;
-}
-
-
-/* an ugly hack to get nfs booting from a central cell to work */
-void ap_nfs_hook(unsigned long server)
-{
- unsigned cid = server - cap_init.baseIP;
- if (cid < cap_init.bootcid + cap_init.numcells &&
- cid != mpp_cid()) {
- unsigned end = jiffies + 20*HZ;
- /* we are booting from another cell */
- printk("waiting for the master cell\n");
- while (time_before(jiffies, end)) ;
- printk("continuing\n");
- }
-}
-
-/* convert a IP address to a cell id */
-int ap_ip_to_cid(u_long ip)
-{
- unsigned cid;
-
- if ((ip & cap_init.netmask) != (cap_init.baseIP & cap_init.netmask))
- return -1;
-
- if ((ip & ~cap_init.netmask) == AP_ALIAS_IP)
- cid = cap_init.bootcid;
- else
- cid = ip - cap_init.baseIP;
- if (cid >= cap_init.bootcid + cap_init.numcells)
- return -1;
- return cid;
-}
-
-
-void ap_reboot(char *bootstr)
-{
- printk("cell(%d) - don't know how to reboot\n",mpp_cid());
- sti();
- while (1) ;
-}
-
-
-void dumb_memset(char *buf,char val,int len)
-{
- while (len--) *buf++ = val;
-}
-
-void ap_init_time(struct timeval *xtime)
-{
- xtime->tv_sec = cap_init.init_time;
- xtime->tv_usec = 0;
-}
diff --git a/arch/sparc/config.in b/arch/sparc/config.in
index 8d3562e37..a983b9a6d 100644
--- a/arch/sparc/config.in
+++ b/arch/sparc/config.in
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.81 2000/01/22 05:14:44 zaitcev Exp $
+# $Id: config.in,v 1.84 2000/01/31 21:10:04 davem Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
@@ -19,43 +19,33 @@ define_bool CONFIG_VT_CONSOLE y
bool 'Symmetric multi-processing support (does not work on sun4/sun4c)' CONFIG_SMP
-bool 'Support for AP1000 multicomputer' CONFIG_AP1000
-if [ "$CONFIG_AP1000" = "y" ]; then
- define_bool CONFIG_NO_KEYBOARD y
- define_bool CONFIG_FDDI y
- define_bool CONFIG_APFDDI y
- define_bool CONFIG_APBLOCK y
- define_bool CONFIG_APBIF y
- tristate ' OPIU DDV Driver' CONFIG_DDV
-else
- bool 'Support for SUN4 machines (disables SUN4[CDM] support)' CONFIG_SUN4
- if [ "$CONFIG_SUN4" != "y" ]; then
- bool ' Support for PCI and PS/2 keyboard/mouse' CONFIG_PCI
- source drivers/pci/Config.in
- fi
+bool 'Support for SUN4 machines (disables SUN4[CDM] support)' CONFIG_SUN4
+if [ "$CONFIG_SUN4" != "y" ]; then
+ bool ' Support for PCI and PS/2 keyboard/mouse' CONFIG_PCI
+ source drivers/pci/Config.in
+fi
- mainmenu_option next_comment
- comment 'Console drivers'
- bool 'PROM console' CONFIG_PROM_CONSOLE
- source drivers/video/Config.in
- endmenu
+mainmenu_option next_comment
+comment 'Console drivers'
+bool 'PROM console' CONFIG_PROM_CONSOLE
+source drivers/video/Config.in
+endmenu
- # Global things across all Sun machines.
- define_bool CONFIG_SBUS y
- define_bool CONFIG_SBUSCHAR y
- define_bool CONFIG_BUSMOUSE y
- define_bool CONFIG_SUN_MOUSE y
- define_bool CONFIG_SERIAL y
- define_bool CONFIG_SUN_SERIAL y
- define_bool CONFIG_SERIAL_CONSOLE y
- define_bool CONFIG_SUN_KEYBOARD y
- define_bool CONFIG_SUN_CONSOLE y
- define_bool CONFIG_SUN_AUXIO y
- define_bool CONFIG_SUN_IO y
- if [ "$CONFIG_SUN4" != "y" ]; then
- source drivers/sbus/char/Config.in
- source drivers/sbus/audio/Config.in
- fi
+# Global things across all Sun machines.
+define_bool CONFIG_SBUS y
+define_bool CONFIG_SBUSCHAR y
+define_bool CONFIG_BUSMOUSE y
+define_bool CONFIG_SUN_MOUSE y
+define_bool CONFIG_SERIAL y
+define_bool CONFIG_SUN_SERIAL y
+define_bool CONFIG_SERIAL_CONSOLE y
+define_bool CONFIG_SUN_KEYBOARD y
+define_bool CONFIG_SUN_CONSOLE y
+define_bool CONFIG_SUN_AUXIO y
+define_bool CONFIG_SUN_IO y
+if [ "$CONFIG_SUN4" != "y" ]; then
+ source drivers/sbus/char/Config.in
+ source drivers/sbus/audio/Config.in
fi
tristate 'Openprom tree appears in /proc/openprom' CONFIG_SUN_OPENPROMFS
@@ -161,7 +151,10 @@ if [ "$CONFIG_NET" = "y" ]; then
tristate ' Dummy net driver support' CONFIG_DUMMY
tristate ' PPP (point-to-point) support' CONFIG_PPP
if [ ! "$CONFIG_PPP" = "n" ]; then
- comment 'CCP compressors for PPP are only built as modules.'
+ dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP
+ dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP
+ dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP
+ dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP m
fi
tristate ' SLIP (serial line) support' CONFIG_SLIP
if [ "$CONFIG_SLIP" != "n" ]; then
diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig
index 26037c33e..536d0c5f6 100644
--- a/arch/sparc/defconfig
+++ b/arch/sparc/defconfig
@@ -14,7 +14,6 @@ CONFIG_EXPERIMENTAL=y
CONFIG_VT=y
CONFIG_VT_CONSOLE=y
# CONFIG_SMP is not set
-# CONFIG_AP1000 is not set
# CONFIG_SUN4 is not set
# CONFIG_PCI is not set
@@ -22,7 +21,6 @@ CONFIG_VT_CONSOLE=y
# Console drivers
#
CONFIG_PROM_CONSOLE=y
-CONFIG_FB=y
#
# Frame-buffer support
@@ -217,10 +215,10 @@ CONFIG_SCSI_FCAL=m
CONFIG_NETDEVICES=y
CONFIG_DUMMY=m
CONFIG_PPP=m
-
-#
-# CCP compressors for PPP are only built as modules.
-#
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
CONFIG_SLIP=m
CONFIG_SLIP_COMPRESSED=y
CONFIG_SLIP_SMART=y
@@ -242,10 +240,12 @@ CONFIG_UNIX98_PTY_COUNT=256
#
# CONFIG_QUOTA is not set
CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
# CONFIG_ADFS_FS is not set
CONFIG_AFFS_FS=m
# CONFIG_HFS_FS is not set
# CONFIG_BFS_FS is not set
+# CONFIG_BFS_FS_WRITE is not set
CONFIG_FAT_FS=m
CONFIG_MSDOS_FS=m
# CONFIG_UMSDOS_FS is not set
@@ -256,23 +256,27 @@ CONFIG_ISO9660_FS=m
# CONFIG_JOLIET is not set
CONFIG_MINIX_FS=m
# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
CONFIG_HPFS_FS=m
CONFIG_PROC_FS=y
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
CONFIG_ROMFS_FS=m
CONFIG_EXT2_FS=y
CONFIG_SYSV_FS=m
# CONFIG_SYSV_FS_WRITE is not set
# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
CONFIG_UFS_FS=m
-CONFIG_UFS_FS_WRITE=y
+# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
CONFIG_CODA_FS=m
CONFIG_NFS_FS=y
+# CONFIG_ROOT_NFS is not set
CONFIG_NFSD=m
# CONFIG_NFSD_V3 is not set
CONFIG_SUNRPC=y
@@ -295,7 +299,6 @@ CONFIG_NCP_FS=m
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-# CONFIG_SGI_PARTITION is not set
CONFIG_SUN_PARTITION=y
CONFIG_NLS=y
diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S
index eb3d007f0..56b3da66a 100644
--- a/arch/sparc/kernel/head.S
+++ b/arch/sparc/kernel/head.S
@@ -1,4 +1,4 @@
-/* $Id: head.S,v 1.101 1999/12/02 08:34:56 jj Exp $
+/* $Id: head.S,v 1.102 2000/01/29 01:08:54 anton Exp $
* head.S: The initial boot code for the Sparc port of Linux.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -483,10 +483,8 @@ current_pc:
1:
mov %o7, %g3
-#ifndef CONFIG_AP1000
tst %o0
be no_sun4u_here
-#endif
mov %g4, %o7 /* Previous %o7. */
mov %o0, %l0 ! stash away romvec
@@ -762,11 +760,6 @@ go_to_highmem:
* I figure out and store nwindows and nwindowsm1 later on.
*/
execute_in_high_mem:
-#if CONFIG_AP1000
- /* we don't have a prom :-( */
- b sun4m_init
- nop
-#endif
mov %l0, %o0 ! put back romvec
mov %l1, %o1 ! and debug_vec
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index c0ffb2675..61a51f103 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -1,4 +1,4 @@
-/* $Id: ioport.c,v 1.29 2000/01/22 07:35:25 zaitcev Exp $
+/* $Id: ioport.c,v 1.30 2000/01/28 13:41:55 jj Exp $
* ioport.c: Simple io mapping allocator.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c
index c89d04872..8e8fab320 100644
--- a/arch/sparc/kernel/irq.c
+++ b/arch/sparc/kernel/irq.c
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.99 1999/12/27 06:08:29 anton Exp $
+/* $Id: irq.c,v 1.100 2000/01/29 01:38:04 anton Exp $
* arch/sparc/kernel/irq.c: Interrupt request handling routines. On the
* Sparc the IRQ's are basically 'cast in stone'
* and you are supposed to probe the prom's device
@@ -739,12 +739,6 @@ void __init init_IRQ(void)
sun4d_init_IRQ();
break;
- case ap1000:
-#if CONFIG_AP1000
- ap_init_IRQ();;
- break;
-#endif
-
default:
prom_printf("Cannot initialize IRQ's on this Sun machine...");
break;
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c
index 420efe1e1..c24d8649c 100644
--- a/arch/sparc/kernel/process.c
+++ b/arch/sparc/kernel/process.c
@@ -1,4 +1,4 @@
-/* $Id: process.c,v 1.144 2000/01/21 11:38:39 jj Exp $
+/* $Id: process.c,v 1.145 2000/01/29 01:08:56 anton Exp $
* linux/arch/sparc/kernel/process.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -266,9 +266,6 @@ void show_stackframe(struct sparc_stackf *sf)
void show_regs(struct pt_regs * regs)
{
-#if __MPP__
- printk("CID: %d\n",mpp_cid());
-#endif
printk("PSR: %08lx PC: %08lx NPC: %08lx Y: %08lx\n", regs->psr,
regs->pc, regs->npc, regs->y);
printk("g0: %08lx g1: %08lx g2: %08lx g3: %08lx ",
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c
index 60928d7aa..50d682929 100644
--- a/arch/sparc/kernel/setup.c
+++ b/arch/sparc/kernel/setup.c
@@ -1,4 +1,4 @@
-/* $Id: setup.c,v 1.113 1999/12/16 14:37:35 anton Exp $
+/* $Id: setup.c,v 1.114 2000/01/29 01:08:57 anton Exp $
* linux/arch/sparc/kernel/setup.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -201,11 +201,6 @@ static void __init boot_flags_init(char *commands)
prom_printf("KGDB: Using serial line /dev/ttyb.\n");
break;
#endif
-#ifdef CONFIG_AP1000
- case 'c':
- printk("KGDB: AP1000+ debugging\n");
- break;
-#endif
default:
printk("KGDB: Unknown tty line.\n");
break;
@@ -326,10 +321,6 @@ void __init setup_arch(char **cmdline_p)
prom_halt();
}
#endif
-#if CONFIG_AP1000
- sparc_cpu_model=ap1000;
- strcpy(&cputypval, "ap+");
-#endif
printk("ARCH: ");
switch(sparc_cpu_model) {
case sun4:
@@ -350,10 +341,6 @@ void __init setup_arch(char **cmdline_p)
case sun4u:
printk("SUN4U\n");
break;
- case ap1000:
- register_console(&prom_console);
- printk("AP1000\n");
- break;
default:
printk("UNKNOWN!\n");
break;
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c
index b8cdd3749..8df494f2d 100644
--- a/arch/sparc/kernel/sparc_ksyms.c
+++ b/arch/sparc/kernel/sparc_ksyms.c
@@ -1,4 +1,4 @@
-/* $Id: sparc_ksyms.c,v 1.87 2000/01/21 17:41:14 anton Exp $
+/* $Id: sparc_ksyms.c,v 1.88 2000/01/28 13:41:55 jj Exp $
* arch/sparc/kernel/ksyms.c: Sparc specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c
index 4dcb7866a..3815cae1b 100644
--- a/arch/sparc/kernel/sys_sparc.c
+++ b/arch/sparc/kernel/sys_sparc.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.57 2000/01/21 11:38:42 jj Exp $
+/* $Id: sys_sparc.c,v 1.59 2000/01/29 07:40:10 davem Exp $
* linux/arch/sparc/kernel/sys_sparc.c
*
* This file contains various random system calls that
@@ -383,12 +383,3 @@ done:
up_read(&uts_sem);
return err;
}
-
-
-#ifndef CONFIG_AP1000
-/* only AP+ systems have sys_aplib */
-asmlinkage int sys_aplib(void)
-{
- return -ENOSYS;
-}
-#endif
diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c
index 15f38bd5e..bb3a5ad36 100644
--- a/arch/sparc/kernel/sys_sunos.c
+++ b/arch/sparc/kernel/sys_sunos.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.111 2000/01/22 05:17:55 anton Exp $
+/* $Id: sys_sunos.c,v 1.112 2000/01/29 07:40:11 davem Exp $
* sys_sunos.c: SunOS specific syscall compatibility support.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S
index 47aea979b..174522d03 100644
--- a/arch/sparc/kernel/systbls.S
+++ b/arch/sparc/kernel/systbls.S
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.91 2000/01/16 06:20:44 davem Exp $
+/* $Id: systbls.S,v 1.93 2000/01/29 16:41:18 jj Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
@@ -47,7 +47,7 @@ sys_call_table:
/*130*/ .long sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall
/*135*/ .long sys_nis_syscall, sys_mkdir, sys_rmdir, sys_utimes, sys_stat64
/*140*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_getrlimit
-/*145*/ .long sys_setrlimit, sys_nis_syscall, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
+/*145*/ .long sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
/*150*/ .long sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall
/*155*/ .long sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
/*160*/ .long sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
@@ -70,7 +70,7 @@ sys_call_table:
/*240*/ .long sys_munlockall, sys_sched_setparam, sys_sched_getparam, sys_sched_setscheduler, sys_sched_getscheduler
/*245*/ .long sys_sched_yield, sys_sched_get_priority_max, sys_sched_get_priority_min, sys_sched_rr_get_interval, sys_nanosleep
/*250*/ .long sys_mremap, sys_sysctl, sys_getsid, sys_fdatasync, sys_nfsservctl
-/*255*/ .long sys_aplib, sys_nis_syscall
+/*255*/ .long sys_nis_syscall, sys_nis_syscall
#ifdef CONFIG_SUNOS_EMUL
/* Now the SunOS syscall table. */
@@ -164,6 +164,6 @@ sunos_sys_table:
.long sunos_nosys, sunos_nosys, sunos_nosys
.long sunos_nosys, sunos_nosys
/*250*/ .long sunos_nosys, sunos_nosys, sunos_nosys
- .long sunos_nosys, sunos_nosys, sys_aplib
+ .long sunos_nosys, sunos_nosys, sunos_nosys
#endif
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c
index 295988f58..3e52fef95 100644
--- a/arch/sparc/kernel/time.c
+++ b/arch/sparc/kernel/time.c
@@ -1,4 +1,4 @@
-/* $Id: time.c,v 1.50 2000/01/21 04:35:53 anton Exp $
+/* $Id: time.c,v 1.51 2000/01/29 01:08:59 anton Exp $
* linux/arch/sparc/kernel/time.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -353,12 +353,6 @@ void __init sbus_time_init(void)
BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM);
btfixup();
-#if CONFIG_AP1000
- init_timers(timer_interrupt);
- ap_init_time(&xtime);
- return;
-#endif
-
if (ARCH_SUN4)
sun4_clock_probe();
else
@@ -451,14 +445,6 @@ extern __inline__ unsigned long do_gettimeoffset(void)
*/
void do_gettimeofday(struct timeval *tv)
{
-#if CONFIG_AP1000
- unsigned long flags;
-
- save_and_cli(flags);
- ap_gettimeofday(&xtime);
- *tv = xtime;
- restore_flags(flags);
-#else /* !(CONFIG_AP1000) */
/* Load doubles must be used on xtime so that what we get
* is guarenteed to be atomic, this is why we can run this
* with interrupts on full blast. Don't touch this... -DaveM
@@ -493,7 +479,6 @@ void do_gettimeofday(struct timeval *tv)
sub %o5, %o2, %o5
st %o4, [%o0 + 0x0]
1: st %o5, [%o0 + 0x4]");
-#endif
}
void do_settimeofday(struct timeval *tv)
@@ -505,13 +490,11 @@ void do_settimeofday(struct timeval *tv)
static void sbus_do_settimeofday(struct timeval *tv)
{
-#if !CONFIG_AP1000
tv->tv_usec -= do_gettimeoffset();
if(tv->tv_usec < 0) {
tv->tv_usec += 1000000;
tv->tv_sec--;
}
-#endif
xtime = *tv;
time_adjust = 0; /* stop active adjtime() */
time_status |= STA_UNSYNC;
diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile
index 5e304411c..00a4f35d2 100644
--- a/arch/sparc/mm/Makefile
+++ b/arch/sparc/mm/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.35 1999/10/09 05:32:01 zaitcev Exp $
+# $Id: Makefile,v 1.36 2000/01/29 01:09:05 anton Exp $
# Makefile for the linux Sparc-specific parts of the memory manager.
#
# Note! Dependencies are done automagically by 'make dep', which also
@@ -9,9 +9,6 @@
O_TARGET := mm.o
O_OBJS := fault.o init.o loadmmu.o generic.o extable.o btfixup.o
-ifeq ($(CONFIG_AP1000),y)
-O_OBJS += asyncd.o
-endif
ifeq ($(CONFIG_SUN4),y)
O_OBJS += nosrmmu.o
else
diff --git a/arch/sparc/mm/asyncd.c b/arch/sparc/mm/asyncd.c
deleted file mode 100644
index 0034cb60b..000000000
--- a/arch/sparc/mm/asyncd.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/* $Id: asyncd.c,v 1.20 2000/01/21 11:38:47 jj Exp $
- * The asyncd kernel daemon. This handles paging on behalf of
- * processes that receive page faults due to remote (async) memory
- * accesses.
- *
- * Idea and skeleton code courtesy of David Miller (bless his cotton socks)
- *
- * Implemented by tridge
- */
-
-#include <linux/mm.h>
-#include <linux/malloc.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/kernel_stat.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/swap.h>
-#include <linux/fs.h>
-#include <linux/config.h>
-#include <linux/interrupt.h>
-
-#include <asm/dma.h>
-#include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for memcpy_to/fromfs */
-#include <asm/bitops.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-
-#define DEBUG 0
-
-#define WRITE_LIMIT 100
-#define LOOP_LIMIT 200
-
-static struct {
- int faults, read, write, success, failure, errors;
-} stats;
-
-/*
- * The wait queue for waking up the async daemon:
- */
-static DECLARE_WAIT_QUEUE_HEAD(asyncd_wait);
-
-struct async_job {
- volatile struct async_job *next;
- int taskid;
- struct mm_struct *mm;
- unsigned long address;
- int write;
- void (*callback)(int,unsigned long,int,int);
-};
-
-static volatile struct async_job *async_queue = NULL;
-static volatile struct async_job *async_queue_end = NULL;
-
-static void add_to_async_queue(int taskid,
- struct mm_struct *mm,
- unsigned long address,
- int write,
- void (*callback)(int,unsigned long,int,int))
-{
- struct async_job *a = kmalloc(sizeof(*a),GFP_ATOMIC);
-
- if (!a) {
- printk("ERROR: out of memory in asyncd\n");
- a->callback(taskid,address,write,1);
- return;
- }
-
- if (write)
- stats.write++;
- else
- stats.read++;
-
- a->next = NULL;
- a->taskid = taskid;
- a->mm = mm;
- a->address = address;
- a->write = write;
- a->callback = callback;
-
- if (!async_queue) {
- async_queue = a;
- } else {
- async_queue_end->next = a;
- }
- async_queue_end = a;
-}
-
-
-void async_fault(unsigned long address, int write, int taskid,
- void (*callback)(int,unsigned long,int,int))
-{
- struct task_struct *tsk = task[taskid];
- struct mm_struct *mm = tsk->mm;
-
- stats.faults++;
-
-#if 0
- printk("paging in %x for task=%d\n",address,taskid);
-#endif
-
- add_to_async_queue(taskid, mm, address, write, callback);
- wake_up(&asyncd_wait);
- mark_bh(TQUEUE_BH);
-}
-
-static int fault_in_page(int taskid,
- struct vm_area_struct *vma,
- unsigned address,int write)
-{
- static unsigned last_address;
- static int last_task, loop_counter;
- struct task_struct *tsk = task[taskid];
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *pte;
- siginfo_t info;
-
- if (!tsk || !tsk->mm)
- return 1;
-
- if (!vma || (write && !(vma->vm_flags & VM_WRITE)))
- goto bad_area;
- if (vma->vm_start > address)
- goto bad_area;
-
- if (address == last_address && taskid == last_task) {
- loop_counter++;
- } else {
- loop_counter = 0;
- last_address = address;
- last_task = taskid;
- }
-
- if (loop_counter == WRITE_LIMIT && !write) {
- printk("MSC bug? setting write request\n");
- stats.errors++;
- write = 1;
- }
-
- if (loop_counter == LOOP_LIMIT) {
- printk("MSC bug? failing request\n");
- stats.errors++;
- return 1;
- }
-
- pgd = pgd_offset(vma->vm_mm, address);
- pmd = pmd_alloc(pgd,address);
- if(!pmd)
- goto no_memory;
- pte = pte_alloc(pmd, address);
- if(!pte)
- goto no_memory;
- if(!pte_present(*pte)) {
- handle_mm_fault(tsk, vma, address, write);
- goto finish_up;
- }
- set_pte(pte, pte_mkyoung(*pte));
- flush_tlb_page(vma, address);
- if(!write)
- goto finish_up;
- if(pte_write(*pte)) {
- set_pte(pte, pte_mkdirty(*pte));
- flush_tlb_page(vma, address);
- goto finish_up;
- }
- handle_mm_fault(tsk, vma, address, write);
-
- /* Fall through for do_wp_page */
-finish_up:
- stats.success++;
- return 0;
-
-no_memory:
- stats.failure++;
- oom(tsk);
- return 1;
-
-bad_area:
- stats.failure++;
- info.si_signo = SIGSEGV;
- info.si_errno = 0;
- info.si_code = SEGV_MAPERR;
- info.si_addr = (void *)address;
- info.si_trapno = 0;
- send_sig_info(SIGSEGV, &info, tsk);
- return 1;
-}
-
-
-/* Note the semaphore operations must be done here, and _not_
- * in async_fault().
- */
-static void run_async_queue(void)
-{
- int ret;
- unsigned flags;
-
- while (async_queue) {
- volatile struct async_job *a;
- struct mm_struct *mm;
- struct vm_area_struct *vma;
-
- save_flags(flags); cli();
- a = async_queue;
- async_queue = async_queue->next;
- restore_flags(flags);
-
- mm = a->mm;
-
- down(&mm->mmap_sem);
- vma = find_vma(mm, a->address);
- ret = fault_in_page(a->taskid,vma,a->address,a->write);
-#if DEBUG
- printk("fault_in_page(task=%d addr=%x write=%d) = %d\n",
- a->taskid,a->address,a->write,ret);
-#endif
- a->callback(a->taskid,a->address,a->write,ret);
- up(&mm->mmap_sem);
- kfree_s((void *)a,sizeof(*a));
- }
-}
-
-
-#if CONFIG_AP1000
-static void asyncd_info(void)
-{
- printk("CID(%d) faults: total=%d read=%d write=%d success=%d fail=%d err=%d\n",
- mpp_cid(),stats.faults, stats.read, stats.write, stats.success,
- stats.failure, stats.errors);
-}
-#endif
-
-
-/*
- * The background async daemon.
- * Started as a kernel thread from the init process.
- */
-int asyncd(void *unused)
-{
- current->session = 1;
- current->pgrp = 1;
- sprintf(current->comm, "asyncd");
- sigfillset(&current->blocked); /* block all signals */
- recalc_sigpending(current);
-
- /* Give asyncd a realtime priority. */
- current->policy = SCHED_FIFO;
- current->priority = 32; /* Fixme --- we need to standardise our
- namings for POSIX.4 realtime scheduling
- priorities. */
-
- printk("Started asyncd\n");
-
-#if CONFIG_AP1000
- bif_add_debug_key('a',asyncd_info,"stats on asyncd");
-#endif
-
- while (1) {
- unsigned flags;
-
- save_flags(flags); cli();
-
- while (!async_queue) {
- spin_lock(&current->sigmask_lock);
- flush_signals(current);
- spin_unlock(&current->sigmask_lock);
- interruptible_sleep_on(&asyncd_wait);
- __sti(); cli();
- }
-
- restore_flags(flags);
-
- run_async_queue();
- }
-}
-
-#if CONFIG_AP1000
-
-static int __init init_ap1000(void)
-{
- kernel_thread(asyncd, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
- return 0;
-}
-
-module_init(init_ap1000)
-
-#endif
diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c
index 3fc96ef14..9e9a225a5 100644
--- a/arch/sparc/mm/init.c
+++ b/arch/sparc/mm/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.78 2000/01/24 03:22:38 anton Exp $
+/* $Id: init.c,v 1.79 2000/01/29 01:09:06 anton Exp $
* linux/arch/sparc/mm/init.c
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -238,15 +238,6 @@ void __init paging_init(void)
sparc_unmapped_base = 0x50000000;
BTFIXUPSET_SETHI(sparc_unmapped_base, 0x50000000);
break;
-
- case ap1000:
-#if CONFIG_AP1000
- apmmu_paging_init();
- sparc_unmapped_base = 0x50000000;
- BTFIXUPSET_SETHI(sparc_unmapped_base, 0x50000000);
- break;
-#endif
-
default:
prom_printf("paging_init: Cannot init paging on this Sparc\n");
prom_printf("paging_init: sparc_cpu_model = %d\n", sparc_cpu_model);
diff --git a/arch/sparc/mm/loadmmu.c b/arch/sparc/mm/loadmmu.c
index 3338666e8..ce0885679 100644
--- a/arch/sparc/mm/loadmmu.c
+++ b/arch/sparc/mm/loadmmu.c
@@ -1,4 +1,4 @@
-/* $Id: loadmmu.c,v 1.53 2000/01/09 10:46:50 anton Exp $
+/* $Id: loadmmu.c,v 1.54 2000/01/29 01:09:07 anton Exp $
* loadmmu.c: This code loads up all the mm function pointers once the
* machine type has been determined. It also sets the static
* mmu values such as PAGE_NONE, etc.
@@ -39,11 +39,6 @@ void __init load_mmu(void)
case sun4d:
ld_mmu_srmmu();
break;
- case ap1000:
-#if CONFIG_AP1000
- ld_mmu_apmmu();
- break;
-#endif
default:
prom_printf("load_mmu: %d unsupported\n", (int)sparc_cpu_model);
prom_halt();
diff --git a/arch/sparc/prom/bootstr.c b/arch/sparc/prom/bootstr.c
index 5edcad9d2..a4a040ca2 100644
--- a/arch/sparc/prom/bootstr.c
+++ b/arch/sparc/prom/bootstr.c
@@ -1,4 +1,4 @@
-/* $Id: bootstr.c,v 1.18 1999/08/31 06:54:45 davem Exp $
+/* $Id: bootstr.c,v 1.19 2000/01/29 01:09:11 anton Exp $
* bootstr.c: Boot string/argument acquisition from the PROM.
*
* Copyright(C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -55,11 +55,6 @@ prom_getbootargs(void)
*/
strncpy(barg_buf, *romvec->pv_v2bootargs.bootargs, BARG_LEN-1);
break;
- case PROM_AP1000:
-#if CONFIG_AP1000
- ap_getbootargs(barg_buf, BARG_LEN);
- break;
-#endif
default:
break;
}
diff --git a/arch/sparc/prom/console.c b/arch/sparc/prom/console.c
index 4a1a42309..2305dc858 100644
--- a/arch/sparc/prom/console.c
+++ b/arch/sparc/prom/console.c
@@ -1,4 +1,4 @@
-/* $Id: console.c,v 1.20 1998/09/21 05:05:50 jj Exp $
+/* $Id: console.c,v 1.21 2000/01/29 01:09:12 anton Exp $
* console.c: Routines that deal with sending and receiving IO
* to/from the current console device using the PROM.
*
@@ -45,7 +45,6 @@ prom_nbgetchar(void)
i = -1;
}
break;
- case PROM_AP1000:
default:
i = -1;
break;
@@ -79,15 +78,6 @@ prom_nbputchar(char c)
else
i = -1;
break;
- case PROM_AP1000:
-#if CONFIG_AP1000
- {
- extern void ap_putchar(char );
- ap_putchar(c);
- i = 0;
- }
-#endif
- break;
default:
i = -1;
break;
@@ -160,8 +150,6 @@ prom_query_input_device()
return PROMDEV_ITTYB;
}
return PROMDEV_I_UNK;
- case PROM_AP1000:
- return PROMDEV_I_UNK;
}
}
@@ -219,7 +207,6 @@ prom_query_output_device()
};
}
break;
- case PROM_AP1000:
default:
}
return PROMDEV_O_UNK;
diff --git a/arch/sparc/prom/devops.c b/arch/sparc/prom/devops.c
index c273b9922..5a58efa0b 100644
--- a/arch/sparc/prom/devops.c
+++ b/arch/sparc/prom/devops.c
@@ -1,4 +1,4 @@
-/* $Id: devops.c,v 1.11 1998/03/09 14:04:24 jj Exp $
+/* $Id: devops.c,v 1.12 2000/01/29 01:09:12 anton Exp $
* devops.c: Device operations using the PROM.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -31,7 +31,6 @@ prom_devopen(char *dstr)
case PROM_V3:
handle = (*(romvec->pv_v2devops.v2_dev_open))(dstr);
break;
- case PROM_AP1000:
default:
handle = -1;
break;
@@ -56,7 +55,6 @@ prom_devclose(int dhandle)
case PROM_V3:
(*(romvec->pv_v2devops.v2_dev_close))(dhandle);
break;
- case PROM_AP1000:
default:
break;
};
@@ -81,7 +79,6 @@ prom_seek(int dhandle, unsigned int seekhi, unsigned int seeklo)
case PROM_V3:
(*(romvec->pv_v2devops.v2_dev_seek))(dhandle, seekhi, seeklo);
break;
- case PROM_AP1000:
default:
break;
};
diff --git a/arch/sparc/prom/init.c b/arch/sparc/prom/init.c
index 0802a97e5..b83409c81 100644
--- a/arch/sparc/prom/init.c
+++ b/arch/sparc/prom/init.c
@@ -1,4 +1,4 @@
-/* $Id: init.c,v 1.13 1999/08/31 06:54:45 davem Exp $
+/* $Id: init.c,v 1.14 2000/01/29 01:09:12 anton Exp $
* init.c: Initialize internal variables used by the PROM
* library functions.
*
@@ -41,10 +41,6 @@ void __init prom_init(struct linux_romvec *rp)
extern struct linux_romvec *sun4_prom_init(void);
rp = sun4_prom_init();
#endif
-#if CONFIG_AP1000
- extern struct linux_romvec *ap_prom_init(void);
- rp = ap_prom_init();
-#endif
romvec = rp;
switch(romvec->pv_romvers) {
@@ -60,10 +56,6 @@ void __init prom_init(struct linux_romvec *rp)
case 40:
prom_vers = PROM_SUN4;
break;
- case 42: /* why not :-) */
- prom_vers = PROM_AP1000;
- break;
-
default:
prom_printf("PROMLIB: Bad PROM version %d\n",
romvec->pv_romvers);
diff --git a/arch/sparc/prom/memory.c b/arch/sparc/prom/memory.c
index c2f311df6..5480edb9c 100644
--- a/arch/sparc/prom/memory.c
+++ b/arch/sparc/prom/memory.c
@@ -1,4 +1,4 @@
-/* $Id: memory.c,v 1.14 1999/08/31 06:54:46 davem Exp $
+/* $Id: memory.c,v 1.15 2000/01/29 01:09:12 anton Exp $
* memory.c: Prom routine for acquiring various bits of information
* about RAM on the machine, both virtual and physical.
*
@@ -194,19 +194,6 @@ void __init prom_meminit(void)
#endif
break;
- case PROM_AP1000:
-#if CONFIG_AP1000
- /* really simple memory map */
- prom_phys_total[0].start_adr = 0x00000000;
- prom_phys_total[0].num_bytes = ap_memory_size();
- prom_phys_total[0].theres_more = 0x0;
- prom_prom_taken[0].start_adr = 0x00000000;
- prom_prom_taken[0].num_bytes = 0x00000000;
- prom_prom_taken[0].theres_more = 0x0;
- prom_phys_avail[0].start_adr = 0x00000000;
- prom_phys_avail[0].num_bytes = prom_phys_total[0].num_bytes;
- prom_phys_avail[0].theres_more = 0x0;
-#endif
default:
break;
};
diff --git a/arch/sparc/prom/mp.c b/arch/sparc/prom/mp.c
index 2346e3564..ba624673f 100644
--- a/arch/sparc/prom/mp.c
+++ b/arch/sparc/prom/mp.c
@@ -1,4 +1,4 @@
-/* $Id: mp.c,v 1.10 1998/03/09 14:04:26 jj Exp $
+/* $Id: mp.c,v 1.11 2000/01/29 01:09:12 anton Exp $
* mp.c: OpenBoot Prom Multiprocessor support routines. Don't call
* these on a UP or else you will halt and catch fire. ;)
*
@@ -29,7 +29,6 @@ prom_startcpu(int cpunode, struct linux_prom_registers *ctable_reg, int ctx, cha
switch(prom_vers) {
case PROM_V0:
case PROM_V2:
- case PROM_AP1000:
default:
ret = -1;
break;
@@ -56,7 +55,6 @@ prom_stopcpu(int cpunode)
switch(prom_vers) {
case PROM_V0:
case PROM_V2:
- case PROM_AP1000:
default:
ret = -1;
break;
@@ -83,7 +81,6 @@ prom_idlecpu(int cpunode)
switch(prom_vers) {
case PROM_V0:
case PROM_V2:
- case PROM_AP1000:
default:
ret = -1;
break;
@@ -110,7 +107,6 @@ prom_restartcpu(int cpunode)
switch(prom_vers) {
case PROM_V0:
case PROM_V2:
- case PROM_AP1000:
default:
ret = -1;
break;
diff --git a/arch/sparc/prom/printf.c b/arch/sparc/prom/printf.c
index 72a6cd6cc..24ac381a8 100644
--- a/arch/sparc/prom/printf.c
+++ b/arch/sparc/prom/printf.c
@@ -1,4 +1,4 @@
-/* $Id: printf.c,v 1.5 1996/04/04 16:31:07 tridge Exp $
+/* $Id: printf.c,v 1.6 2000/01/29 01:09:12 anton Exp $
* printf.c: Internal prom library printf facility.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -28,16 +28,12 @@ prom_printf(char *fmt, ...)
bptr = ppbuf;
-#if CONFIG_AP1000
- ap_write(1,bptr,strlen(bptr));
-#else
while((ch = *(bptr++)) != 0) {
if(ch == '\n')
prom_putchar('\r');
prom_putchar(ch);
}
-#endif
va_end(args);
return;
}
diff --git a/arch/sparc64/config.in b/arch/sparc64/config.in
index ace1366ba..fdf3960e3 100644
--- a/arch/sparc64/config.in
+++ b/arch/sparc64/config.in
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.87 2000/01/16 06:18:53 davem Exp $
+# $Id: config.in,v 1.89 2000/01/31 21:10:10 davem Exp $
# For a description of the syntax of this configuration file,
# see the Configure script.
#
diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
index 59db5d4bc..3e841d71b 100644
--- a/arch/sparc64/defconfig
+++ b/arch/sparc64/defconfig
@@ -292,6 +292,7 @@ CONFIG_VIDEO_DEV=y
#
# CONFIG_QUOTA is not set
CONFIG_AUTOFS_FS=m
+CONFIG_AUTOFS4_FS=m
# CONFIG_ADFS_FS is not set
CONFIG_AFFS_FS=m
# CONFIG_HFS_FS is not set
@@ -307,10 +308,12 @@ CONFIG_ISO9660_FS=m
# CONFIG_JOLIET is not set
CONFIG_MINIX_FS=m
# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
CONFIG_HPFS_FS=m
CONFIG_PROC_FS=y
CONFIG_DEVPTS_FS=y
# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
CONFIG_ROMFS_FS=m
CONFIG_EXT2_FS=y
CONFIG_SYSV_FS=m
@@ -318,15 +321,16 @@ CONFIG_SYSV_FS=m
CONFIG_UDF_FS=m
# CONFIG_UDF_RW is not set
CONFIG_UFS_FS=m
-CONFIG_UFS_FS_WRITE=y
+# CONFIG_UFS_FS_WRITE is not set
#
# Network File Systems
#
CONFIG_CODA_FS=m
CONFIG_NFS_FS=y
+# CONFIG_ROOT_NFS is not set
CONFIG_NFSD=m
-CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3 is not set
CONFIG_SUNRPC=y
CONFIG_LOCKD=y
CONFIG_SMB_FS=m
@@ -347,7 +351,6 @@ CONFIG_NCP_FS=m
#
# CONFIG_PARTITION_ADVANCED is not set
CONFIG_MSDOS_PARTITION=y
-# CONFIG_SGI_PARTITION is not set
CONFIG_SUN_PARTITION=y
CONFIG_NLS=y
diff --git a/arch/sparc64/kernel/binfmt_elf32.c b/arch/sparc64/kernel/binfmt_elf32.c
index 76516f2f2..59b48600d 100644
--- a/arch/sparc64/kernel/binfmt_elf32.c
+++ b/arch/sparc64/kernel/binfmt_elf32.c
@@ -1,7 +1,7 @@
/*
* binfmt_elf32.c: Support 32-bit Sparc ELF binaries on Ultra.
*
- * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com)
* Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek (jj@ultra.linux.cz)
*/
diff --git a/arch/sparc64/kernel/dtlb_backend.S b/arch/sparc64/kernel/dtlb_backend.S
index 81f4fd366..9c1818c5e 100644
--- a/arch/sparc64/kernel/dtlb_backend.S
+++ b/arch/sparc64/kernel/dtlb_backend.S
@@ -1,8 +1,8 @@
-/* $Id: dtlb_backend.S,v 1.8 1999/12/05 10:41:35 davem Exp $
+/* $Id: dtlb_backend.S,v 1.9 2000/01/31 04:59:12 davem Exp $
* dtlb_backend.S: Back end to DTLB miss replacement strategy.
* This is included directly into the trap table.
*
- * Copyright (C) 1996,1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1996,1998 David S. Miller (davem@redhat.com)
* Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
*/
diff --git a/arch/sparc64/kernel/dtlb_base.S b/arch/sparc64/kernel/dtlb_base.S
index 71e5b14d7..0f86bc896 100644
--- a/arch/sparc64/kernel/dtlb_base.S
+++ b/arch/sparc64/kernel/dtlb_base.S
@@ -1,8 +1,8 @@
-/* $Id: dtlb_base.S,v 1.4 1998/06/15 16:59:30 jj Exp $
+/* $Id: dtlb_base.S,v 1.5 2000/01/31 04:59:12 davem Exp $
* dtlb_base.S: Front end to DTLB miss replacement strategy.
* This is included directly into the trap table.
*
- * Copyright (C) 1996,1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1996,1998 David S. Miller (davem@redhat.com)
* Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
*/
diff --git a/arch/sparc64/kernel/dtlb_prot.S b/arch/sparc64/kernel/dtlb_prot.S
index 067a1d051..73f3596e1 100644
--- a/arch/sparc64/kernel/dtlb_prot.S
+++ b/arch/sparc64/kernel/dtlb_prot.S
@@ -1,8 +1,8 @@
-/* $Id: dtlb_prot.S,v 1.18 1999/03/02 15:42:14 jj Exp $
+/* $Id: dtlb_prot.S,v 1.19 2000/01/31 04:59:12 davem Exp $
* dtlb_prot.S: DTLB protection trap strategy.
* This is included directly into the trap table.
*
- * Copyright (C) 1996,1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1996,1998 David S. Miller (davem@redhat.com)
* Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
*/
diff --git a/arch/sparc64/kernel/ioctl32.c b/arch/sparc64/kernel/ioctl32.c
index 7a7315003..d51e36f61 100644
--- a/arch/sparc64/kernel/ioctl32.c
+++ b/arch/sparc64/kernel/ioctl32.c
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.74 2000/01/15 04:47:48 davem Exp $
+/* $Id: ioctl32.c,v 1.76 2000/01/31 21:10:15 davem Exp $
* ioctl32.c: Conversion between 32bit and 64bit native ioctls.
*
* Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
diff --git a/arch/sparc64/kernel/iommu_common.c b/arch/sparc64/kernel/iommu_common.c
index d1041b85f..27aa136ff 100644
--- a/arch/sparc64/kernel/iommu_common.c
+++ b/arch/sparc64/kernel/iommu_common.c
@@ -1,4 +1,4 @@
-/* $Id: iommu_common.c,v 1.2 1999/12/19 09:17:53 davem Exp $
+/* $Id: iommu_common.c,v 1.3 2000/01/28 13:41:59 jj Exp $
* iommu_common.c: UltraSparc SBUS/PCI common iommu code.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
diff --git a/arch/sparc64/kernel/itlb_base.S b/arch/sparc64/kernel/itlb_base.S
index eefc1c074..4ef509731 100644
--- a/arch/sparc64/kernel/itlb_base.S
+++ b/arch/sparc64/kernel/itlb_base.S
@@ -1,8 +1,8 @@
-/* $Id: itlb_base.S,v 1.7 1999/03/02 15:42:12 jj Exp $
+/* $Id: itlb_base.S,v 1.8 2000/01/31 04:59:12 davem Exp $
* itlb_base.S: Front end to ITLB miss replacement strategy.
* This is included directly into the trap table.
*
- * Copyright (C) 1996,1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1996,1998 David S. Miller (davem@redhat.com)
* Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
*/
diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c
index e72671428..409a44897 100644
--- a/arch/sparc64/kernel/pci_iommu.c
+++ b/arch/sparc64/kernel/pci_iommu.c
@@ -1,4 +1,4 @@
-/* $Id: pci_iommu.c,v 1.7 1999/12/20 14:08:15 jj Exp $
+/* $Id: pci_iommu.c,v 1.8 2000/01/28 13:41:59 jj Exp $
* pci_iommu.c: UltraSparc PCI controller IOM/STC support.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c
index 559769b87..1ff768056 100644
--- a/arch/sparc64/kernel/pci_psycho.c
+++ b/arch/sparc64/kernel/pci_psycho.c
@@ -1,4 +1,4 @@
-/* $Id: pci_psycho.c,v 1.9 2000/01/11 23:38:32 davem Exp $
+/* $Id: pci_psycho.c,v 1.10 2000/01/28 13:42:00 jj Exp $
* pci_psycho.c: PSYCHO/U2P specific PCI controller support.
*
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c
index 2f82de9ce..44247c371 100644
--- a/arch/sparc64/kernel/pci_sabre.c
+++ b/arch/sparc64/kernel/pci_sabre.c
@@ -1,4 +1,4 @@
-/* $Id: pci_sabre.c,v 1.10 2000/01/11 23:38:35 davem Exp $
+/* $Id: pci_sabre.c,v 1.11 2000/01/28 13:42:01 jj Exp $
* pci_sabre.c: Sabre specific PCI controller support.
*
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c
index a73387754..38e731f37 100644
--- a/arch/sparc64/kernel/sbus.c
+++ b/arch/sparc64/kernel/sbus.c
@@ -1,4 +1,4 @@
-/* $Id: sbus.c,v 1.6 1999/12/20 14:08:17 jj Exp $
+/* $Id: sbus.c,v 1.7 2000/01/28 13:41:58 jj Exp $
* sbus.c: UltraSparc SBUS controller support.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c
index 418b2f7b2..c48a1f6e4 100644
--- a/arch/sparc64/kernel/sparc64_ksyms.c
+++ b/arch/sparc64/kernel/sparc64_ksyms.c
@@ -1,4 +1,4 @@
-/* $Id: sparc64_ksyms.c,v 1.70 2000/01/07 18:15:18 jj Exp $
+/* $Id: sparc64_ksyms.c,v 1.72 2000/01/28 13:41:59 jj Exp $
* arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -124,11 +124,6 @@ EXPORT_SYMBOL_PRIVATE(write_lock);
EXPORT_SYMBOL_PRIVATE(write_unlock);
#endif
-/* rw semaphores */
-EXPORT_SYMBOL_NOVERS(__down_read_failed);
-EXPORT_SYMBOL_NOVERS(__down_write_failed);
-EXPORT_SYMBOL_NOVERS(__rwsem_wake);
-
/* Kernel wide locking */
EXPORT_SYMBOL(kernel_flag);
@@ -169,6 +164,11 @@ EXPORT_SYMBOL(local_irq_count);
EXPORT_SYMBOL(local_bh_count);
#endif
+/* rw semaphores */
+EXPORT_SYMBOL_NOVERS(__down_read_failed);
+EXPORT_SYMBOL_NOVERS(__down_write_failed);
+EXPORT_SYMBOL_NOVERS(__rwsem_wake);
+
/* Atomic counter implementation. */
EXPORT_SYMBOL_PRIVATE(atomic_add);
EXPORT_SYMBOL_PRIVATE(atomic_sub);
diff --git a/arch/sparc64/kernel/starfire.c b/arch/sparc64/kernel/starfire.c
index 3237b37dc..8ff7ea4d2 100644
--- a/arch/sparc64/kernel/starfire.c
+++ b/arch/sparc64/kernel/starfire.c
@@ -1,7 +1,7 @@
-/* $Id: starfire.c,v 1.4 1999/09/21 14:35:25 davem Exp $
+/* $Id: starfire.c,v 1.5 2000/01/31 04:59:12 davem Exp $
* starfire.c: Starfire/E10000 support.
*
- * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1998 David S. Miller (davem@redhat.com)
*/
#include <linux/kernel.h>
diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
index 3c3a5c1c6..be2638ec9 100644
--- a/arch/sparc64/kernel/sys_sparc.c
+++ b/arch/sparc64/kernel/sys_sparc.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.34 2000/01/21 11:39:06 jj Exp $
+/* $Id: sys_sparc.c,v 1.35 2000/01/29 07:40:12 davem Exp $
* linux/arch/sparc64/kernel/sys_sparc.c
*
* This file contains various random system calls that
diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c
index 6beb0531f..62058ffcf 100644
--- a/arch/sparc64/kernel/sys_sunos32.c
+++ b/arch/sparc64/kernel/sys_sunos32.c
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.37 2000/01/21 11:39:03 jj Exp $
+/* $Id: sys_sunos32.c,v 1.38 2000/01/29 07:40:13 davem Exp $
* sys_sunos32.c: SunOS binary compatability layer on sparc64.
*
* Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 2c61f6623..10effccae 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -1,4 +1,4 @@
-/* $Id: systbls.S,v 1.66 2000/01/16 06:20:48 davem Exp $
+/* $Id: systbls.S,v 1.67 2000/01/29 16:41:21 jj Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
@@ -48,7 +48,7 @@ sys_call_table32:
/*130*/ .word sys_ftruncate, sys_flock, sys_lstat64, sys_nis_syscall, sys_nis_syscall
.word sys_nis_syscall, sys_mkdir, sys_rmdir, sys32_utimes, sys_stat64
/*140*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys32_getrlimit
- .word sys32_setrlimit, sys_nis_syscall, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write
+ .word sys32_setrlimit, sys_pivot_root, sys32_prctl, sys32_pciconfig_read, sys32_pciconfig_write
/*150*/ .word sys_nis_syscall, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall
.word sys_nis_syscall, sys_nis_syscall, sys32_statfs, sys32_fstatfs, sys_oldumount
/*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_nis_syscall
@@ -107,7 +107,7 @@ sys_call_table:
/*130*/ .word sys_ftruncate, sys_flock, sys_nis_syscall, sys_sendto, sys_shutdown
.word sys_socketpair, sys_mkdir, sys_rmdir, sys_utimes, sys_nis_syscall
/*140*/ .word sys_nis_syscall, sys_getpeername, sys_nis_syscall, sys_nis_syscall, sys_getrlimit
- .word sys_setrlimit, sys_nis_syscall, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
+ .word sys_setrlimit, sys_pivot_root, sys_prctl, sys_pciconfig_read, sys_pciconfig_write
/*150*/ .word sys_getsockname, sys_nis_syscall, sys_nis_syscall, sys_poll, sys_nis_syscall
.word sys_nis_syscall, sys_nis_syscall, sys_statfs, sys_fstatfs, sys_oldumount
/*160*/ .word sys_nis_syscall, sys_nis_syscall, sys_getdomainname, sys_setdomainname, sys_utrap_install
diff --git a/arch/sparc64/lib/debuglocks.c b/arch/sparc64/lib/debuglocks.c
index 315724ec3..518281daa 100644
--- a/arch/sparc64/lib/debuglocks.c
+++ b/arch/sparc64/lib/debuglocks.c
@@ -1,7 +1,7 @@
-/* $Id: debuglocks.c,v 1.3 1999/09/10 10:40:50 davem Exp $
+/* $Id: debuglocks.c,v 1.4 2000/01/31 04:59:10 davem Exp $
* debuglocks.c: Debugging versions of SMP locking primitives.
*
- * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1998 David S. Miller (davem@redhat.com)
*/
#include <linux/kernel.h>
diff --git a/arch/sparc64/lib/memscan.S b/arch/sparc64/lib/memscan.S
index 423bc1409..a34c6b9d2 100644
--- a/arch/sparc64/lib/memscan.S
+++ b/arch/sparc64/lib/memscan.S
@@ -1,8 +1,8 @@
-/* $Id: memscan.S,v 1.2 1998/05/21 14:42:22 jj Exp $
+/* $Id: memscan.S,v 1.3 2000/01/31 04:59:10 davem Exp $
* memscan.S: Optimized memscan for Sparc64.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@ultra.linux.cz)
- * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1998 David S. Miller (davem@redhat.com)
*/
#define HI_MAGIC 0x8080808080808080
diff --git a/arch/sparc64/mm/Makefile b/arch/sparc64/mm/Makefile
index a7448f1db..d97c47778 100644
--- a/arch/sparc64/mm/Makefile
+++ b/arch/sparc64/mm/Makefile
@@ -1,4 +1,4 @@
-# $Id: Makefile,v 1.5 1998/07/26 03:02:54 davem Exp $
+# $Id: Makefile,v 1.6 2000/01/31 01:30:49 davem Exp $
# Makefile for the linux Sparc64-specific parts of the memory manager.
#
# Note! Dependencies are done automagically by 'make dep', which also
@@ -14,6 +14,6 @@
$(CC) -D__ASSEMBLY__ $(AFLAGS) -ansi -c $< -o $*.o
O_TARGET := mm.o
-O_OBJS := ultra.o fault.o init.o generic.o asyncd.o extable.o modutil.o
+O_OBJS := ultra.o fault.o init.o generic.o extable.o modutil.o
include $(TOPDIR)/Rules.make
diff --git a/arch/sparc64/mm/asyncd.c b/arch/sparc64/mm/asyncd.c
deleted file mode 100644
index b87efd590..000000000
--- a/arch/sparc64/mm/asyncd.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/* $Id: asyncd.c,v 1.12 2000/01/21 11:39:13 jj Exp $
- * The asyncd kernel daemon. This handles paging on behalf of
- * processes that receive page faults due to remote (async) memory
- * accesses.
- *
- * Idea and skeleton code courtesy of David Miller (bless his cotton socks)
- *
- * Implemented by tridge
- */
-
-#include <linux/mm.h>
-#include <linux/malloc.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/kernel_stat.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/stat.h>
-#include <linux/swap.h>
-#include <linux/fs.h>
-#include <linux/config.h>
-#include <linux/interrupt.h>
-#include <linux/signal.h>
-
-#include <asm/dma.h>
-#include <asm/system.h> /* for cli()/sti() */
-#include <asm/segment.h> /* for memcpy_to/fromfs */
-#include <asm/bitops.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-
-#define DEBUG 0
-
-#define WRITE_LIMIT 100
-#define LOOP_LIMIT 200
-
-static struct {
- int faults, read, write, success, failure, errors;
-} stats;
-
-/*
- * The wait queue for waking up the async daemon:
- */
-static DECLARE_WAIT_QUEUE_HEAD(asyncd_wait);
-
-struct async_job {
- volatile struct async_job *next;
- int taskid;
- struct mm_struct *mm;
- unsigned long address;
- int write;
- void (*callback)(int,unsigned long,int,int);
-};
-
-static volatile struct async_job *async_queue = NULL;
-static volatile struct async_job *async_queue_end = NULL;
-
-static void add_to_async_queue(int taskid,
- struct mm_struct *mm,
- unsigned long address,
- int write,
- void (*callback)(int,unsigned long,int,int))
-{
- struct async_job *a = kmalloc(sizeof(*a),GFP_ATOMIC);
-
- if (!a) {
- printk("ERROR: out of memory in asyncd\n");
- a->callback(taskid,address,write,1);
- return;
- }
-
- if (write)
- stats.write++;
- else
- stats.read++;
-
- a->next = NULL;
- a->taskid = taskid;
- a->mm = mm;
- a->address = address;
- a->write = write;
- a->callback = callback;
-
- if (!async_queue) {
- async_queue = a;
- } else {
- async_queue_end->next = a;
- }
- async_queue_end = a;
-}
-
-
-void async_fault(unsigned long address, int write, int taskid,
- void (*callback)(int,unsigned long,int,int))
-{
-#warning Need some fixing here... -DaveM
- struct task_struct *tsk = current /* XXX task[taskid] */;
- struct mm_struct *mm = tsk->mm;
-
- stats.faults++;
-
-#if 0
- printk("paging in %x for task=%d\n",address,taskid);
-#endif
-
- add_to_async_queue(taskid, mm, address, write, callback);
- wake_up(&asyncd_wait);
- mark_bh(TQUEUE_BH);
-}
-
-static int fault_in_page(int taskid,
- struct vm_area_struct *vma,
- unsigned long address, int write)
-{
- static unsigned last_address;
- static int last_task, loop_counter;
- siginfo_t info;
-#warning Need some fixing here... -DaveM
- struct task_struct *tsk = current /* XXX task[taskid] */;
- pgd_t *pgd;
- pmd_t *pmd;
- pte_t *pte;
-
- if (!tsk || !tsk->mm)
- return 1;
-
- if (!vma || (write && !(vma->vm_flags & VM_WRITE)))
- goto bad_area;
- if (vma->vm_start > address)
- goto bad_area;
-
- if (address == last_address && taskid == last_task) {
- loop_counter++;
- } else {
- loop_counter = 0;
- last_address = address;
- last_task = taskid;
- }
-
- if (loop_counter == WRITE_LIMIT && !write) {
- printk("MSC bug? setting write request\n");
- stats.errors++;
- write = 1;
- }
-
- if (loop_counter == LOOP_LIMIT) {
- printk("MSC bug? failing request\n");
- stats.errors++;
- return 1;
- }
-
- pgd = pgd_offset(vma->vm_mm, address);
- pmd = pmd_alloc(pgd,address);
- if(!pmd)
- goto no_memory;
- pte = pte_alloc(pmd, address);
- if(!pte)
- goto no_memory;
- if(!pte_present(*pte)) {
- handle_mm_fault(tsk, vma, address, write);
- goto finish_up;
- }
- set_pte(pte, pte_mkyoung(*pte));
- flush_tlb_page(vma, address);
- if(!write)
- goto finish_up;
- if(pte_write(*pte)) {
- set_pte(pte, pte_mkdirty(*pte));
- flush_tlb_page(vma, address);
- goto finish_up;
- }
- handle_mm_fault(tsk, vma, address, write);
-
- /* Fall through for do_wp_page */
-finish_up:
- stats.success++;
- return 0;
-
-no_memory:
- stats.failure++;
- oom(tsk);
- return 1;
-
-bad_area:
- stats.failure++;
- info.si_signo = SIGSEGV;
- info.si_errno = 0;
- info.si_code = SEGV_MAPERR;
- info.si_addr = (void *)address;
- info.si_trapno = 0;
- send_sig_info(SIGSEGV, &info, tsk);
- return 1;
-}
-
-
-/* Note the semaphore operations must be done here, and _not_
- * in async_fault().
- */
-static void run_async_queue(void)
-{
- int ret;
- unsigned flags;
-
- while (async_queue) {
- volatile struct async_job *a;
- struct mm_struct *mm;
- struct vm_area_struct *vma;
-
- save_flags(flags); cli();
- a = async_queue;
- async_queue = async_queue->next;
- restore_flags(flags);
-
- mm = a->mm;
-
- down(&mm->mmap_sem);
- vma = find_vma(mm, a->address);
- ret = fault_in_page(a->taskid,vma,a->address,a->write);
-#if DEBUG
- printk("fault_in_page(task=%d addr=%x write=%d) = %d\n",
- a->taskid,a->address,a->write,ret);
-#endif
- a->callback(a->taskid,a->address,a->write,ret);
- up(&mm->mmap_sem);
- kfree_s((void *)a,sizeof(*a));
- }
-}
-
-
-#if CONFIG_AP1000
-static void asyncd_info(void)
-{
- printk("CID(%d) faults: total=%d read=%d write=%d success=%d fail=%d err=%d\n",
- mpp_cid(),stats.faults, stats.read, stats.write, stats.success,
- stats.failure, stats.errors);
-}
-#endif
-
-
-/*
- * The background async daemon.
- * Started as a kernel thread from the init process.
- */
-int asyncd(void *unused)
-{
- current->session = 1;
- current->pgrp = 1;
- sprintf(current->comm, "asyncd");
-
- sigfillset(&current->blocked); /* block all signals */
- recalc_sigpending(current);
-
- /* Give asyncd a realtime priority. */
- current->policy = SCHED_FIFO;
- current->priority = 32; /* Fixme --- we need to standardise our
- namings for POSIX.4 realtime scheduling
- priorities. */
-
- printk("Started asyncd\n");
-
-#if CONFIG_AP1000
- bif_add_debug_key('a',asyncd_info,"stats on asyncd");
-#endif
-
- while (1) {
- unsigned flags;
-
- save_flags(flags); cli();
-
- while (!async_queue) {
- spin_lock(&current->sigmask_lock);
- flush_signals(current);
- spin_unlock(&current->sigmask_lock);
- interruptible_sleep_on(&asyncd_wait);
- __sti(); cli(); /* acquire gloabl_irq_lock */
- }
-
- restore_flags(flags);
-
- run_async_queue();
- }
-}
-
diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c
index 450d2fc9e..46dbfb241 100644
--- a/arch/sparc64/solaris/misc.c
+++ b/arch/sparc64/solaris/misc.c
@@ -1,4 +1,4 @@
-/* $Id: misc.c,v 1.20 2000/01/12 02:59:26 davem Exp $
+/* $Id: misc.c,v 1.21 2000/01/29 07:40:15 davem Exp $
* misc.c: Miscelaneous syscall emulation for Solaris
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
diff --git a/drivers/Makefile b/drivers/Makefile
index 71ee973cf..def2731d2 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -11,7 +11,7 @@ SUB_DIRS := block char net parport sound misc
MOD_SUB_DIRS := $(SUB_DIRS)
ALL_SUB_DIRS := $(SUB_DIRS) pci sgi scsi sbus cdrom isdn pnp i2o ieee1394 \
macintosh video dio zorro fc4 usb \
- nubus tc ap1000 atm pcmcia i2c telephony
+ nubus tc atm pcmcia i2c telephony
ifdef CONFIG_DIO
SUB_DIRS += dio
@@ -137,10 +137,6 @@ SUB_DIRS += atm
MOD_SUB_DIRS += atm
endif
-ifeq ($(CONFIG_AP1000),y)
-SUB_DIRS += ap1000
-endif
-
ifeq ($(CONFIG_FC4),y)
SUB_DIRS += fc4
MOD_SUB_DIRS += fc4
diff --git a/drivers/ap1000/Makefile b/drivers/ap1000/Makefile
deleted file mode 100644
index 47f37720a..000000000
--- a/drivers/ap1000/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-# File: drivers/ap1000/Makefile
-#
-# Makefile for the AP1000 drivers
-#
-
-L_TARGET := ap1000.a
-L_OBJS := bif.o apfddi.o mac.o plc.o ringbuf.o
-
-ifeq ($(CONFIG_APBLOCK),y)
-L_OBJS += ap.o
-else
- ifeq ($(CONFIG_APBLOCK),m)
- M_OBJS += ap.o
- endif
-endif
-
-ifeq ($(CONFIG_DDV),y)
-L_OBJS += ddv.o ddv_util.o
-else
- ifeq ($(CONFIG_DDV),m)
- M_OBJS += ddv.o ddv_util.o
- endif
-endif
-
-include $(TOPDIR)/Rules.make
-
-clean:
- rm -f core *.o *.a *.s
-
diff --git a/drivers/ap1000/am79c830.h b/drivers/ap1000/am79c830.h
deleted file mode 100644
index f9ba50910..000000000
--- a/drivers/ap1000/am79c830.h
+++ /dev/null
@@ -1,276 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * Definitions for the AM79C830 FORMAC (Fiber Optic Ring MAC) chip.
- */
-
-typedef int formac_reg;
-
-struct formac {
- formac_reg cmdreg1; /* command register 1 */
- formac_reg cmdreg2; /* command register 2 */
-#define st1u cmdreg1 /* status reg 1, upper */
-#define st1l cmdreg2 /* status reg 1, lower */
- formac_reg st2u; /* status reg 2, upper */
- formac_reg st2l; /* status reg 2, lower */
- formac_reg imsk1u; /* interrupt mask 1, upper */
- formac_reg imsk1l; /* interrupt mask 1, lower */
- formac_reg imsk2u; /* interrupt mask 2, upper */
- formac_reg imsk2l; /* interrupt mask 2, lower */
- formac_reg said; /* short address, individual */
- formac_reg laim; /* long adrs, indiv, MS word */
- formac_reg laic; /* long adrs, indiv, middle word */
- formac_reg lail; /* long adrs, indiv, LS word */
- formac_reg sagp; /* short address, group */
- formac_reg lagm; /* short adrs, group, MS word */
- formac_reg lagc; /* short adrs, group, middle word */
- formac_reg lagl; /* short adrs, group, LS word */
- formac_reg mdreg1; /* mode reg 1 */
- formac_reg stmchn; /* state machine reg */
- formac_reg mir1; /* MAC information reg, upper */
- formac_reg mir0; /* MAC information reg, lower */
- formac_reg tmax; /* TMax value (2's-comp) */
- formac_reg tvx; /* TVX value (2's-comp) */
- formac_reg trt; /* TRT timer value */
- formac_reg tht; /* THT timer value */
- formac_reg tneg; /* current TNeg (2's-comp) */
- formac_reg tmrs; /* extra bits of tneg, trt, tht; late count */
- formac_reg treq0; /* our TReq (2's-comp), lower */
- formac_reg treq1; /* our TReq (2's-comp), upper */
- formac_reg pri0; /* priority reg for async queue 0 */
- formac_reg pri1; /* priority reg for async queue 1 */
- formac_reg pri2; /* priority reg for async queue 2 */
- formac_reg tsync; /* TSync value (2's-comp) */
- formac_reg mdreg2; /* mode reg 2 */
- formac_reg frmthr; /* frame threshold reg */
- formac_reg eacb; /* end address of claim/beacon area */
- formac_reg earv; /* end address of receive area */
- formac_reg eas; /* end address of sync queue */
- formac_reg eaa0; /* end address of async queue 0 */
- formac_reg eaa1; /* end address of async queue 1 */
- formac_reg eaa2; /* end address of async queue 2 */
- formac_reg sacl; /* start address of claim frame */
- formac_reg sabc; /* start address of beacon frame */
- formac_reg wpxsf; /* write pointer, special frames */
- formac_reg rpxsf; /* read pointer, special frames */
- formac_reg dummy1; /* not used */
- formac_reg rpr; /* read pointer, receive */
- formac_reg wpr; /* write pointer, receive */
- formac_reg swpr; /* shadow write pointer, receive */
- formac_reg wpxs; /* write pointer, sync queue */
- formac_reg wpxa0; /* write pointer, async queue 0 */
- formac_reg wpxa1; /* write pointer, async queue 1 */
- formac_reg wpxa2; /* write pointer, async queue 2 */
- formac_reg swpxs; /* shadow write pointer, sync queue */
- formac_reg swpxa0; /* shadow write pointer, async queue 0 */
- formac_reg swpxa1; /* shadow write pointer, async queue 1 */
- formac_reg swpxa2; /* shadow write pointer, async queue 2 */
- formac_reg rpxs; /* read pointer, sync queue */
- formac_reg rpxa0; /* read pointer, async queue 0 */
- formac_reg rpxa1; /* read pointer, async queue 1 */
- formac_reg rpxa2; /* read pointer, async queue 2 */
- formac_reg marr; /* memory address for random reads */
- formac_reg marw; /* memory address for random writes */
- formac_reg mdru; /* memory data register, upper */
- formac_reg mdrl; /* memory data register, lower */
- formac_reg tmsync; /* TSync timer value */
- formac_reg fcntr; /* frame counter */
- formac_reg lcntr; /* lost counter */
- formac_reg ecntr; /* error counter */
-};
-
-/* Values for cmdreg1 */
-#define C1_SOFTWARE_RESET 1
-#define C1_IRMEMWI 2
-#define C1_IRMEMWO 3
-#define C1_IDLE_LISTEN 4
-#define C1_CLAIM_LISTEN 5
-#define C1_BEACON_LISTEN 6
-#define C1_LOAD_TVX 7
-#define C1_SEND_NR_TOKEN 0x0c
-#define C1_SEND_R_TOKEN 0x0d
-#define C1_ENTER_SI_MODE 0x0e
-#define C1_EXIT_SI_MODE 0x0f
-#define C1_CLR_SYNCQ_LOCK 0x11
-#define C1_CLR_ASYNCQ0_LOCK 0x12
-#define C1_CLR_ASYNCQ1_LOCK 0x14
-#define C1_CLR_ASYNCQ2_LOCK 0x18
-#define C1_CLR_RECVQ_LOCK 0x20
-#define C1_CLR_ALL_LOCKS 0x3f
-
-/* Values for cmdreg2 */
-#define C2_XMIT_SYNCQ 1
-#define C2_XMIT_ASYNCQ0 2
-#define C2_XMIT_ASYNCQ1 4
-#define C2_XMIT_ASYNCQ2 8
-#define C2_ABORT_XMIT 0x10
-#define C2_RESET_XMITQS 0x20
-#define C2_SET_TAG 0x30
-#define C2_EN_RECV_FRAME 0x40
-
-/* Bits in (st1u << 16) + st1l (and (imsk1u << 16) + imsk1l) */
-#define S1_XMIT_ABORT 0x80000000
-#define S1_XABORT_ASYNC2 0x40000000
-#define S1_XABORT_ASYNC1 0x20000000
-#define S1_XABORT_ASYNC0 0x10000000
-#define S1_XABORT_SYNC 0x08000000
-#define S1_XBUF_FULL_SYNC 0x04000000
-#define S1_XBUF_FULL_ASYNC 0x02000000
-#define S1_XDONE_SYNC 0x01000000
-#define S1_END_CHAIN_ASYNC2 0x00800000
-#define S1_END_CHAIN_ASYNC1 0x00400000
-#define S1_END_CHAIN_ASYNC0 0x00200000
-#define S1_END_CHAIN_SYNC 0x00100000
-#define S1_END_FRAME_ASYNC2 0x00080000
-#define S1_END_FRAME_ASYNC1 0x00040000
-#define S1_END_FRAME_ASYNC0 0x00020000
-#define S1_END_FRAME_SYNC 0x00010000
-#define S1_BUF_UNDERRUN_ASYNC2 0x00008000
-#define S1_BUF_UNDERRUN_ASYNC1 0x00004000
-#define S1_BUF_UNDERRUN_ASYNC0 0x00002000
-#define S1_BUF_UNDERRUN_SYNC 0x00001000
-#define S1_PAR_ERROR_ASYNC2 0x00000800
-#define S1_PAR_ERROR_ASYNC1 0x00000400
-#define S1_PAR_ERROR_ASYNC0 0x00000200
-#define S1_PAR_ERROR_SYNC 0x00000100
-#define S1_XINSTR_FULL_ASYNC2 0x00000080
-#define S1_XINSTR_FULL_ASYNC1 0x00000040
-#define S1_XINSTR_FULL_ASYNC0 0x00000020
-#define S1_XINSTR_FULL_SYNC 0x00000010
-#define S1_QUEUE_LOCK_ASYNC2 0x00000008
-#define S1_QUEUE_LOCK_ASYNC1 0x00000004
-#define S1_QUEUE_LOCK_ASYNC0 0x00000002
-#define S1_QUEUE_LOCK_SYNC 0x00000001
-
-/* Bits in (st2u << 16) + st2l (and (imsk2u << 16) + imsk2l) */
-#define S2_RECV_COMPLETE 0x80000000
-#define S2_RECV_BUF_EMPTY 0x40000000
-#define S2_RECV_ABORT 0x20000000
-#define S2_RECV_BUF_FULL 0x10000000
-#define S2_RECV_FIFO_OVF 0x08000000
-#define S2_RECV_FRAME 0x04000000
-#define S2_RECV_FRCT_OVF 0x02000000
-#define S2_NP_SIMULT_LOAD 0x01000000
-#define S2_ERR_SPECIAL_FR 0x00800000
-#define S2_CLAIM_STATE 0x00400000
-#define S2_MY_CLAIM 0x00200000
-#define S2_HIGHER_CLAIM 0x00100000
-#define S2_LOWER_CLAIM 0x00080000
-#define S2_BEACON_STATE 0x00040000
-#define S2_MY_BEACON 0x00020000
-#define S2_OTHER_BEACON 0x00010000
-#define S2_RING_OP 0x00008000
-#define S2_MULTIPLE_DA 0x00004000
-#define S2_TOKEN_ERR 0x00002000
-#define S2_TOKEN_ISSUED 0x00001000
-#define S2_TVX_EXP 0x00000800
-#define S2_TRT_EXP 0x00000400
-#define S2_MISSED_FRAME 0x00000200
-#define S2_ADDRESS_DET 0x00000100
-#define S2_PHY_INVALID 0x00000080
-#define S2_LOST_CTR_OVF 0x00000040
-#define S2_ERR_CTR_OVF 0x00000020
-#define S2_FRAME_CTR_OVF 0x00000010
-#define S2_SHORT_IFG 0x00000008
-#define S2_DUPL_CLAIM 0x00000004
-#define S2_TRT_EXP_RECOV 0x00000002
-
-/* Bits in mdreg1 */
-#define M1_SINGLE_FRAME 0x8000
-#define M1_MODE 0x7000
-#define M1_MODE_INITIALIZE 0x0000
-#define M1_MODE_MEMORY 0x1000
-#define M1_MODE_ONLINE_SP 0x2000
-#define M1_MODE_ONLINE 0x3000
-#define M1_MODE_INT_LOOP 0x4000
-#define M1_MODE_EXT_LOOP 0x7000
-#define M1_SHORT_ADRS 0x0800
-#define M1_ADDET 0x0700
-#define M1_ADDET_NORM 0x0000
-#define M1_ADDET_METOO 0x0100
-#define M1_ADDET_NSA_NOTME 0x0200
-#define M1_ADDET_NSA 0x0300
-#define M1_ADDET_DISABLE_RECV 0x0400
-#define M1_ADDET_LIM_PROMISC 0x0600
-#define M1_ADDET_PROMISC 0x0700
-#define M1_SELECT_RA 0x0080
-#define M1_DISABLE_CARRY 0x0040
-#define M1_EXT_GRP 0x0030
-#define M1_EXT_GRP_MYGRP 0x0000
-#define M1_EXT_GRP_SOFT 0x0010
-#define M1_EXT_GRP_UPPER24 0x0020
-#define M1_EXT_GRP_UPPER16 0x0030
-#define M1_LOCK_XMIT_QS 0x0008
-#define M1_FULL_DUPLEX 0x0004
-#define M1_XMTINH_PIN 0x0002
-
-/* Bits in mdreg2 */
-#define M2_TAGMODE 0x8000
-#define M2_STRIP_FCS 0x4000
-#define M2_CHECK_PARITY 0x2000
-#define M2_EVEN_PARITY 0x1000
-#define M2_LSB_FIRST 0x0800
-#define M2_RCV_BYTE_BDRY_MASK 0x0600
-#define M2_RCV_BYTE_BDRY 0x0200
-#define M2_ENABLE_HSREQ 0x0100
-#define M2_ENABLE_NPDMA 0x0080
-#define M2_SYNC_NPDMA 0x0040
-#define M2_SYMBOL_CTRL 0x0020
-#define M2_RECV_BAD_FRAMES 0x0010
-#define M2_AFULL_MASK 0x000f
-#define M2_AFULL 0x0001
-
-/* Bits in stmchn */
-#define SM_REV_MASK 0xe000
-#define SM_REV 0x2000
-#define SM_SEND_IMM_MODE 0x1000
-#define SM_TOKEN_MODE 0x0c00
-#define SM_TOKEN_MODE_NR 0x0000
-#define SM_TOKEN_MODE_ENTER_R 0x0400
-#define SM_TOKEN_MODE_ENTER_NR 0x0800
-#define SM_TOKEN_MODE_R 0x0c00
-#define SM_RCV_STATE 0x0380
-#define SM_XMIT_STATE 0x0070
-#define SM_MDR_PENDING 0x0008
-#define SM_MDR_TAG 0x0004
-
-/* Bits in transmit descriptor */
-#define TD_MORE 0x80000000
-#define TD_MAGIC 0x40000000
-#define TD_BYTE_BDRY_MASK 0x18000000
-#define TD_BYTE_BDRY_1 0x08000000
-#define TD_XMIT_DONE 0x04000000
-#define TD_NO_FCS 0x02000000
-#define TD_XMIT_ABORT 0x01000000
-#define TD_BYTE_BDRY_LG 27
-
-/* Bits in pointer in buffer memory (nontag mode) */
-#define PT_MAGIC 0xa0000000
-
-/* Bits in receive status word */
-#define RS_VALID 0x80000000
-#define RS_ABORTED 0x40000000
-#define RS_SRC_ROUTE 0x10000000
-#define RS_E_INDIC 0x08000000
-#define RS_A_INDIC 0x04000000
-#define RS_C_INDIC 0x02000000
-#define RS_ERROR 0x01000000
-#define RS_ADDR_MATCH 0x00800000
-#define RS_FRAME_TYPE 0x00700000
-#define RS_FT_SMT 0x00000000
-#define RS_FT_LLC 0x00100000
-#define RS_FT_IMPL 0x00200000
-#define RS_FT_MAC 0x00400000
-#define RS_FT_LLC_SYNC 0x00500000
-#define RS_FT_IMPL_SYNC 0x00600000
-#define RS_BYTE_BDRY_MASK 0x00030000
-#define RS_BYTE_BDRY 0x00010000
-#define RS_BYTE_BDRY_LG 16
-
-#define RS_LENGTH 0x0000ffff
-
diff --git a/drivers/ap1000/am79c864.h b/drivers/ap1000/am79c864.h
deleted file mode 100644
index 0fef95791..000000000
--- a/drivers/ap1000/am79c864.h
+++ /dev/null
@@ -1,162 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * Definitions for Am79c864 PLC (Physical Layer Controller)
- */
-
-typedef int plc_reg;
-
-struct plc {
- plc_reg ctrl_a;
- plc_reg ctrl_b;
- plc_reg intr_mask;
- plc_reg xmit_vector;
- plc_reg vec_length;
- plc_reg le_threshold;
- plc_reg c_min;
- plc_reg tl_min;
- plc_reg tb_min;
- plc_reg t_out;
- plc_reg dummy1;
- plc_reg lc_length;
- plc_reg t_scrub;
- plc_reg ns_max;
- plc_reg tpc_load;
- plc_reg tne_load;
- plc_reg status_a;
- plc_reg status_b;
- plc_reg tpc;
- plc_reg tne;
- plc_reg clk_div;
- plc_reg bist_sig;
- plc_reg rcv_vector;
- plc_reg intr_event;
- plc_reg viol_sym_ct;
- plc_reg min_idle_ct;
- plc_reg link_err_ct;
-};
-
-/* Bits in ctrl_a */
-#define CA_NOISE_TIMER 0x4000
-#define CA_TNE_16BIT 0x2000
-#define CA_TPC_16BIT 0x1000
-#define CA_REQ_SCRUB 0x0800
-#define CA_VSYM_INTR_MODE 0x0200
-#define CA_MINI_INTR_MODE 0x0100
-#define CA_LOOPBACK 0x0080
-#define CA_FOT_OFF 0x0040
-#define CA_EB_LOOP 0x0020
-#define CA_LM_LOOP 0x0010
-#define CA_BYPASS 0x0008
-#define CA_REM_LOOP 0x0004
-#define CA_RF_DISABLE 0x0002
-#define CA_RUN_BIST 0x0001
-
-/* Bits in ctrl_b */
-#define CB_CONFIG_CTRL 0x8000
-#define CB_MATCH_LS 0x7800
-#define CB_MATCH_LS_ANY 0x0000
-#define CB_MATCH_LS_QLS 0x4000
-#define CB_MATCH_LS_MLS 0x2000
-#define CB_MATCH_LS_HLS 0x1000
-#define CB_MATCH_LS_ILS 0x0800
-#define CB_MAINT_LS 0x0700
-#define CB_MAINT_LS_QLS 0x0000
-#define CB_MAINT_LS_ILS 0x0100
-#define CB_MAINT_LS_HLS 0x0200
-#define CB_MAINT_LS_MLS 0x0300
-#define CB_MAINT_LS_PDR 0x0600
-#define CB_CLASS_S 0x0080
-#define CB_PC_LCT 0x0060
-#define CB_PC_LCT_NONE 0x0000
-#define CB_PC_LCT_PDR 0x0020
-#define CB_PC_LCT_IDLE 0x0040
-#define CB_PC_LCT_LOOP 0x0060
-#define CB_PC_JOIN 0x0010
-#define CB_LONG_LCT 0x0008
-#define CB_PC_MAINT 0x0004
-#define CB_PCM_CTRL 0x0003
-#define CB_PC_START 0x0001
-#define CB_PC_TRACE 0x0002
-#define CB_PC_STOP 0x0003
-
-/* Bits in status_a */
-#define SA_SIG_DETECT 0x0400
-#define SA_PREV_LS 0x0300
-#define SA_PREV_LS_QLS 0x0000
-#define SA_PREV_LS_MLS 0x0100
-#define SA_PREV_LS_HLS 0x0200
-#define SA_PREV_LS_ILS 0x0300
-#define SA_LINE_ST 0x00e0
-#define SA_LINE_ST_NLS 0x0000
-#define SA_LINE_ST_ALS 0x0020
-#define SA_LINE_ST_ILS4 0x0060
-#define SA_LINE_ST_QLS 0x0080
-#define SA_LINE_ST_MLS 0x00a0
-#define SA_LINE_ST_HLS 0x00c0
-#define SA_LINE_ST_ILS 0x00e0
-#define SA_LSM_STATE 0x0010
-#define SA_UNKN_LINE_ST 0x0008
-#define SA_SYM_PAIR_CTR 0x0007
-
-/* Bits in status_b */
-#define SB_RF_STATE 0xc000
-#define SB_RF_STATE_REPEAT 0x0000
-#define SB_RF_STATE_IDLE 0x4000
-#define SB_RF_STATE_HALT1 0x8000
-#define SB_RF_STATE_HALT2 0xc000
-#define SB_PCI_STATE 0x3000
-#define SB_PCI_STATE_REMOVED 0x0000
-#define SB_PCI_STATE_INS_SCR 0x1000
-#define SB_PCI_STATE_REM_SCR 0x2000
-#define SB_PCI_STATE_INSERTED 0x3000
-#define SB_PCI_SCRUB 0x0800
-#define SB_PCM_STATE 0x0780
-#define SB_PCM_STATE_OFF 0x0000
-#define SB_PCM_STATE_BREAK 0x0080
-#define SB_PCM_STATE_TRACE 0x0100
-#define SB_PCM_STATE_CONNECT 0x0180
-#define SB_PCM_STATE_NEXT 0x0200
-#define SB_PCM_STATE_SIGNAL 0x0280
-#define SB_PCM_STATE_JOIN 0x0300
-#define SB_PCM_STATE_VERIFY 0x0380
-#define SB_PCM_STATE_ACTIVE 0x0400
-#define SB_PCM_STATE_MAIN 0x0480
-#define SB_PCM_SIGNALING 0x0040
-#define SB_LSF 0x0020
-#define SB_RCF 0x0010
-#define SB_TCF 0x0008
-#define SB_BREAK_REASON 0x0007
-#define SB_BREAK_REASON_NONE 0x0000
-#define SB_BREAK_REASON_START 0x0001
-#define SB_BREAK_REASON_T_OUT 0x0002
-#define SB_BREAK_REASON_NS_MAX 0x0003
-#define SB_BREAK_REASON_QLS 0x0004
-#define SB_BREAK_REASON_ILS 0x0005
-#define SB_BREAK_REASON_HLS 0x0006
-
-/* Bits in intr_event and intr_mask */
-#define IE_NP_ERROR 0x8000
-#define IE_SIGNAL_OFF 0x4000
-#define IE_LE_CTR 0x2000
-#define IE_MINI_CTR 0x1000
-#define IE_VSYM_CTR 0x0800
-#define IE_PHY_INVALID 0x0400
-#define IE_EBUF_ERR 0x0200
-#define IE_TNE_EXP 0x0100
-#define IE_TPC_EXP 0x0080
-#define IE_PCM_ENABLED 0x0040
-#define IE_PCM_BREAK 0x0020
-#define IE_SELF_TEST 0x0010
-#define IE_TRACE_PROP 0x0008
-#define IE_PCM_CODE 0x0004
-#define IE_LS_MATCH 0x0002
-#define IE_PARITY_ERR 0x0001
-
-/* Correct value for BIST signature */
-#define BIST_CORRECT 0x6ecd
diff --git a/drivers/ap1000/ap.c b/drivers/ap1000/ap.c
deleted file mode 100644
index 6e05d7cb5..000000000
--- a/drivers/ap1000/ap.c
+++ /dev/null
@@ -1,307 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * ap.c - Single AP1000 block driver.
- *
- * (C) dwalsh, Pious project, DCS, ANU 1996
- *
- * This block driver is designed to simply to perform
- * io operations to the hosts file system.
- *
- * Heavily modified by tridge
- *
- */
-
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/module.h>
-#include <asm/uaccess.h>
-#include <asm/ap1000/apservice.h>
-
-#define AP_DEBUG 0
-
-#define MAJOR_NR APBLOCK_MAJOR
-#define AP_DRIVER 1
-#include <linux/blk.h>
-
-#define NUM_APDEVS 8
-#define MAX_REQUESTS 1
-
-static DECLARE_WAIT_QUEUE_HEAD(busy_wait);
-
-static int ap_blocksizes[NUM_APDEVS];
-static int ap_length[NUM_APDEVS];
-static int ap_fds[NUM_APDEVS];
-
-#define SECTOR_BLOCK_SHIFT 9
-#define AP_BLOCK_SHIFT 12 /* 4k blocks */
-#define AP_BLOCK_SIZE (1<<AP_BLOCK_SHIFT)
-
-static volatile int request_count = 0;
-
-static void ap_release(struct inode * inode, struct file * filp)
-{
- MOD_DEC_USE_COUNT;
-}
-
-static void ap_request(request_queue_t * q)
-{
- struct cap_request creq;
- unsigned int minor;
- int offset, len;
- struct request *req;
-
- if (request_count >= MAX_REQUESTS) return;
-
-repeat:
-
- if (!CURRENT) {
- return;
- }
-
- if (MAJOR(CURRENT->rq_dev) != MAJOR_NR) {
- panic(DEVICE_NAME ": request list destroyed");
- }
- if (CURRENT->bh) {
- if (!buffer_locked(CURRENT->bh)) {
- panic(DEVICE_NAME ": block not locked");
- }
- }
-
- req = CURRENT;
-
- minor = MINOR(req->rq_dev);
-
- if (minor >= NUM_APDEVS) {
- printk("apblock: request for invalid minor %d\n",minor);
- end_request(0);
- goto repeat;
- }
-
- offset = req->sector;
- len = req->current_nr_sectors;
-
- if ((offset + len) > ap_length[minor]) {
- printk("apblock: request for invalid sectors %d -> %d\n",
- offset,offset+len);
- end_request(0);
- goto repeat;
- }
-
- if (ap_fds[minor] == -1) {
- printk("apblock: minor %d not open\n",minor);
- end_request(0);
- goto repeat;
- }
-
- /* convert to our units */
- offset <<= SECTOR_BLOCK_SHIFT;
- len <<= SECTOR_BLOCK_SHIFT;
-
- /* setup a request for the host */
- creq.cid = mpp_cid();
- creq.size = sizeof(creq);
- creq.header = 0;
- creq.data[0] = (int)(req);
- creq.data[1] = ap_fds[minor];
- creq.data[2] = offset;
- creq.data[3] = len;
-
- switch (req->cmd) {
- case READ:
-#if AP_DEBUG
- printk("apblock: read req=0x%x len=%d offset=%d\n",
- req,len,offset);
-#endif
- creq.type = REQ_BREAD;
- if (bif_queue(&creq,0,0)) {
- return;
- }
- break;
-
- case WRITE:
-#if AP_DEBUG
- printk("apblock: write req=0x%x len=%d offset=%d\n",
- req,len,offset);
-#endif
- creq.type = REQ_BWRITE;
- creq.size += len;
- if (bif_queue_nocopy(&creq,req->buffer,creq.size - sizeof(creq))) {
- return;
- }
- break;
-
- default:
- printk("apblock: unknown ap op %d\n",req->cmd);
- end_request(0);
- return;
- }
-
- if (++request_count < MAX_REQUESTS)
- goto repeat;
-}
-
-/* this is called by ap1000/bif.c when a read/write has completed */
-void ap_complete(struct cap_request *creq)
-{
-#if AP_DEBUG
- struct request *req = (struct request *)(creq->data[0]);
-
- printk("request 0x%x complete\n",req);
-#endif
- end_request(1);
- request_count--;
- ap_request(NULL);
-}
-
-
-/* this is called by ap1000/bif.c to find a buffer to put a BREAD into
- using DMA */
-char *ap_buffer(struct cap_request *creq)
-{
- struct request *req = (struct request *)(creq->data[0]);
-
- return(req->buffer);
-}
-
-
-static int ap_open(struct inode * inode, struct file * filp)
-{
- struct cap_request creq;
- int minor;
- minor = DEVICE_NR(inode->i_rdev);
-
-#if AP_DEBUG
- printk("ap_open: minor=%x\n", minor);
-#endif
-
- if (minor >= NUM_APDEVS)
- return -ENODEV;
-
- /* if its already open then don't do anything */
- if (ap_fds[minor] != -1)
- return 0;
-
- /* send the open request to the front end */
- creq.cid = mpp_cid();
- creq.type = REQ_BOPEN;
- creq.header = 0;
- creq.size = sizeof(creq);
- creq.data[0] = minor;
-
- bif_queue(&creq,0,0);
-
- /* wait for the reply */
- while (ap_fds[minor] == -1)
- sleep_on(&busy_wait);
-
- return 0;
-}
-
-
-static int ap_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- if (!inode || !inode->i_rdev)
- return -EINVAL;
-
- switch (cmd) {
- case BLKGETSIZE: /* Return device size */
- if (put_user(ap_length[MINOR(inode->i_rdev)],(long *) arg))
- return -EFAULT;
- return 0;
-
- default:
- break;
- };
-
- return 0;
-}
-
-
-/* this is called by ap1000/bif.c when a open reply comes in */
-void ap_open_reply(struct cap_request *creq)
-{
- int minor = creq->data[0];
-
- ap_fds[minor] = creq->data[1];
- ap_length[minor] = creq->data[2] >> SECTOR_BLOCK_SHIFT;
-
-#if AP_DEBUG
- printk("ap opened minor %d length=%d fd=%d\n",
- minor,ap_length[minor],ap_fds[minor]);
-#endif
-
- wake_up(&busy_wait);
-}
-
-static struct block_device_operations ap_fops = {
- open: ap_open,
- release: ap_release,
- ioctl: ap_ioctl,
-};
-
-
-int ap_init(void)
-{
- int i;
- static int done = 0;
-
- if (done) return(1);
-
- if (register_blkdev(MAJOR_NR,"apblock",&ap_fops)) {
- printk("ap: unable to get major %d for ap block dev\n",MAJOR_NR);
- return -1;
- }
- printk("ap_init: register dev %d\n", MAJOR_NR);
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &ap_request);
-
- for (i=0;i<NUM_APDEVS;i++) {
- ap_blocksizes[i] = AP_BLOCK_SIZE;
- ap_length[i] = 0;
- ap_fds[i] = -1;
- }
-
- blksize_size[MAJOR_NR] = ap_blocksizes;
-
- read_ahead[MAJOR_NR] = 32; /* 16k read ahead */
- for (i=0;i<NUM_APDEVS;i++)
- register_disk(NILL, MKDEV(MAJOR_NR,i), 1, &ap_fops, 0);
-
- return(0);
-}
-
-/* loadable module support */
-
-#ifdef MODULE
-
-int init_module(void)
-{
- int error = ap_init();
- if (!error)
- printk(KERN_INFO "APBLOCK: Loaded as module.\n");
- return error;
-}
-
-/* Before freeing the module, invalidate all of the protected buffers! */
-void cleanup_module(void)
-{
- int i;
-
- for (i = 0 ; i < NUM_APDEVS; i++)
- invalidate_buffers(MKDEV(MAJOR_NR, i));
-
- unregister_blkdev( MAJOR_NR, "apblock" );
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
-}
-
-#endif /* MODULE */
diff --git a/drivers/ap1000/apfddi-reg.h b/drivers/ap1000/apfddi-reg.h
deleted file mode 100644
index b3f25fb2a..000000000
--- a/drivers/ap1000/apfddi-reg.h
+++ /dev/null
@@ -1,14 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/* FDDI register pointers */
-extern volatile struct formac *mac;
-extern volatile struct plc *plc;
-extern volatile int *csr0;
-extern volatile int *csr1;
-extern volatile int *buffer_mem;
-extern volatile int *fifo;
diff --git a/drivers/ap1000/apfddi.c b/drivers/ap1000/apfddi.c
deleted file mode 100644
index b215e8d03..000000000
--- a/drivers/ap1000/apfddi.c
+++ /dev/null
@@ -1,702 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * $Id: apfddi.c,v 1.6 1996/12/18 01:45:51 tridge Exp $
- *
- * Network interface definitions for AP1000 fddi device.
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/socket.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/in.h>
-#include <linux/if_ether.h> /* For the statistics structure. */
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-
-#include <linux/inet.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-
-#include <asm/ap1000/apservice.h>
-#include <asm/ap1000/apreg.h>
-#include <asm/irq.h>
-
-#include <net/arp.h>
-
-#include "apfddi.h"
-#include "smt-types.h"
-#include "mac.h"
-#include "plc.h"
-#include "am79c830.h"
-#include "apfddi-reg.h"
-
-volatile struct formac *mac;
-volatile struct plc *plc;
-volatile int *csr0;
-volatile int *csr1;
-volatile int *buffer_mem;
-volatile int *fifo;
-
-#define APFDDI_DEBUG 0
-
-#define APFDDI_IRQ 7
-
-#define T(x) (-SECS_TO_FDDI_TIME(x))
-
-struct plc_info plc_info = {
- pt_s, /* port_type */
- T(1.6e-3), /* c_min */
- T(50e-6), /* tl_min */
- T(5e-3), /* tb_min */
- T(100e-3), /* t_out */
- T(50e-3), /* lc_short */
- T(500e-3), /* lc_medium */
- T(5.0), /* lc_long */
- T(50.0), /* lc_extended */
- T(3.5e-3), /* t_scrub */
- T(1.3e-3), /* ns_max */
-};
-
-struct mac_info mac_info = {
- T(165e-3), /* tmax */
- T(3.5e-3), /* tvx */
- T(20e-3), /* treq */
- { 0x42, 0x59 }, /* s_address */
- { 0x42, 0x59, 0x10, 0x76, 0x88, 0x82 }, /* l_address */
- { 0 }, /* s_group_adrs */
- { 0 }, /* l_group_adrs */
- 0, /* rcv_own_frames */
- 1, /* only_good_frames */
-};
-
-u_char fddi_bitrev[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,
-};
-
-/* XXX our hardware address, canonical bit order */
-static u_char apfddi_saddr[6] = { 0x42, 0x9a, 0x08, 0x6e, 0x11, 0x41 };
-
-struct net_device *apfddi_device = NULL;
-struct net_device_stats *apfddi_stats = NULL;
-
-volatile struct apfddi_queue *apfddi_queue_top = NULL;
-
-void map_regs(void)
-{
- unsigned long reg_base_addr = 0xfbf00000;
-
- mac = (volatile struct formac *) (reg_base_addr + FORMAC);
- plc = (volatile struct plc *) (reg_base_addr + PLC);
- csr0 = (volatile int *) (reg_base_addr + CSR0);
- csr1 = (volatile int *) (reg_base_addr + CSR1);
- buffer_mem = (volatile int *) (reg_base_addr + BUFFER_MEM);
- fifo = (volatile int *) (reg_base_addr + FIFO);
-}
-
-int ring_op;
-
-void apfddi_startup(void)
-{
- int reason;
-
-#if APFDDI_DEBUG
- printk("In apfddi_startup\n");
-#endif
-
- *csr0 = CS0_LED0;
- ring_op = 0;
- if (*csr1 & 0xf078) {
- *csr1 = CS1_RESET_MAC | CS1_RESET_FIFO;
- *csr1 = 0;
- reason = 1;
- printk("resetting after power-on\n");
- } else {
- *csr1 = CS1_RESET_FIFO;
- *csr1 = 0;
- reason = plc_inited(&plc_info);
- if (reason)
- printk("resetting: plc reason %d\n", reason);
- }
- if (reason) {
-#if APFDDI_DEBUG
- printk("Calling plc_init\n");
-#endif
- plc_init(&plc_info);
-#if APFDDI_DEBUG
- printk("Calling mac_init\n");
-#endif
- mac_init(&mac_info);
- *csr0 |= CS0_LED1;
- pc_start(loop_none);
-
- } else {
- *csr0 |= CS0_LED2 | CS0_LED1;
- reason = mac_inited(&mac_info);
- if (reason) {
- printk("resetting mac: reason %d\n", reason);
- mac_init(&mac_info);
- mac_reset(loop_none);
- mac_claim();
- } else {
- ring_op = 1;
- *csr0 &= ~(CS0_LED0 | CS0_LED1 | CS0_LED2);
- }
- }
-}
-
-void apfddi_off(void)
-{
- *csr0 &= ~CS0_LED1;
- pc_stop();
-}
-
-void apfddi_sleep(void)
-{
- mac_sleep();
- plc_sleep();
-}
-
-void apfddi_poll(void)
-{
- if (*csr0 & CS0_PHY_IRQ)
- plc_poll();
- if (*csr0 & CS0_MAC_IRQ)
- mac_poll();
-}
-
-void set_cf_join(int on)
-{
- if (on) {
-#if APFDDI_DEBUG
- printk("apfddi: joined the ring!\n");
-#endif
- mac_reset(loop_none);
- *csr0 |= CS0_LED2;
- mac_claim();
- } else {
- mac_disable();
- ring_op = 0;
- *csr0 = (*csr0 & ~CS0_LED2) | CS0_LED1 | CS0_LED0;
- }
-}
-
-void set_ring_op(int up)
-{
- ring_op = up;
- if (up) {
-#if APFDDI_DEBUG
- printk("apfddi: ring operational!\n");
-#endif
- *csr0 &= ~(CS0_LED2 | CS0_LED1 | CS0_LED0);
- } else
- *csr0 |= CS0_LED2 | CS0_LED1 | CS0_LED0;
-}
-
-void rmt_event(int st)
-{
- if (st & (S2_BEACON_STATE|S2_MULTIPLE_DA|S2_TOKEN_ERR
- |S2_DUPL_CLAIM|S2_TRT_EXP_RECOV)) {
- printk("st2 = %x\n", st);
- }
-}
-
-
-int apfddi_init(struct net_device *dev);
-static void apfddi_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int apfddi_xmit(struct sk_buff *skb, struct net_device *dev);
-int apfddi_rx(struct mac_buf *mbuf);
-static struct net_device_stats *apfddi_get_stats(struct net_device *dev);
-#if APFDDI_DEBUG
-void dump_packet(char *action, char *buf, int len, int seq);
-#endif
-
-/*
- * Create FDDI header for an arbitrary protocol layer
- *
- * saddr=NULL means use device source address (always will anyway)
- * daddr=NULL means leave destination address (eg unresolved arp)
- */
-static int apfddi_hard_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type, void *daddr,
- void *saddr, unsigned len)
-{
- struct fddi_header *fh;
- struct llc_header *lh;
- u_char *base_header;
- u_char *fd_daddr = (u_char *)daddr;
- int i;
-
-#if APFDDI_DEBUG
- printk("In apfddi_hard_header\n");
-#endif
-
- if (skb == NULL) {
- printk("Null skb in apfddi_hard_header... returning...\n");
- return 0;
- }
-
- switch(type) {
- case ETH_P_IP:
-#if APFDDI_DEBUG
- printk("apfddi_hard_header: Processing IP packet\n");
-#endif
- break;
- case ETH_P_ARP:
-#if APFDDI_DEBUG
- printk("apfddi_hard_header: Processing ARP packet\n");
-#endif
- break;
- case ETH_P_RARP:
-#if APFDDI_DEBUG
- printk("apfddi_hard_header: Processing RARP packet\n");
-#endif
- break;
- default:
- printk("apfddi_hard_header: I don't understand protocol %d (0x%x)\n",
- type, type);
- apfddi_stats->tx_errors++;
- return 0;
- }
-
- base_header = (u_char *)skb_push(skb, FDDI_HARDHDR_LEN-4);
- if (base_header == NULL) {
- printk("apfddi_hard_header: Memory squeeze, dropping packet.\n");
- apfddi_stats->tx_dropped++;
- return 0;
- }
- fh = (struct fddi_header *)(base_header + 3);
- lh = (struct llc_header *)((char *)fh + FDDI_HDRLEN);
-
- lh->llc_dsap = lh->llc_ssap = LLC_SNAP_LSAP;
- lh->snap_control = LLC_UI;
- lh->snap_org_code[0] = 0;
- lh->snap_org_code[1] = 0;
- lh->snap_org_code[2] = 0;
- lh->snap_ether_type = htons(type);
-
-#if APFDDI_DEBUG
- printk("snap_ether_type is %d (0x%x)\n", lh->snap_ether_type,
- lh->snap_ether_type);
-#endif
-
- fh->fddi_fc = FDDI_FC_LLC;
-
- /*
- * Fill in the source address.
- */
- for (i = 0; i < 6; i++)
- fh->fddi_shost[i] = fddi_bitrev[apfddi_saddr[i]];
-
- /*
- * Fill in the destination address.
- */
- if (daddr) {
-#if APFDDI_DEBUG
- printk("daddr is: ");
-#endif
- for (i = 0; i < 6; i++) {
- fh->fddi_dhost[i] = fddi_bitrev[fd_daddr[i]];
-#if APFDDI_DEBUG
- printk("%x(%x):",fh->fddi_dhost[i], fd_daddr[i]);
-#endif
- }
-#if APFDDI_DEBUG
- printk("\n");
-#endif
- return(FDDI_HARDHDR_LEN-4);
- }
- else {
-#if APFDDI_DEBUG
- printk("apfddi_hard_header, daddr was NULL\n");
-#endif
- return -(FDDI_HARDHDR_LEN-4);
- }
-}
-
-/*
- * Rebuild the FDDI header. This is called after an ARP (or in future
- * other address resolution) has completed on this sk_buff. We now let
- * ARP fill in the other fields.
- */
-static int apfddi_rebuild_header(void *buff, struct net_device *dev,
- unsigned long raddr, struct sk_buff *skb)
-{
- int i, status;
- struct fddi_header *fh = (struct fddi_header *)(buff+3);
-
-#if APFDDI_DEBUG
- printk("In apfddi_rebuild_header, dev is %x apfddi_device is %x\n", dev,
- apfddi_device);
- printk("rebuild header for fc 0x%x\n", fh->fddi_fc);
- printk("dest address is:\n");
- for (i = 0; i < 6; i++) printk("%x:", fh->fddi_dhost[i]);
-#endif
- status = arp_find(raddr, skb) ? 1 : 0;
-
- if (!status) {
-#if APFDDI_DEBUG
- printk("dest address is now:\n");
- for (i = 0; i < 6; i++) printk("%x:", fh->fddi_dhost[i]);
- printk("status is %d\n", status);
-#endif
- /*
- * Bit reverse the dest_address.
- */
- for (i = 0; i < 6; i++)
- fh->fddi_dhost[i] = fddi_bitrev[fh->fddi_dhost[i]];
- }
-#if APFDDI_DEBUG
- printk("\n");
-#endif
- return(status);
-}
-
-static int apfddi_set_mac_address(struct net_device *dev, void *addr)
-{
-#if APFDDI_DEBUG
- printk("In apfddi_set_mac_address\n");
-#endif
- return (0);
-}
-
-static void apfddi_set_multicast_list(struct net_device *dev)
-{
-#if APFDDI_DEBUG
- printk("In apfddi_set_multicast_list\n");
-#endif
-}
-
-static int apfddi_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-#if APFDDI_DEBUG
- printk("In apfddi_do_ioctl\n");
-#endif
- return (0);
-}
-
-static int apfddi_set_config(struct net_device *dev, struct ifmap *map)
-{
-#if APFDDI_DEBUG
- printk("In apfddi_set_config\n");
-#endif
- return (0);
-}
-
-/*
- * Opening the fddi device through ifconfig.
- */
-int apfddi_open(struct net_device *dev)
-{
- static int already_run = 0;
- unsigned flags;
- int res;
-
- if (already_run) {
- apfddi_startup();
- *csr0 |= CS0_INT_ENABLE;
- return 0;
- }
- already_run = 1;
-
- map_regs();
- apfddi_startup();
-
- save_flags(flags); cli();
- if ((res = request_irq(APFDDI_IRQ, apfddi_interrupt, SA_INTERRUPT,
- "apfddi", dev))) {
- printk("Failed to install apfddi handler error=%d\n", res);
- restore_flags(flags);
- return(0);
- }
- enable_irq(APFDDI_IRQ);
- restore_flags(flags);
-
-#if APFDDI_DEBUG
- printk("Installed apfddi interrupt handler\n");
-#endif
- *csr0 |= CS0_INT_ENABLE;
-#if APFDDI_DEBUG
- printk("Enabled fddi interrupts\n");
-#endif
-
- return 0;
-}
-
-/*
- * Stop the fddi device through ifconfig.
- */
-int apfddi_stop(struct net_device *dev)
-{
- *csr0 &= ~CS0_INT_ENABLE;
- apfddi_sleep();
- return 0;
-}
-
-
-/*
- * Initialise fddi network interface.
- */
-int apfddi_init(struct net_device *dev)
-{
- int i;
-
- /*
- * Check if this thing has already been initialised.
- */
- if (apfddi_device != NULL)
- return -ENODEV;
-
- printk("apfddi_init(): Initialising fddi interface\n");
-
- apfddi_device = dev;
-
- dev->open = apfddi_open;
- dev->stop = apfddi_stop;
- dev->hard_start_xmit = apfddi_xmit;
- dev->get_stats = apfddi_get_stats;
- dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_ATOMIC);
- if (dev->priv == NULL)
- return -ENOMEM;
- memset(dev->priv, 0, sizeof(struct net_device_stats));
- apfddi_stats = (struct net_device_stats *)apfddi_device->priv;
-
- /* Initialise the fddi device structure */
- for (i = 0; i < DEV_NUMBUFFS; i++)
- skb_queue_head_init(&dev->buffs[i]);
-
- dev->hard_header = apfddi_hard_header;
- dev->rebuild_header = apfddi_rebuild_header;
- dev->set_mac_address = apfddi_set_mac_address;
- dev->header_cache_update = NULL;
- dev->do_ioctl = apfddi_do_ioctl;
- dev->set_config = apfddi_set_config;
- dev->set_multicast_list = apfddi_set_multicast_list;
- dev->type = ARPHRD_ETHER;
- dev->hard_header_len = FDDI_HARDHDR_LEN;
- dev->mtu = FDDIMTU;
- dev->addr_len = 6;
- memcpy(dev->dev_addr, apfddi_saddr, sizeof(apfddi_saddr));
- dev->tx_queue_len = 100; /* XXX What should this be? */
- dev->irq = APFDDI_IRQ;
-
- memset(dev->broadcast, 0xFF, ETH_ALEN);
-
- return(0);
-}
-
-static void apfddi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-#if APFDDI_DEBUG
- static int times = 0;
-#endif
- unsigned flags;
- save_flags(flags); cli();
-
-#if APFDDI_DEBUG
- printk("In apfddi_interrupt irq %d dev_id %p times %d\n",
- irq, dev_id, ++times);
-#endif
-
- apfddi_poll();
- restore_flags(flags);
-}
-
-#if APFDDI_DEBUG
-static char *flagbits[8] = {
- "fin", "syn", "rst", "push", "ack", "urg", "6", "7"
-};
-
-void dump_packet(action, buf, len, seq)
- char *action, *buf;
- int len, seq;
-{
- int i, flags;
- char *sep;
-
- printk("%s packet %d of %d bytes at %d:\n", action, seq,
- len, jiffies);
- printk(" from %x to %x pktid=%d ttl=%d pcol=%d len=%d\n",
- *(long *)(buf+12), *(long *)(buf+16), *(u_short *)(buf+4),
- *(unsigned char *)(buf+8), buf[9], *(u_short *)(buf+2));
- if( buf[9] == 6 || buf[9] == 17 ){
- /* TCP or UDP */
- printk(" sport=%d dport=%d",
- *(u_short *)(buf+20), *(u_short *)(buf+22));
- if( buf[9] == 6 ){
- printk(" seq=%d ack=%d win=%d flags=<",
- *(long *)(buf+24), *(long *)(buf+28),
- *(unsigned short *)(buf+34));
- flags = buf[33];
- sep = "";
- for (i = 7; i >= 0; --i) {
- if (flags & (1 << i)) {
- printk("%s%s", sep, flagbits[i]);
- sep = "+";
- }
- }
- printk(">");
- }
- printk("\n");
- }
-}
-#endif
-
-#if APFDDI_DEBUG
-static void apfddi_print_frame(struct sk_buff *skb)
-{
- int i;
- struct llc_header *lh;
- static int seq = 0;
-
-#if 0
- printk("skb->len is %d\n", skb->len);
- printk("fc is 0x%x\n", *(u_char *)(skb->data+3));
- printk("dest address is:\n");
- for (i = 0; i < 6; i++) {
- printk("%x:", fddi_bitrev[*(u_char *)(skb->data+4+i)]);
- }
- printk("\n");
- printk("source address is:\n");
- for (i = 0; i < 6; i++) {
- printk("%x:", fddi_bitrev[*(u_char *)(skb->data+10+i)]);
- }
- printk("\n");
-#endif
- lh = (struct llc_header *)(skb->data+16);
-#if 0
- printk("llc_dsp %d llc_ssap %d snap_control %d org_code [0]=%d [1]=%d [2]=%d ether_type=%d\n",
- lh->llc_dsap, lh->llc_ssap, lh->snap_control,
- lh->snap_org_code[0], lh->snap_org_code[1], lh->snap_org_code[2],
- lh->snap_ether_type);
-#endif
- if (lh->snap_ether_type == ETH_P_IP)
- dump_packet("apfddi_xmit:", skb->data+24, skb->len-24, seq++);
-}
-#endif
-
-/*
- * Transmitting packet over FDDI.
- */
-static int apfddi_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- unsigned long flags;
-
-#if APFDDI_DEBUG
- printk("In apfddi_xmit\n");
-#endif
-
- /*
- * Check there is some work to do.
- */
- if (skb == NULL || dev == NULL)
- return(0);
-
-#if APFDDI_DEBUG
- printk("skb address is for apfddi 0x%x\n", skb);
-#endif
-
- /*
- * Check lock variable.
- */
- save_flags(flags); cli();
- if (dev->tbusy != 0) {
- restore_flags(flags);
- printk("apfddi_xmit: device busy\n");
- apfddi_stats->tx_errors++;
- return 1;
- }
- restore_flags(flags);
- dev->tbusy = 1;
-
- dev->trans_start = jiffies;
-
- skb->mac.raw = skb->data;
-
- /*
- * Append packet onto send queue.
- */
- if (mac_queue_append(skb)) {
- /*
- * No memory.
- */
- return 1;
- }
-
- /*
- * Process packet queue.
- */
- mac_process();
-
- apfddi_stats->tx_packets++;
- dev->tbusy = 0;
- return 0;
-}
-
-#if APFDDI_DEBUG
-void print_mbuf(struct mac_buf *mbuf)
-{
- printk("mac %p length=%d ptr=%p wraplen=%d wrapptr=%x fr_start=%d fr_end=%d\n",
- mbuf, mbuf->length, mbuf->ptr, mbuf->wraplen, mbuf->wrapptr,
- mbuf->fr_start, mbuf->fr_end);
-}
-#endif
-
-/*
- * Return statistics of fddi driver.
- */
-static struct net_device_stats *apfddi_get_stats(struct net_device *dev)
-{
- return((struct net_device_stats *)dev->priv);
-}
-
-
-
-
diff --git a/drivers/ap1000/apfddi.h b/drivers/ap1000/apfddi.h
deleted file mode 100644
index a77dd6160..000000000
--- a/drivers/ap1000/apfddi.h
+++ /dev/null
@@ -1,142 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-#define BUFFER_MEM 0x40000
-#define CSR0 0x60000
-#define CSR1 0x60004
-#define PLC 0x60080
-#define FORMAC 0x60200
-#define FIFO 0x68000
-
-/* Size of buffer memory */
-#define BUFFER_SIZE 32768 /* words; 128kB */
-
-/* Bits in CSR0 */
-#define CS0_INT_REQ 0x8000 /* board interrupt request asserted */
-#define CS0_MAC_IRQ 0x4000 /* FORMAC is requesting interrupt */
-#define CS0_PHY_IRQ 0x2000 /* PLC is requesting interrupt */
-#define CS0_LED2 0x1000 /* turn on led 2 */
-#define CS0_DO_IRQ 0x0200 /* request interrupt */
-#define CS0_INT_ENABLE 0x0100 /* enable interrupt requests */
-#define CS0_DMA_ENABLE 0x0080 /* enable DMA requests */
-#define CS0_DMA_RECV 0x0040 /* DMA requests are in receive dirn. */
-#define CS0_LED1 0x0010 /* turn on led 1 */
-#define CS0_LED0 0x0008 /* turn on led 0 (red) */
-#define CS0_HREQ 0x0007 /* host request to FORMAC */
-#define CS0_HREQ_WSPEC 0x0002 /* write special frames */
-#define CS0_HREQ_RECV 0x0003 /* read receive queue */
-#define CS0_HREQ_WS 0x0004 /* write synchronous queue */
-#define CS0_HREQ_WA0 0x0005 /* write async queue 0 */
-#define CS0_HREQ_WA1 0x0006 /* write async queue 1 */
-#define CS0_HREQ_WA2 0x0007 /* write async queue 2 */
-
-/* Bits in CSR1 */
-#define CS1_THIS_QAF 0x0800 /* this queue almost full */
-#define CS1_FIFO_TAG 0x0400 /* tag of word at head of fifo */
-#define CS1_BUF_RD_TAG 0x0200 /* tag of last word read from buffer */
-#define CS1_BUF_WR_TAG 0x0100 /* tag to write to buffer */
-#define CS1_TAGMODE 0x0080 /* enable tag mode */
-#define CS1_RESET_MAC 0x0040 /* reset FORMAC and PLC */
-#define CS1_RESET_FIFO 0x0020 /* reset FIFO */
-#define CS1_CLEAR_QAF 0x0010 /* clear queue-almost-full bits */
-#define CS1_FIFO_LEVEL 0x0007 /* # words in FIFO (0 - 4) */
-
-/*
- * FDDI Frame Control values.
- */
-#define FDDI_SMT 0x41
-#define FDDI_SMT_NSA 0x4f
-#define FDDI_FC_LLC 0x50
-#define FDDI_FC_LLC_MASK 0xf0
-
-/*
- * Unnumbered LLC format commands
- */
-#define LLC_UI 0x3
-#define LLC_UI_P 0x13
-#define LLC_DISC 0x43
-#define LLC_DISC_P 0x53
-#define LLC_UA 0x63
-#define LLC_UA_P 0x73
-#define LLC_TEST 0xe3
-#define LLC_TEST_P 0xf3
-#define LLC_FRMR 0x87
-#define LLC_FRMR_P 0x97
-#define LLC_DM 0x0f
-#define LLC_DM_P 0x1f
-#define LLC_XID 0xaf
-#define LLC_XID_P 0xbf
-#define LLC_SABME 0x6f
-#define LLC_SABME_P 0x7f
-
-/*
- * Supervisory LLC commands
- */
-#define LLC_RR 0x01
-#define LLC_RNR 0x05
-#define LLC_REJ 0x09
-
-/*
- * Info format - dummy only
- */
-#define LLC_INFO 0x00
-
-/*
- * ISO PDTR 10178 contains among others
- */
-#define LLC_X25_LSAP 0x7e
-#define LLC_SNAP_LSAP 0xaa
-#define LLC_ISO_LSAP 0xfe
-
-/*
- * Structure of the FDDI MAC header.
- */
-struct fddi_header {
- u_char fddi_fc; /* frame control field */
- u_char fddi_dhost[6]; /* destination address */
- u_char fddi_shost[6]; /* source address */
-};
-
-/*
- * Structure of LLC/SNAP header.
- */
-struct llc_header {
- u_char llc_dsap;
- u_char llc_ssap;
- u_char snap_control;
- u_char snap_org_code[3];
- u_short snap_ether_type;
-};
-
-#define FDDI_HDRLEN 13 /* sizeof(struct fddi_header) */
-#define LLC_SNAPLEN 8 /* bytes for LLC/SNAP header */
-#define FDDI_HARDHDR_LEN 28 /* Hard header size */
-
-#define FDDIMTU 4352
-
-
-/* Types of loopback we can do. */
-typedef enum {
- loop_none,
- loop_formac,
- loop_plc_lm,
- loop_plc_eb,
- loop_pdx
-} LoopbackType;
-
-/* Offset from fifo for writing word with tag. */
-#define FIFO_TAG 0x80
-
-#define MAX_FRAME_LEN 4500
-
-void set_ring_op(int up);
-void rmt_event(int st);
-void set_cf_join(int on);
-
-extern struct net_device *apfddi_device;
-extern struct net_device_stats *apfddi_stats;
-
diff --git a/drivers/ap1000/bif.c b/drivers/ap1000/bif.c
deleted file mode 100644
index 331ee0f26..000000000
--- a/drivers/ap1000/bif.c
+++ /dev/null
@@ -1,280 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * $Id: bif.c,v 1.13 1996/12/18 01:45:52 tridge Exp $
- *
- * Network interface definitions for bif device.
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/socket.h>
-#include <linux/errno.h>
-#include <linux/fcntl.h>
-#include <linux/in.h>
-#include <linux/if_ether.h> /* For the statistics structure. */
-#include <linux/netdevice.h>
-#include <linux/if_arp.h> /* For ARPHRD_BIF */
-
-#include <asm/system.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-
-#include <linux/inet.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <net/sock.h>
-
-#include <asm/ap1000/apservice.h>
-#include <asm/ap1000/apreg.h>
-
-#define BIF_DEBUG 0
-#if BIF_DEBUG
-static int seq = 0;
-#endif
-
-#define BIF_MTU 10240
-
-static struct net_device *bif_device = 0;
-static struct net_device_stats *bif_stats = 0;
-
-int bif_init(struct net_device *dev);
-int bif_open(struct net_device *dev);
-static int bif_xmit(struct sk_buff *skb, struct net_device *dev);
-int bif_rx(struct sk_buff *skb);
-int bif_stop(struct net_device *dev);
-static struct net_device_stats *bif_get_stats(struct net_device *dev);
-
-static int bif_hard_header(struct sk_buff *skb, struct net_device *dev,
- unsigned short type, void *daddr,
- void *saddr, unsigned len)
-{
-#if BIF_DEBUG
- printk("bif_hard_header()\n");
-#endif
-
- skb_push(skb,dev->hard_header_len);
-
- if (daddr) skb->arp = 1;
-
- /* tell IP how much space we took */
- return (dev->hard_header_len);
-}
-
-static int bif_rebuild_header(void *buff, struct net_device *dev,
- unsigned long raddr, struct sk_buff *skb)
-{
- /* this would normally be used to fill in hardware addresses after
- an ARP */
-#if BIF_DEBUG
- printk("bif_rebuild_header()\n");
-#endif
- if (skb) skb->arp = 1;
- return(0);
-}
-
-static int bif_set_mac_address(struct net_device *dev, void *addr)
-{
- printk("BIF: set_mac_address called\n");
- return (0);
-}
-
-static void bif_set_multicast_list(struct net_device *dev)
-{
- return;
-}
-
-static int bif_do_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
- printk("BIF: Called do_ioctl\n");
- return (0);
-}
-
-static int bif_set_config(struct net_device *dev, struct ifmap *map)
-{
- printk("BIF: Called bif_set_config\n");
- return (0);
-}
-
-/*
- * Initialise bif network interface.
- */
-int bif_init(struct net_device *dev)
-{
- int i;
-
- printk("bif_init(): Initialising bif interface\n");
- bif_device = dev;
-
- dev->mtu = BIF_MTU;
- dev->tbusy = 0;
- dev->hard_start_xmit = bif_xmit;
- dev->hard_header = bif_hard_header;
- dev->hard_header_len = sizeof(struct cap_request);
- dev->addr_len = 0;
- dev->tx_queue_len = 50000; /* no limit (almost!) */
- dev->type = ARPHRD_BIF;
- dev->rebuild_header = bif_rebuild_header;
- dev->open = bif_open;
- dev->flags = IFF_NOARP; /* Don't use ARP on this device */
- dev->priv = kmalloc(sizeof(struct net_device_stats), GFP_KERNEL);
- if (dev->priv == NULL)
- return -ENOMEM;
- memset(dev->priv, 0, sizeof(struct net_device_stats));
- bif_stats = (struct net_device_stats *)bif_device->priv;
-
-
- dev->stop = bif_stop;
- dev->get_stats = bif_get_stats;
-
- dev->set_mac_address = bif_set_mac_address;
- dev->header_cache_update = NULL;
- dev->do_ioctl = bif_do_ioctl;
- dev->set_config = bif_set_config;
- dev->set_multicast_list = bif_set_multicast_list;
-
- memset(dev->broadcast, 0xFF, ETH_ALEN);
-
- dev_init_buffers(dev);
-
- return(0);
-}
-
-int bif_open(struct net_device *dev)
-{
- printk("In bif_open\n");
- dev->tbusy = 0;
- dev->start = 1;
- return 0;
-}
-
-#if BIF_DEBUG
-static void dump_packet(char *action, char *buf, int len, int seq)
-{
- int flags;
- char *sep;
-
- printk("%s packet %d of %d bytes at %d:\n", action, seq,
- len, (int)jiffies);
- printk(" from %x to %x pktid=%d ttl=%d pcol=%d len=%d\n",
- *(long *)(buf+12), *(long *)(buf+16), *(u_short *)(buf+4),
- *(unsigned char *)(buf+8), buf[9], *(u_short *)(buf+2));
- if( buf[9] == 6 || buf[9] == 17 ){
- /* TCP or UDP */
- printk(" sport=%d dport=%d",
- *(u_short *)(buf+20), *(u_short *)(buf+22));
- if( buf[9] == 6 ){
- printk(" seq=%d ack=%d win=%d flags=<",
- *(long *)(buf+24), *(long *)(buf+28),
- *(unsigned short *)(buf+34));
- flags = buf[33];
- sep = "";
- printk(">");
- }
- printk("\n");
- }
- else {
- printk(" protocol = %d\n", buf[9]);
- }
-}
-#endif
-
-
-static int bif_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- extern int bif_send_ip(int cid,struct sk_buff *skb);
- extern int tnet_send_ip(int cid,struct sk_buff *skb);
- extern int msc_blocked, tnet_ip_enabled;
- u_long destip;
- int cid;
-
- if (skb == NULL || dev == NULL)
- return(0);
-
- destip = *(u_long *)(skb->data+sizeof(struct cap_request)+16);
- cid = ap_ip_to_cid(destip);
-
- skb->dev = dev;
- skb->mac.raw = skb->data;
-
- if (cid != -1 && tnet_ip_enabled && !msc_blocked) {
- tnet_send_ip(cid,skb);
- } else {
- bif_send_ip(cid, skb);
- }
-
- dev->tbusy = 0;
-
- bif_stats->tx_packets++;
-
- mark_bh(NET_BH);
-
- return 0;
-}
-
-
-/*
- * Receive a packet from the BIF - called from interrupt handler.
- */
-int bif_rx(struct sk_buff *skb)
-{
-#if BIF_DEBUG
- dump_packet("bif_rx:", skb->data, skb->len, seq++);
-#endif
-
- if (bif_device == NULL) {
- printk("bif: bif_device is NULL in bif_rx\n");
- dev_kfree_skb(skb);
- return 0;
- }
- skb->dev = bif_device;
- skb->protocol = ETH_P_IP;
-
-#if 1
- /* try disabling checksums on receive */
- if (ap_ip_to_cid(*(u_long *)(((char *)skb->data)+12)) != -1)
- skb->ip_summed = CHECKSUM_UNNECESSARY;
-#endif
-
- /*
- * Inform the network layer of the new packet.
- */
- skb->mac.raw = skb->data;
- netif_rx(skb);
-
- if (bif_stats == NULL) {
- printk("bif: bif_stats is NULL is bif_rx\n");
- return 0;
- }
- bif_stats->rx_packets++;
-
- return 0;
-}
-
-int bif_stop(struct net_device *dev)
-{
- printk("in bif_close\n");
-
- dev->tbusy = 1;
- dev->start = 0;
-
- return 0;
-}
-
-/*
- * Return statistics of bif driver.
- */
-static struct net_device_stats *bif_get_stats(struct net_device *dev)
-{
- return((struct net_device_stats *)dev->priv);
-}
-
diff --git a/drivers/ap1000/ddv.c b/drivers/ap1000/ddv.c
deleted file mode 100644
index 3e32c9c83..000000000
--- a/drivers/ap1000/ddv.c
+++ /dev/null
@@ -1,1008 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * ddv.c - Single AP1000 block driver.
- *
- * This block driver performs io operations to the ddv option
- * board. (Hopefully:)
- *
- */
-
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/fs.h>
-#include <linux/ext2_fs.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/mm.h>
-#include <linux/malloc.h>
-#define __KERNEL_SYSCALLS__
-#include <linux/unistd.h>
-#include <linux/sched.h>
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
-#include <linux/module.h>
-#include <asm/ap1000/apreg.h>
-#include <asm/ap1000/DdvReqTable.h>
-
-#define MAJOR_NR DDV_MAJOR
-
-#include <linux/blk.h>
-#include <linux/genhd.h>
-#include <linux/hdreg.h>
-
-#define DDV_DEBUG 0
-#define AIR_DISK 1
-
-#define SECTOR_SIZE 512
-
-/* we can have lots of partitions */
-#define PARTN_BITS 6
-#define NUM_DDVDEVS (1<<PARTN_BITS)
-
-#define PARDISK_BASE (1<<5) /* partitions above this number are
- striped across all the cells */
-#define STRIPE_SHIFT 6
-#define STRIPE_SECTORS (1<<STRIPE_SHIFT) /* number of sectors per stripe */
-
-#define MAX_BNUM 16
-#define MAX_REQUEST (TABLE_SIZE - 2)
-#define REQUEST_LOW 16
-#define REQUEST_HIGH 4
-
-
-/* we fake up a block size larger than the physical block size to try
- to make things a bit more efficient */
-#define SECTOR_BLOCK_SHIFT 9
-
-#define SECTOR_MASK ((BLOCK_SIZE >> 9) - 1)
-
-/* try to read ahead a bit */
-#define DDV_READ_AHEAD 64
-
-static int have_ddv_board = 1;
-static unsigned num_options = 0;
-static unsigned this_option = 0;
-
-extern int ddv_get_mlist(unsigned mptr[],int bnum);
-extern int ddv_set_request(struct request *req,
- int request_type,int bnum,int mlist,int len,int offset);
-extern void ddv_load_kernel(char *opcodep);
-extern int ddv_restart_cpu(void);
-extern int ddv_mlist_available(void);
-static int ddv_revalidate(kdev_t dev, struct gendisk *gdev);
-static void ddv_geninit(void);
-static void ddv_release(struct inode * inode, struct file * filp);
-static void ddv_request1(void);
-
-
-static char *ddv_opcodep = NULL;
-static struct request *next_request = NULL;
-
-static DECLARE_WAIT_QUEUE_HEAD(busy_wait);
-
-static int ddv_blocksizes[NUM_DDVDEVS]; /* in bytes */
-int ddv_sect_length[NUM_DDVDEVS]; /* in sectors */
-int ddv_blk_length[NUM_DDVDEVS]; /* in blocks */
-
-/* these are used by the ddv_daemon, which services remote disk requests */
-static struct remote_request *rem_queue = NULL;
-static struct remote_request *rem_queue_end;
-static DECLARE_WAIT_QUEUE_HEAD(ddv_daemon_wait);
-
-static int opiu_kernel_loaded = 0;
-
-static struct {
- unsigned reads, writes, blocks, rq_started, rq_finished, errors;
- unsigned sectors_read, sectors_written;
-} ddv_stats;
-
-static struct hd_struct partition_tables[NUM_DDVDEVS];
-
-static struct gendisk ddv_gendisk = {
- MAJOR_NR, /* Major number */
- DEVICE_NAME, /* Major name */
- PARTN_BITS, /* Bits to shift to get real from partition */
- 1 << PARTN_BITS, /* Number of partitions per real */
- partition_tables,/* hd struct */
- ddv_blk_length, /* block sizes */
- 1, /* number */
- (void *) NULL, /* internal */
- NULL /* next */
-};
-
-struct ddv_geometry {
- unsigned char heads;
- unsigned char sectors;
- unsigned short cylinders;
- unsigned long start;
-};
-
-static struct ddv_geometry ddv_geometry;
-
-
-struct remote_request {
- union {
- struct remote_request *next;
- void (*fn)(void);
- } u;
- unsigned bnum; /* how many blocks does this contain */
- struct request *reqp; /* pointer to the request on the original cell */
- unsigned cell; /* what cell is the request from */
- struct request req; /* details of the request */
-};
-
-
-static void ddv_set_optadr(void)
-{
- unsigned addr = 0x11000000;
- OPT_IO(OBASE) = addr;
- MSC_IO(MSC_OPTADR) =
- ((addr & 0xff000000)>>16) |
- ((OPTION_BASE & 0xf0000000)>>24) |
- ((OPTION_BASE + 0x10000000)>>28);
- OPT_IO(PRST) = 0;
-}
-
-extern struct RequestTable *RTable;
-extern struct OPrintBufArray *PrintBufs;
-extern struct OAlignBufArray *AlignBufs;
-extern struct DiskInfo *DiskInfo;
-
-static void ddv_release(struct inode * inode, struct file * filp)
-{
-#if DEBUG
- printk("ddv_release started\n");
-#endif
-#if DEBUG
- printk("ddv_release done\n");
-#endif
-}
-
-
-static unsigned in_request = 0;
-static unsigned req_queued = 0;
-
-static void ddv_end_request(int uptodate,struct request *req)
-{
- struct buffer_head * bh;
-
- ddv_stats.rq_finished++;
-
-/* printk("ddv_end_request(%d,%p)\n",uptodate,req); */
-
- req->errors = 0;
- if (!uptodate) {
- printk("end_request: I/O error, dev %s, sector %lu\n",
- kdevname(req->rq_dev), req->sector);
- req->nr_sectors--;
- req->nr_sectors &= ~SECTOR_MASK;
- req->sector += (BLOCK_SIZE / SECTOR_SIZE);
- req->sector &= ~SECTOR_MASK;
- ddv_stats.errors++;
- }
-
- if ((bh = req->bh) != NULL) {
- req->bh = bh->b_reqnext;
- bh->b_reqnext = NULL;
- mark_buffer_uptodate(bh, uptodate);
- unlock_buffer(bh);
- if ((bh = req->bh) != NULL) {
- req->current_nr_sectors = bh->b_size >> 9;
- if (req->nr_sectors < req->current_nr_sectors) {
- req->nr_sectors = req->current_nr_sectors;
- printk("end_request: buffer-list destroyed\n");
- }
- req->buffer = bh->b_data;
- printk("WARNING: ddv: more sectors!\n");
- ddv_stats.errors++;
- return;
- }
- }
- if (req->sem != NULL)
- up(req->sem);
- req->rq_status = RQ_INACTIVE;
- wake_up(&wait_for_request);
-}
-
-
-/* check that a request is all OK to process */
-static int request_ok(struct request *req)
-{
- int minor;
- if (!req) return 0;
-
- if (MAJOR(req->rq_dev) != MAJOR_NR)
- panic(DEVICE_NAME ": bad major number\n");
- if (!buffer_locked(req->bh))
- panic(DEVICE_NAME ": block not locked");
-
- minor = MINOR(req->rq_dev);
- if (minor >= NUM_DDVDEVS) {
- printk("ddv_request: Invalid minor (%d)\n", minor);
- return 0;
- }
-
- if ((req->sector + req->current_nr_sectors) > ddv_sect_length[minor]) {
- printk("ddv: out of range minor=%d offset=%d len=%d sect_length=%d\n",
- minor,(int)req->sector,(int)req->current_nr_sectors,
- ddv_sect_length[minor]);
- return 0;
- }
-
- if (req->cmd != READ && req->cmd != WRITE) {
- printk("unknown request type %d\n",req->cmd);
- return 0;
- }
-
- /* it seems to be OK */
- return 1;
-}
-
-
-static void complete_request(struct request *req,int bnum)
-{
- while (bnum--) {
- ddv_end_request(1,req);
- req = req->next;
- }
-}
-
-
-static int completion_pointer = 0;
-
-static void check_completion(void)
-{
- int i,bnum;
- struct request *req;
-
- if (!RTable) return;
-
- for (;
- (i=completion_pointer) != RTable->ddv_pointer &&
- RTable->async_info[i].status == DDV_REQ_FREE;
- completion_pointer = INC_T(completion_pointer))
- {
- req = (struct request *)RTable->async_info[i].argv[7];
- bnum = RTable->async_info[i].bnum;
- if (!req || !bnum) {
- printk("%s(%d)\n",__FILE__,__LINE__);
- ddv_stats.errors++;
- continue;
- }
-
- RTable->async_info[i].status = 0;
- RTable->async_info[i].argv[7] = 0;
-
- complete_request(req,bnum);
- in_request--;
- }
-}
-
-
-static struct request *get_request_queue(struct request *oldq)
-{
- struct request *req,*req2;
-
- /* skip any non-active or bad requests */
- skip1:
- if (!(req = CURRENT))
- return oldq;
-
- if (req->rq_status != RQ_ACTIVE) {
- CURRENT = req->next;
- goto skip1;
- }
-
- if (!request_ok(req)) {
- ddv_end_request(0,req);
- CURRENT = req->next;
- goto skip1;
- }
-
- /* now grab as many as we can */
- req_queued++;
-
- for (req2 = req;
- req2->next &&
- req2->next->rq_status == RQ_ACTIVE &&
- request_ok(req2->next);
- req2 = req2->next)
- req_queued++;
-
- /* leave CURRENT pointing at the bad ones */
- CURRENT = req2->next;
-
- /* chop our list at that point */
- req2->next = NULL;
-
- if (!oldq)
- return req;
-
- for (req2=oldq;req2->next;req2=req2->next) ;
-
- req2->next = req;
-
- return oldq;
-}
-
-
-static void ddv_rem_complete(struct remote_request *rem)
-{
- unsigned flags;
- int bnum = rem->bnum;
- struct request *req = rem->reqp;
-
- complete_request(req,bnum);
- in_request--;
-
- save_flags(flags); cli();
- ddv_request1();
- restore_flags(flags);
-}
-
-
-/*
- * The background ddv daemon. This receives remote disk requests
- * and processes them via the normal block operations
- */
-static int ddv_daemon(void *unused)
-{
- current->session = 1;
- current->pgrp = 1;
- sprintf(current->comm, "ddv_daemon");
- spin_lock_irq(&current->sigmask_lock);
- sigfillset(&current->blocked); /* block all signals */
- recalc_sigpending(current);
- spin_unlock_irq(&current->sigmask_lock);
-
- /* Give it a realtime priority. */
- current->policy = SCHED_FIFO;
- current->priority = 32; /* Fixme --- we need to standardise our
- namings for POSIX.4 realtime scheduling
- priorities. */
-
- printk("Started ddv_daemon\n");
-
- while (1) {
- struct remote_request *rem;
- unsigned flags;
- struct buffer_head *bhlist[MAX_BNUM*4];
- int i,j,minor,len,shift,offset;
-
- save_flags(flags); cli();
-
- while (!rem_queue) {
- spin_lock(&current->sigmask_lock);
- flush_signals(current);
- spin_unlock(&current->sigmask_lock);
- interruptible_sleep_on(&ddv_daemon_wait);
- __sti(); cli();
- }
-
- rem = rem_queue;
- rem_queue = rem->u.next;
- restore_flags(flags);
-
-
- minor = MINOR(rem->req.rq_dev);
- len = rem->req.current_nr_sectors;
- offset = rem->req.sector;
-
- /* work out the conversion to the local block size from
- sectors */
- for (shift=0;
- (SECTOR_SIZE<<shift) != ddv_blocksizes[minor];
- shift++) ;
-
- /* do the request */
- for (i=0; len; i++) {
- bhlist[i] = getblk(rem->req.rq_dev,
- offset >> shift,
- ddv_blocksizes[minor]);
- if (!buffer_uptodate(bhlist[i]))
- ll_rw_block(READ,1,&bhlist[i]);
- offset += 1<<shift;
- len -= 1<<shift;
- }
-
- for (j=0;j<i;j++)
- if (!buffer_uptodate(bhlist[j]))
- wait_on_buffer(bhlist[j]);
-
-
- /* put() the data */
-
-
- /* release the buffers */
- for (j=0;j<i;j++)
- brelse(bhlist[j]);
-
- /* tell the originator that its done */
- rem->u.fn = ddv_rem_complete;
- tnet_rpc(rem->cell,rem,sizeof(int)*3,1);
- }
-}
-
-
-/* receive a remote disk request */
-static void ddv_rem_queue(char *data,unsigned size)
-{
- unsigned flags;
- struct remote_request *rem = (struct remote_request *)
- kmalloc(size,GFP_ATOMIC);
-
- if (!rem) {
- /* oh bugger! */
- ddv_stats.errors++;
- return;
- }
-
- memcpy(rem,data,size);
- rem->u.next = NULL;
-
- save_flags(flags); cli();
-
- /* add it to our remote request queue */
- if (!rem_queue)
- rem_queue = rem;
- else
- rem_queue_end->u.next = rem;
- rem_queue_end = rem;
-
- restore_flags(flags);
-
- wake_up(&ddv_daemon_wait);
-}
-
-
-/* which disk should this request go to */
-static inline unsigned pardisk_num(struct request *req)
-{
- int minor = MINOR(req->rq_dev);
- unsigned stripe;
- unsigned cell;
-
- if (minor < PARDISK_BASE)
- return this_option;
-
- stripe = req->sector >> STRIPE_SHIFT;
- cell = stripe % num_options;
-
- return cell;
-}
-
-
-/* check if a 2nd request can be tacked onto the first */
-static inline int contiguous(struct request *req1,struct request *req2)
-{
- if (req2->cmd != req1->cmd ||
- req2->rq_dev != req1->rq_dev ||
- req2->sector != req1->sector + req1->current_nr_sectors ||
- req2->current_nr_sectors != req1->current_nr_sectors)
- return 0;
- if (pardisk_num(req1) != pardisk_num(req2))
- return 0;
- return 1;
-}
-
-static void ddv_request1(void)
-{
- struct request *req,*req1,*req2;
- unsigned offset,len,req_num,mlist,bnum,available=0;
- static unsigned mptrs[MAX_BNUM];
- unsigned cell;
-
- if (in_request > REQUEST_HIGH)
- return;
-
- next_request = get_request_queue(next_request);
-
- while ((req = next_request)) {
- int minor;
-
- if (in_request >= MAX_REQUEST)
- return;
-
- if (in_request>1 && req_queued<REQUEST_LOW)
- return;
-
- /* make sure we have room for a request */
- available = ddv_mlist_available();
- if (available < 1) return;
- if (available > MAX_BNUM)
- available = MAX_BNUM;
-
- offset = req->sector;
- len = req->current_nr_sectors;
- minor = MINOR(req->rq_dev);
-
- mptrs[0] = (int)req->buffer;
-
- for (bnum=1,req1=req,req2=req->next;
- req2 && bnum<available && contiguous(req1,req2);
- req1=req2,req2=req2->next) {
- mptrs[bnum++] = (int)req2->buffer;
- }
-
- next_request = req2;
-
-
- req_queued -= bnum;
- ddv_stats.blocks += bnum;
- ddv_stats.rq_started += bnum;
-
- if (req->cmd == READ) {
- ddv_stats.reads++;
- ddv_stats.sectors_read += len*bnum;
- } else {
- ddv_stats.writes++;
- ddv_stats.sectors_written += len*bnum;
- }
-
- if (minor >= PARDISK_BASE) {
- /* translate the request to the normal partition */
- unsigned stripe;
- minor -= PARDISK_BASE;
-
- stripe = offset >> STRIPE_SHIFT;
- stripe /= num_options;
- offset = (stripe << STRIPE_SHIFT) +
- (offset & ((1<<STRIPE_SHIFT)-1));
-#if AIR_DISK
- /* like an air-guitar :-) */
- complete_request(req,bnum);
- continue;
-#endif
- }
-
- if ((cell=pardisk_num(req)) != this_option) {
- /* its a remote request */
- struct remote_request *rem;
- unsigned *remlist;
- unsigned size = sizeof(*rem) + sizeof(int)*bnum;
-
- rem = (struct remote_request *)kmalloc(size,GFP_ATOMIC);
- if (!rem) {
- /* hopefully we can get it on the next go */
- return;
- }
- remlist = (unsigned *)(rem+1);
-
- rem->u.fn = ddv_rem_queue;
- rem->cell = this_option;
- rem->bnum = bnum;
- rem->req = *req;
- rem->reqp = req;
- rem->req.rq_dev = MKDEV(MAJOR_NR,minor);
- rem->req.sector = offset;
- memcpy(remlist,mptrs,sizeof(mptrs[0])*bnum);
-
- if (tnet_rpc(cell,rem,size,1) != 0) {
- kfree_s(rem,size);
- return;
- }
- } else {
- /* its a local request */
- if ((mlist = ddv_get_mlist(mptrs,bnum)) == -1) {
- ddv_stats.errors++;
- panic("ddv: mlist corrupted");
- }
-
- req_num = RTable->cell_pointer;
- RTable->async_info[req_num].status =
- req->cmd==READ?DDV_RAWREAD_REQ:DDV_RAWWRITE_REQ;
- RTable->async_info[req_num].bnum = bnum;
- RTable->async_info[req_num].argv[0] = mlist;
- RTable->async_info[req_num].argv[1] = len;
- RTable->async_info[req_num].argv[2] = offset +
- partition_tables[minor].start_sect;
- RTable->async_info[req_num].argv[3] = bnum;
- RTable->async_info[req_num].argv[7] = (unsigned)req;
- RTable->cell_pointer = INC_T(RTable->cell_pointer);
-
- }
-
- in_request++;
- }
-}
-
-
-static void ddv_request(request_queue_t * q)
-{
- cli();
- ddv_request1();
- sti();
-}
-
-
-static void check_printbufs(void)
-{
- int i;
-
- if (!PrintBufs) return;
-
- while (PrintBufs->option_counter != PrintBufs->cell_counter) {
- i = PrintBufs->cell_counter;
- printk("opiu (%d): ",i);
- if (((unsigned)PrintBufs->bufs[i].fmt) > 0x100000)
- printk("Error: bad format in printk at %p\n",
- PrintBufs->bufs[i].fmt);
- else
- printk(PrintBufs->bufs[i].fmt + OPIBUS_BASE,
- PrintBufs->bufs[i].args[0],
- PrintBufs->bufs[i].args[1],
- PrintBufs->bufs[i].args[2],
- PrintBufs->bufs[i].args[3],
- PrintBufs->bufs[i].args[4],
- PrintBufs->bufs[i].args[5]);
- if (++PrintBufs->cell_counter == PRINT_BUFS)
- PrintBufs->cell_counter = 0;
- }
-}
-
-static void ddv_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned long flags;
- save_flags(flags); cli();
- OPT_IO(IRC1) = 0x80000000;
-
- check_printbufs();
- check_completion();
-
- ddv_request1();
- restore_flags(flags);
-}
-
-static int ddv_open(struct inode * inode, struct file * filp)
-{
- int minor = MINOR(inode->i_rdev);
-
- if (!have_ddv_board || minor >= NUM_DDVDEVS)
- return -ENODEV;
-
- if (minor >= PARDISK_BASE) {
- ddv_sect_length[minor] = ddv_sect_length[minor - PARDISK_BASE];
- ddv_blk_length[minor] = ddv_blk_length[minor - PARDISK_BASE];
- }
-
- return 0;
-}
-
-
-static void ddv_open_reply(struct cap_request *creq)
-{
- int size = creq->size - sizeof(*creq);
- ddv_opcodep = (char *)kmalloc(size,GFP_ATOMIC);
- read_bif(ddv_opcodep, size);
-#if DEBUG
- printk("received opiu kernel of size %d\n",size);
-#endif
- if (size == 0)
- have_ddv_board = 0;
- wake_up(&busy_wait);
-}
-
-extern struct block_device_operations ddv_fops;
-
-static void ddv_load_opiu(void)
-{
- int i;
- struct cap_request creq;
-
- /* if the opiu kernel is already loaded then we don't do anything */
- if (!have_ddv_board || opiu_kernel_loaded)
- return;
-
- bif_register_request(REQ_DDVOPEN,ddv_open_reply);
-
- /* send the open request to the front end */
- creq.cid = mpp_cid();
- creq.type = REQ_DDVOPEN;
- creq.header = 0;
- creq.size = sizeof(creq);
-
- bif_queue(&creq,0,0);
-
- ddv_set_optadr();
-
- while (!ddv_opcodep)
- sleep_on(&busy_wait);
-
- if (!have_ddv_board)
- return;
-
- ddv_load_kernel(ddv_opcodep);
-
- kfree(ddv_opcodep);
- ddv_opcodep = NULL;
-
- if (ddv_restart_cpu())
- return;
-
- ddv_sect_length[0] = DiskInfo->blocks;
- ddv_blk_length[0] = DiskInfo->blocks >> 1;
- ddv_blocksizes[0] = BLOCK_SIZE;
-
- ddv_geometry.cylinders = ddv_sect_length[0] /
- (ddv_geometry.heads*ddv_geometry.sectors);
-
- register_disk(&ddv_gendisk, MKDEV(MAJOR_NR,0), 1<<PARTN_BITS,
- &ddv_fops, ddv_sect_length[0]);
-
- /* FIXME. The crap below is, well, crap. Pseudo-RAID and unsafe one */
- for (i=0;i<PARDISK_BASE;i++) {
- ddv_sect_length[i] = ddv_gendisk.part[i].nr_sects;
- ddv_blk_length[i] = ddv_gendisk.part[i].nr_sects >> 1;
- }
-
- /* setup the parallel partitions by multiplying the normal
- partition by the number of options */
- for (;i<NUM_DDVDEVS;i++) {
- ddv_sect_length[i] = ddv_sect_length[i-PARDISK_BASE]*num_options;
- ddv_blk_length[i] = ddv_blk_length[i-PARDISK_BASE]*num_options;
- ddv_gendisk.part[i].start_sect = ddv_gendisk.part[i-PARDISK_BASE].start_sect;
- ddv_gendisk.part[i].nr_sects = ddv_sect_length[i];
- }
-
-
- opiu_kernel_loaded = 1;
-}
-
-
-/*
- * This routine is called to flush all partitions and partition tables
- * for a changed disk, and then re-read the new partition table.
- */
-static int ddv_revalidate(kdev_t dev, struct gendisk *gdev)
-{
- int target;
- int max_p;
- int start;
- int i;
-
- target = DEVICE_NR(dev);
-
- max_p = gdev->max_p;
- start = target << gdev->minor_shift;
-
- printk("ddv_revalidate dev=%d target=%d max_p=%d start=%d\n",
- dev,target,max_p,start);
-
- for (i=max_p - 1; i >=0 ; i--) {
- int minor = start + i;
- kdev_t devi = MKDEV(gdev->major, minor);
- sync_dev(devi);
- invalidate_inodes(devi);
- invalidate_buffers(devi);
- gdev->part[minor].start_sect = 0;
- gdev->part[minor].nr_sects = 0;
- };
-
- ddv_sect_length[start] = DiskInfo->blocks;
- ddv_blk_length[start] = DiskInfo->blocks >> 1;
-
- grok_partitions(gdev, target, 1<<PARTN_BITS, ddv_sect_length[start]);
-
- printk("sect_length[%d]=%d blk_length[%d]=%d\n",
- start,ddv_sect_length[start],
- start,ddv_blk_length[start]);
-
- for (i=0;i<max_p;i++) {
- ddv_sect_length[start+i] = gdev->part[start+i].nr_sects;
- ddv_blk_length[start+i] = gdev->part[start+i].nr_sects >> 1;
- if (gdev->part[start+i].nr_sects)
- printk("partition[%d] start=%d length=%d\n",i,
- (int)gdev->part[start+i].start_sect,
- (int)gdev->part[start+i].nr_sects);
- }
-
- return 0;
-}
-
-
-
-
-static int ddv_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- int err;
- struct ddv_geometry *loc = (struct ddv_geometry *) arg;
- int dev;
- int minor = MINOR(inode->i_rdev);
-
- if ((!inode) || !(inode->i_rdev))
- return -EINVAL;
- dev = DEVICE_NR(inode->i_rdev);
-#if DEBUG
- printk("ddv_ioctl: cmd=%x dev=%x minor=%d\n", cmd, dev, minor);
-#endif
- switch (cmd) {
- case HDIO_GETGEO:
- printk("\tHDIO_GETGEO\n");
- if (!loc) return -EINVAL;
- if (put_user(ddv_geometry.heads, (char *) &loc->heads)) return -EFAULT;
- if (put_user(ddv_geometry.sectors, (char *) &loc->sectors)) return -EFAULT;
- if (put_user(ddv_geometry.cylinders, (short *) &loc->cylinders)) return -EFAULT;
- if (put_user(ddv_geometry.start, (long *) &loc->start)) return -EFAULT;
- return 0;
-
- case HDIO_GET_MULTCOUNT :
- printk("\tHDIO_GET_MULTCOUNT\n");
- return -EINVAL;
-
- case HDIO_GET_IDENTITY :
- printk("\tHDIO_GET_IDENTITY\n");
- return -EINVAL;
-
- case HDIO_GET_NOWERR :
- printk("\tHDIO_GET_NOWERR\n");
- return -EINVAL;
-
- case HDIO_SET_NOWERR :
- printk("\tHDIO_SET_NOWERR\n");
- return -EINVAL;
-
- case BLKRRPART:
- printk("\tBLKRRPART\n");
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
- return ddv_revalidate(inode->i_rdev,&ddv_gendisk);
-
- case BLKGETSIZE: /* Return device size */
- if (put_user(ddv_sect_length[minor],(long *) arg)) return -EFAULT;
-#if DEBUG
- printk("BLKGETSIZE gave %d\n",ddv_sect_length[minor]);
-#endif
- return 0;
-
- default:
- printk("ddv_ioctl: Invalid cmd=%d(0x%x)\n", cmd, cmd);
- return -EINVAL;
- };
-}
-
-static struct block_device_operations ddv_fops = {
- open: ddv_open,
- release: ddv_release,
- ioctl: ddv_ioctl,
-};
-
-
-static void ddv_status(void)
-{
- if (!have_ddv_board) {
- printk("no ddv board\n");
- return;
- }
-
- printk("
-in_request %u req_queued %u
-MTable: start=%u end=%u
-Requests: started=%u finished=%u
-Requests: completion_pointer=%u ddv_pointer=%u cell_pointer=%u
-PrintBufs: option_counter=%u cell_counter=%u
-ddv_stats: reads=%u writes=%u blocks=%u
-ddv_stats: sectors_read=%u sectors_written=%u
-CURRENT=%p next_request=%p errors=%u
-",
- in_request,req_queued,
- RTable->start_mtable,RTable->end_mtable,
- ddv_stats.rq_started,ddv_stats.rq_finished,
- completion_pointer,RTable->ddv_pointer,RTable->cell_pointer,
- PrintBufs->option_counter,PrintBufs->cell_counter,
- ddv_stats.reads,ddv_stats.writes,ddv_stats.blocks,
- ddv_stats.sectors_read,ddv_stats.sectors_written,
- CURRENT,next_request,
- ddv_stats.errors);
-}
-
-
-int ddv_init(void)
-{
- int cid;
-
- cid = mpp_cid();
-
- if (register_blkdev(MAJOR_NR,DEVICE_NAME,&ddv_fops)) {
- printk("ap: unable to get major %d for ap block dev\n",
- MAJOR_NR);
- return -1;
- }
-
- printk("ddv_init: register dev %d\n", MAJOR_NR);
- blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
- read_ahead[MAJOR_NR] = DDV_READ_AHEAD;
-
- bif_add_debug_key('d',ddv_status,"DDV status");
- ddv_gendisk.next = gendisk_head;
- gendisk_head = &ddv_gendisk;
-
- num_options = mpp_num_cells();
- this_option = mpp_cid();
-
- kernel_thread(ddv_daemon, NULL, 0);
-
- ddv_geninit();
-
- return(0);
-}
-
-
-static void ddv_geninit(void)
-{
- int i;
- static int done = 0;
-
- if (done)
- printk("ddv_geninit already done!\n");
-
- done = 1;
-
- printk("ddv_geninit\n");
-
- /* request interrupt line 2 */
- if (request_irq(APOPT0_IRQ,ddv_interrupt,SA_INTERRUPT,"apddv",NULL)) {
- printk("Failed to install ddv interrupt handler\n");
- }
-
- for (i=0;i<NUM_DDVDEVS;i++) {
- ddv_blocksizes[i] = BLOCK_SIZE;
- ddv_sect_length[i] = 0;
- ddv_blk_length[i] = 0;
- }
-
- ddv_geometry.heads = 32;
- ddv_geometry.sectors = 32;
- ddv_geometry.cylinders = 1;
- ddv_geometry.start = 0;
-
- blksize_size[MAJOR_NR] = ddv_blocksizes;
-
- ddv_load_opiu();
-}
-
-
-/* loadable module support */
-
-#ifdef MODULE
-
-int init_module(void)
-{
- int error = ddv_init();
- if (!error)
- printk(KERN_INFO "DDV: Loaded as module.\n");
- return error;
-}
-
-/* Before freeing the module, invalidate all of the protected buffers! */
-void cleanup_module(void)
-{
- int i;
- struct gendisk ** gdp;
-
- for (i = 0 ; i < NUM_DDVDEVS; i++)
- invalidate_buffers(MKDEV(MAJOR_NR, i));
-
- /* reset the opiu */
- OPT_IO(OPIU_OP) = OPIU_RESET;
- OPT_IO(PRST) = PRST_IRST;
-
- unregister_blkdev( MAJOR_NR, DEVICE_NAME );
- for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))
- if (*gdp == &ddv_gendisk)
- break;
- if (*gdp)
- *gdp = (*gdp)->next;
- free_irq(APOPT0_IRQ, NULL);
- blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
-}
-
-#endif /* MODULE */
-
-
diff --git a/drivers/ap1000/ddv_util.c b/drivers/ap1000/ddv_util.c
deleted file mode 100644
index d6cf12216..000000000
--- a/drivers/ap1000/ddv_util.c
+++ /dev/null
@@ -1,116 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-#define __NO_VERSION__
-#include <linux/module.h>
-#include <linux/blk.h>
-#include <linux/genhd.h>
-#include <asm/pgtable.h>
-#include <asm/ap1000/apreg.h>
-#include <asm/ap1000/DdvReqTable.h>
-
-
-#define GENDISK_STRUCT ddv_gendisk
-
-struct RequestTable *RTable=NULL;
-struct OPrintBufArray *PrintBufs=NULL;
-struct OAlignBufArray *AlignBufs=NULL;
-struct DiskInfo *DiskInfo=NULL;
-
-extern int ddv_length[];
-
-int ddv_mlist_available(void)
-{
- int start = RTable->start_mtable;
- int end = RTable->end_mtable;
-
- if (start >= end)
- return (MTABLE_SIZE - start);
- return (end+1) - start;
-}
-
-
-int ddv_get_mlist(unsigned mptr[],int bnum)
-{
- int available = ddv_mlist_available();
- int i;
- int start = RTable->start_mtable;
-
- if (available < bnum) {
- return -1;
- }
-
- for (i = 0; i < bnum; i++) {
- unsigned phys = (unsigned)mmu_v2p((unsigned)mptr[i]);
- if (phys == -1)
- panic("bad address %x in ddv_get_mlist\n",mptr[i]);
- RTable->mtable[RTable->start_mtable] = phys;
- RTable->start_mtable = INC_ML(RTable->start_mtable);
- }
-
- return start;
-}
-
-
-
-void ddv_load_kernel(char *opcodep)
-{
- int tsize;
- char *p;
- struct exec *mhead;
-
- mhead = (struct exec *)opcodep;
- p = opcodep + sizeof(*mhead);
-
- tsize = (mhead->a_text + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1);
- memcpy((char *)OPIBUS_BASE+mhead->a_entry,p,mhead->a_text);
- memcpy((char *)OPIBUS_BASE+mhead->a_entry+tsize,
- p+mhead->a_text,mhead->a_data);
- memset((char *)OPIBUS_BASE+mhead->a_entry+tsize+mhead->a_data,0,
- mhead->a_bss+PAGE_SIZE);
-
-#ifdef DDV_DEBUG
- printk("CELL(%d) loaded opiu kernel of size %ld %ld %ld (%ld)\n",
- ap_getcid(),
- mhead->a_text,mhead->a_data,mhead->a_bss,mhead->a_entry);
-#endif
-}
-
-
-int ddv_restart_cpu(void)
-{
- unsigned long timeout;
-
- OPT_IO(OPIU_OP) = OPIU_RESET;
- OPT_IO(PRST) = PRST_IRST;
- if (OPT_IO(PRST) != PRST_IRST) {
- printk("_iu_load reset release error.\n");
- return(-1);
- }
- for (timeout=jiffies + 10;
- time_before(jiffies, timeout) || (OPT_IO(PBUF0) == 0);
- ) /* wait */ ;
- if (OPT_IO(PBUF0) == 0) {
- printk("WARNING: option kernel didn't startup\n");
- return(-1);
- } else {
- printk("option kernel IU running\n");
- DiskInfo = (struct DiskInfo *)(OPT_IO(PBUF0) + OPIBUS_BASE);
- RTable = (struct RequestTable *)(DiskInfo->ptrs[0]+OPIBUS_BASE);
- PrintBufs = (struct OPrintBufArray *)(DiskInfo->ptrs[1]+OPIBUS_BASE);
- AlignBufs = (struct OAlignBufArray *)(DiskInfo->ptrs[2]+OPIBUS_BASE);
-
- printk("Disk capacity: %d blocks of size %d\n",
- (int)DiskInfo->blocks,(int)DiskInfo->blk_size);
-
- OPT_IO(PBUF0) = 0;
- }
- return(0);
-}
-
-
-
diff --git a/drivers/ap1000/mac.c b/drivers/ap1000/mac.c
deleted file mode 100644
index 8e85ff555..000000000
--- a/drivers/ap1000/mac.c
+++ /dev/null
@@ -1,1177 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * Routines for controlling the FORMAC+
- */
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include <linux/skbuff.h>
-#include <linux/interrupt.h>
-#include <linux/if_ether.h> /* For the statistics structure. */
-#include <linux/netdevice.h>
-#include <linux/if_arp.h>
-#include <linux/inet.h>
-#include <net/sock.h>
-
-#include <asm/ap1000/apreg.h>
-#include <asm/ap1000/apservice.h>
-#include <asm/pgtable.h>
-
-#include "apfddi.h"
-#include "smt-types.h"
-#include "am79c830.h"
-#include "mac.h"
-#include "plc.h"
-#include "apfddi-reg.h"
-
-#define MAC_DEBUG 0
-
-/* Values for dma_state */
-#define IDLE 0
-#define XMITTING 1
-#define RECVING 2
-
-/*
- * Messages greater than this value are transferred to the FDDI send buffer
- * using DMA.
- */
-#define DMA_XMIT_THRESHOLD 64
-#define DMA_RECV_THRESHOLD 64
-
-/*
- * If the FDDI receive buffer is occupied by less than this value, then
- * sending has priority.
- */
-#define RECV_THRESHOLD (20*1024)
-
-#define DMA_RESET_MASKS ((AP_CLR_INTR_MASK<<DMA_INTR_NORMAL_SH) | \
- (AP_CLR_INTR_MASK<<DMA_INTR_ERROR_SH))
-
-#define DMA_INTR_REQS ((AP_INTR_REQ<<DMA_INTR_NORMAL_SH) | \
- (AP_INTR_REQ<<DMA_INTR_ERROR_SH))
-
-static void mac_print_state(void);
-
-typedef unsigned int mac_status_t;
-
-static volatile struct mac_queue *mac_queue_top = NULL;
-static volatile struct mac_queue *mac_queue_bottom = NULL;
-
-struct formac_state {
- LoopbackType loopback;
- int ring_op;
- int recv_ptr;
- int recv_empty;
- int recv_ovf;
- int xmit_ptr;
- int xmit_free;
- int xmit_start;
- int xmit_chains;
- int xmit_more_ptr;
- int frames_xmitted;
- int xmit_chain_start[3];
- int frames_recvd;
- int recv_aborted;
- int xmit_aborted;
- int wrong_bb;
- int recv_error;
- volatile struct mac_queue *cur_macq; /* Current queue el for send DMA */
- volatile struct mac_buf cur_mbuf; /* Current mac_buf for send DMA */
- struct sk_buff *cur_skb; /* skb for received packets by DMA */
- int dma_state;
-};
-
-#define SPFRAMES_SIZE 64 /* # words for special frames area */
-#define RECV_BUF_START SPFRAMES_SIZE
-#define RECV_BUF_END (BUFFER_SIZE / 2 + 2048)
-#define RECV_BUF_SIZE (RECV_BUF_END - RECV_BUF_START)
-#define XMIT_BUF_START RECV_BUF_END
-#define XMIT_BUF_END BUFFER_SIZE
-
-#define S2_RMT_EVENTS (S2_CLAIM_STATE | S2_MY_CLAIM | S2_HIGHER_CLAIM | \
- S2_LOWER_CLAIM | S2_BEACON_STATE | S2_MY_BEACON | \
- S2_OTHER_BEACON | S2_RING_OP | S2_MULTIPLE_DA | \
- S2_TOKEN_ERR | S2_DUPL_CLAIM | S2_TRT_EXP_RECOV)
-
-struct mac_info *this_mac_info;
-struct formac_state this_mac_state;
-
-int
-mac_init(struct mac_info *mip)
-{
- struct formac_state *msp = &this_mac_state;
-
- bif_add_debug_key('f',mac_print_state,"show FDDI mac state");
-
- this_mac_info = mip;
-
- mac->cmdreg1 = C1_SOFTWARE_RESET;
- mac->said = (mip->s_address[0] << 8) + mip->s_address[1];
- mac->laim = (mip->l_address[0] << 8) + mip->l_address[1];
- mac->laic = (mip->l_address[2] << 8) + mip->l_address[3];
- mac->lail = (mip->l_address[4] << 8) + mip->l_address[5];
- mac->sagp = (mip->s_group_adrs[0] << 8) + mip->s_group_adrs[1];
- mac->lagm = (mip->l_group_adrs[0] << 8) + mip->l_group_adrs[1];
- mac->lagc = (mip->l_group_adrs[2] << 8) + mip->l_group_adrs[3];
- mac->lagl = (mip->l_group_adrs[4] << 8) + mip->l_group_adrs[5];
- mac->tmax = mip->tmax >> 5;
- mac->tvx = (mip->tvx - 254) / 255; /* it's -ve, round downwards */
- mac->treq0 = mip->treq;
- mac->treq1 = mip->treq >> 16;
- mac->pri0 = ~0;
- mac->pri1 = ~0;
- mac->pri2 = ~0;
- mac->mdreg2 = /*M2_STRIP_FCS +*/ M2_CHECK_PARITY + M2_EVEN_PARITY
- + 3 * M2_RCV_BYTE_BDRY + M2_ENABLE_HSREQ
- + M2_ENABLE_NPDMA + M2_SYNC_NPDMA + M2_RECV_BAD_FRAMES;
- mac->eacb = RECV_BUF_START - 1;
- mac->earv = XMIT_BUF_START - 1;
- mac->eas = mac->earv;
- mac->eaa0 = BUFFER_SIZE - 1;
- mac->eaa1 = mac->eaa0;
- mac->eaa2 = mac->eaa1;
- mac->wpxsf = 0;
- mac->rpr = RECV_BUF_START;
- mac->wpr = RECV_BUF_START + 1;
- mac->swpr = RECV_BUF_START;
- mac->wpxs = mac->eas;
- mac->swpxs = mac->eas;
- mac->rpxs = mac->eas;
- mac->wpxa0 = XMIT_BUF_START;
- mac->rpxa0 = XMIT_BUF_START;
-
- memset(msp, 0, sizeof(*msp));
- msp->recv_ptr = RECV_BUF_START;
- msp->recv_empty = 1;
- msp->xmit_ptr = XMIT_BUF_START;
- msp->xmit_free = XMIT_BUF_START + 1;
- msp->xmit_start = XMIT_BUF_START;
- msp->xmit_chains = 0;
- msp->frames_xmitted = 0;
- msp->frames_recvd = 0;
- msp->recv_aborted = 0;
-
- mac->mdreg1 = M1_MODE_MEMORY;
-
- mac_make_spframes();
-
- return 0;
-}
-
-int
-mac_inited(struct mac_info *mip)
-{
- struct formac_state *msp = &this_mac_state;
- mac_status_t st1, st2;
-
- if (mac->said != (mip->s_address[0] << 8) + mip->s_address[1]
- || mac->laim != (mip->l_address[0] << 8) + mip->l_address[1]
- || mac->laic != (mip->l_address[2] << 8) + mip->l_address[3]
- || mac->lail != (mip->l_address[4] << 8) + mip->l_address[5]
- || mac->sagp != (mip->s_group_adrs[0] << 8) + mip->s_group_adrs[1]
- || mac->lagm != (mip->l_group_adrs[0] << 8) + mip->l_group_adrs[1]
- || mac->lagc != (mip->l_group_adrs[2] << 8) + mip->l_group_adrs[3]
- || mac->lagl != (mip->l_group_adrs[4] << 8) + mip->l_group_adrs[5])
- return 1;
- if ((mac->mdreg1 & ~M1_ADDET) != (M1_MODE_ONLINE | M1_SELECT_RA
- | M1_FULL_DUPLEX))
- return 3;
- if (mac->treq0 != (mip->treq & 0xffff)
- || mac->treq1 != ((unsigned)mip->treq >> 16))
- return 4;
-
- st1 = (mac->st1u << 16) + mac->st1l;
- st2 = (mac->st2u << 16) + mac->st2l;
- if ((st2 & S2_RING_OP) == 0)
- return 5;
-
- /* It's probably OK, reset some things to be safe. */
- this_mac_info = mip;
- *csr0 &= ~CS0_HREQ;
- mac->tmax = mip->tmax >> 5;
- mac->tvx = (mip->tvx - 254) / 255; /* it's -ve, round downwards */
- mac->pri0 = ~0;
- mac->pri1 = ~0;
- mac->pri2 = ~0;
- mac->mdreg2 = /*M2_STRIP_FCS +*/ M2_CHECK_PARITY + M2_EVEN_PARITY
- + 3 * M2_RCV_BYTE_BDRY + M2_ENABLE_HSREQ
- + M2_ENABLE_NPDMA + M2_SYNC_NPDMA + M2_RECV_BAD_FRAMES;
-
- /* clear out the receive queue */
- mac->mdreg1 = (mac->mdreg1 & ~M1_ADDET) | M1_ADDET_DISABLE_RECV;
- mac->rpr = RECV_BUF_START;
- mac->wpr = RECV_BUF_START + 1;
- mac->swpr = RECV_BUF_START;
-
- memset(msp, 0, sizeof(*msp));
- msp->recv_ptr = RECV_BUF_START;
- msp->recv_empty = 1;
-
- /* XXX reset transmit pointers */
- mac->cmdreg2 = C2_ABORT_XMIT;
- mac->cmdreg2 = C2_RESET_XMITQS;
- mac->wpxa0 = XMIT_BUF_START;
- mac->rpxa0 = XMIT_BUF_START;
- msp->xmit_ptr = XMIT_BUF_START;
- msp->xmit_free = XMIT_BUF_START + 1;
- msp->xmit_start = XMIT_BUF_START;
- msp->xmit_chains = 0;
-
- mac_make_spframes();
- mac->cmdreg1 = C1_CLR_ALL_LOCKS;
-
- msp->frames_xmitted = 0;
- msp->frames_recvd = 0;
- msp->recv_aborted = 0;
- msp->ring_op = 1;
-
- mac->mdreg1 = (mac->mdreg1 & ~M1_ADDET) | M1_ADDET_NSA;
- mac->imsk1u = ~(S1_XMIT_ABORT | S1_END_FRAME_ASYNC0) >> 16;
- mac->imsk1l = ~(S1_PAR_ERROR_ASYNC0 | S1_QUEUE_LOCK_ASYNC0);
- mac->imsk2u = ~(S2_RECV_COMPLETE | S2_RECV_BUF_FULL | S2_RECV_FIFO_OVF
- | S2_ERR_SPECIAL_FR | S2_RMT_EVENTS
- | S2_NP_SIMULT_LOAD) >> 16;
- mac->imsk2l = ~(S2_RMT_EVENTS | S2_MISSED_FRAME);
-
- return 0;
-}
-
-void mac_make_spframes(void)
-{
- volatile int *bp;
- struct mac_info *mip = this_mac_info;
- int sa;
- struct formac_state *msp = &this_mac_state;
-
- /* initialize memory to avoid parity errors */
- *csr0 &= ~CS0_HREQ;
- *csr1 &= ~CS1_BUF_WR_TAG;
- for (bp = &buffer_mem[BUFFER_SIZE]; bp > &buffer_mem[XMIT_BUF_START];)
- *--bp = 0xdeadbeef;
- for (; bp > buffer_mem;)
- *--bp = 0xfeedf00d;
- buffer_mem[msp->recv_ptr] = 0;
-
- bp = buffer_mem;
- *bp++ = 0; /* auto-void frame pointer (not used) */
-
- /* make claim frame */
- sa = bp - buffer_mem;
- *bp++ = 0xd8000011; /* claim frame descr. + length */
- *bp++ = 0xc3; /* FC value for claim frame, long addr */
- *bp++ = (mip->l_address[0] << 24) + (mip->l_address[1] << 16)
- + (mip->l_address[2] << 8) + mip->l_address[3];
- *bp++ = (mip->l_address[4] << 24) + (mip->l_address[5] << 16)
- + (mip->l_address[0] << 8) + mip->l_address[1];
- *bp++ = (mip->l_address[2] << 24) + (mip->l_address[3] << 16)
- + (mip->l_address[4] << 8) + mip->l_address[5];
- *bp++ = mip->treq;
- mac->sacl = bp - buffer_mem; /* points to pointer to claim frame */
- *bp++ = 0xa0000000 + sa; /* pointer to start of claim frame */
-
- /* make beacon frame */
- sa = bp - buffer_mem;
- *bp++ = 0xd8000011; /* beacon frame descr. + length */
- *bp++ = 0xc2; /* FC value for beacon frame, long addr */
- *bp++ = 0; /* DA = 0 */
- *bp++ = (mip->l_address[0] << 8) + mip->l_address[1];
- *bp++ = (mip->l_address[2] << 24) + (mip->l_address[3] << 16)
- + (mip->l_address[4] << 8) + mip->l_address[5];
- *bp++ = 0; /* beacon reason = failed claim */
- mac->sabc = bp - buffer_mem;
- *bp++ = 0xa0000000 + sa; /* pointer to start of beacon frame */
-}
-
-void mac_reset(LoopbackType loopback)
-{
- int mode;
- struct formac_state *msp = &this_mac_state;
-
- msp->loopback = loopback;
- switch (loopback) {
- case loop_none:
- mode = M1_MODE_ONLINE;
- break;
- case loop_formac:
- mode = M1_MODE_INT_LOOP;
- break;
- default:
- mode = M1_MODE_EXT_LOOP;
- break;
- }
- mac->mdreg1 = mode | M1_ADDET_NSA | M1_SELECT_RA | M1_FULL_DUPLEX;
- mac->cmdreg1 = C1_IDLE_LISTEN;
- mac->cmdreg1 = C1_CLR_ALL_LOCKS;
- mac->imsk1u = ~(S1_XMIT_ABORT | S1_END_FRAME_ASYNC0) >> 16;
- mac->imsk1l = ~(S1_PAR_ERROR_ASYNC0 | S1_QUEUE_LOCK_ASYNC0);
- mac->imsk2u = ~(S2_RECV_COMPLETE | S2_RECV_BUF_FULL | S2_RECV_FIFO_OVF
- | S2_ERR_SPECIAL_FR | S2_RMT_EVENTS
- | S2_NP_SIMULT_LOAD) >> 16;
- mac->imsk2l = ~(S2_RMT_EVENTS | S2_MISSED_FRAME);
-}
-
-void mac_claim(void)
-{
- mac->cmdreg1 = C1_CLAIM_LISTEN;
-}
-
-void mac_disable(void)
-{
- mac->mdreg1 = M1_MODE_MEMORY;
- mac->imsk1u = ~0;
- mac->imsk1l = ~0;
- mac->imsk2u = ~0;
- mac->imsk2l = ~0;
- mac->wpr = mac->swpr + 1;
- if (mac->wpr > mac->earv)
- mac->wpr = mac->eacb + 1;
- buffer_mem[mac->swpr] = 0;
-}
-
-void mac_stats(void)
-{
- struct formac_state *msp = &this_mac_state;
-
- if (msp->recv_ovf)
- printk("%d receive buffer overflows\n", msp->recv_ovf);
- if (msp->wrong_bb)
- printk("%d frames on wrong byte bdry\n", msp->wrong_bb);
- printk("%d frames transmitted, %d aborted\n", msp->frames_xmitted,
- msp->xmit_aborted);
- printk("%d frames received, %d aborted\n", msp->frames_recvd,
- msp->recv_aborted);
- printk("%d frames received with errors\n", msp->recv_error);
-}
-
-void mac_sleep(void)
-{
- /* disable the receiver */
- mac->mdreg1 = (mac->mdreg1 & ~M1_ADDET) | M1_ADDET_DISABLE_RECV;
-}
-
-void mac_poll(void)
-{
- mac_status_t st1, st2;
- struct formac_state *msp = &this_mac_state;
- int up, f, d, l, r, e, i;
-
- st1 = (mac->st1u << 16) + mac->st1l;
- st2 = (mac->st2u << 16) + mac->st2l;
-
- if (st2 & S2_NP_SIMULT_LOAD)
- panic("NP/formac simultaneous load!!!");
-
- up = (st2 & S2_RING_OP) != 0;
- if (up != msp->ring_op) {
- /* ring has come up or down */
- msp->ring_op = up;
- printk("mac: ring %s\n", up? "up": "down");
- set_ring_op(up);
- }
-
- if (up) {
- if (st1 & S1_XMIT_ABORT) {
- ++msp->xmit_aborted;
- if (st1 & S1_QUEUE_LOCK_ASYNC0) {
- printk("mac: xmit queue locked, resetting xmit buffer\n");
- mac->cmdreg2 = C2_RESET_XMITQS; /* XXX bit gross */
- mac->rpxa0 = XMIT_BUF_START;
- buffer_mem[XMIT_BUF_START] = 0;
- msp->xmit_ptr = XMIT_BUF_START;
- msp->xmit_start = XMIT_BUF_START;
- msp->xmit_chains = 0;
- mac->cmdreg1 = C1_CLR_ASYNCQ0_LOCK;
- st1 &= ~(S1_END_CHAIN_ASYNC0 | S1_END_FRAME_ASYNC0
- | S1_XINSTR_FULL_ASYNC0);
- } else
- st1 |= S1_END_FRAME_ASYNC0;
- } else if (st1 & S1_QUEUE_LOCK_ASYNC0) {
- printk("mac: xmit queue locked, why?\n");
- mac->cmdreg1 = C1_CLR_ASYNCQ0_LOCK;
- }
-
- if (st1 & S1_END_FRAME_ASYNC0) {
- /* advance xmit_start */
- e = msp->xmit_start;
- while (e != msp->xmit_ptr) {
- /* find the end of the current frame */
- f = buffer_mem[e]; /* read pointer */
- if (f == 0)
- break; /* huh?? */
- f &= 0xffff;
- d = buffer_mem[f]; /* read descriptor */
- l = ((d & 0xffff) + ((d >> TD_BYTE_BDRY_LG) & 3) + 3) >> 2;
- e = f + 1 + l; /* index of ptr at end of frame */
- r = mac->rpxa0;
- if ((r <= msp->xmit_ptr && r < e && e <= msp->xmit_ptr)
- || (r > msp->xmit_ptr && (r < e || e <= msp->xmit_ptr)))
- break; /* up to current frame */
- /* printk("frame @ %x done\n", msp->xmit_start); */
- msp->xmit_start = e;
- if ((st1 & S1_XMIT_ABORT) == 0)
- ++msp->frames_xmitted;
- if ((msp->xmit_chains == 1 && e == msp->xmit_ptr) ||
- (msp->xmit_chains > 1 && e == msp->xmit_chain_start[1])) {
- /* we've finished chain 0 */
- --msp->xmit_chains;
- for (i = 0; i < msp->xmit_chains; ++i)
- msp->xmit_chain_start[i] = msp->xmit_chain_start[i+1];
- if (msp->xmit_chains >= 2) {
- mac->cmdreg2 = C2_XMIT_ASYNCQ0;
- /* printk("mac_poll: xmit chain\n"); */
- }
- if (msp->xmit_chains == 0)
- *csr0 &= ~CS0_LED1;
- }
- }
- /*
- * Now that we have a bit more space in the transmit buffer,
- * see if we want to put another frame in.
- */
-#if MAC_DEBUG
- printk("Removed space in transmit buffer.\n");
-#endif
- mac_process();
- }
- }
-
- if (st2 & S2_RMT_EVENTS) {
- rmt_event(st2);
- }
-
- if (st2 & S2_RECV_COMPLETE) {
- /*
- * A frame has just finished arriving in the receive buffer.
- */
- *csr0 |= CS0_LED2;
- msp->recv_empty = 0;
-#if MAC_DEBUG
- printk("Frame has just trickled in...\n");
-#endif
- mac_process();
- }
-
- if (st2 & S2_RECV_BUF_FULL) {
- /*
- * receive buffer overflow: reset and unlock the receive buffer.
- */
-/* printk("mac: receive buffer full\n"); */
- mac->rpr = RECV_BUF_START;
- mac->wpr = RECV_BUF_START + 1;
- mac->swpr = RECV_BUF_START;
- msp->recv_ptr = RECV_BUF_START;
- msp->recv_empty = 1;
- buffer_mem[RECV_BUF_START] = 0;
- mac->cmdreg1 = C1_CLR_RECVQ_LOCK;
- ++msp->recv_ovf;
-
-#if 0
- } else if (st2 & S2_RECV_FIFO_OVF) {
- printk("mac: receive FIFO overflow\n");
- /* any further action required here? */
-
- } else if (st2 & S2_MISSED_FRAME) {
- printk("mac: missed frame\n");
-#endif
- }
-
- if (st2 & S2_ERR_SPECIAL_FR) {
- printk("mac: bug: error in special frame\n");
- mac_disable();
- }
-}
-
-void
-mac_xmit_alloc(sp, bb)
- struct mac_buf *sp;
- int bb;
-{
- int nwords;
-
- nwords = (sp->length + bb + 3) >> 2;
- sp->fr_start = mac_xalloc(nwords + 2);
- sp->fr_end = sp->fr_start + nwords + 1;
- sp->ptr = (char *) &buffer_mem[sp->fr_start + 1] + bb;
- buffer_mem[sp->fr_start] = TD_MAGIC + (bb << TD_BYTE_BDRY_LG) + sp->length;
-}
-
-void
-mac_queue_frame(sp)
- struct mac_buf *sp;
-{
- struct formac_state *msp = &this_mac_state;
-
- buffer_mem[sp->fr_end] = 0; /* null pointer at end of frame */
- buffer_mem[msp->xmit_ptr] = PT_MAGIC + sp->fr_start;
- if (msp->xmit_chains <= 2) {
- msp->xmit_chain_start[msp->xmit_chains] = msp->xmit_ptr;
- if (msp->xmit_chains < 2)
- mac->cmdreg2 = C2_XMIT_ASYNCQ0;
- ++msp->xmit_chains;
- } else {
- buffer_mem[msp->xmit_more_ptr] |= TD_MORE;
- }
- msp->xmit_ptr = sp->fr_end;
- msp->xmit_more_ptr = sp->fr_start;
- *csr0 |= CS0_LED1;
-}
-
-int
-mac_xalloc(int nwords)
-{
- int fr_start;
- struct formac_state *msp = &this_mac_state;
-
- /*
- * Find some room in the transmit buffer.
- */
- fr_start = msp->xmit_free;
- if (fr_start > msp->xmit_start) {
- if (fr_start + nwords > XMIT_BUF_END) {
- /* no space at end - see if we can start again from the front */
- fr_start = XMIT_BUF_START;
- if (fr_start + nwords > msp->xmit_start)
- panic("no space in xmit buffer (1)");
- }
- } else {
- if (fr_start + nwords > msp->xmit_start)
- panic("no space in xmit buffer (2)");
- }
-
- msp->xmit_free = fr_start + nwords;
-
- return fr_start;
-}
-
-int
-mac_recv_frame(sp)
- struct mac_buf *sp;
-{
- struct formac_state *msp = &this_mac_state;
- int status, bb, orig_recv_ptr;
-
- orig_recv_ptr = msp->recv_ptr;
- for (;;) {
- status = buffer_mem[msp->recv_ptr];
- if ((status & RS_VALID) == 0) {
- if (status != 0) {
- printk("recv buf out of sync: recv_ptr=%x status=%x\n",
- msp->recv_ptr, status);
- printk(" rpr=%x swpr=%x, buf[rpr]=%x\n", mac->rpr, mac->swpr,
- buffer_mem[mac->rpr]);
- msp->recv_ptr = mac->swpr;
- }
- *csr0 &= ~CS0_LED2;
- msp->recv_empty = 1;
- if (mac->rpr == orig_recv_ptr)
- mac->rpr = msp->recv_ptr;
- return 0;
- }
- if (status & RS_ABORTED)
- ++msp->recv_aborted;
- else {
- bb = (status >> RS_BYTE_BDRY_LG) & 3;
- if (bb != 3) {
- ++msp->wrong_bb;
- bb = 3;
- }
- if ((status & RS_ERROR) == 0)
- break;
- ++msp->recv_error;
- msp->recv_ptr += NWORDS((status & RS_LENGTH) + bb);
- }
- if (++msp->recv_ptr >= RECV_BUF_END)
- msp->recv_ptr -= RECV_BUF_SIZE;
- }
- ++msp->frames_recvd;
- if (mac->rpr == orig_recv_ptr)
- mac->rpr = msp->recv_ptr;
-
- sp->fr_start = msp->recv_ptr;
- sp->length = (status & RS_LENGTH) + bb; /* + 4 (status) - 4 (FCS) */
- sp->ptr = (void *) &buffer_mem[sp->fr_start];
- if ((msp->recv_ptr += NWORDS(sp->length) + 1) >= RECV_BUF_END)
- msp->recv_ptr -= RECV_BUF_SIZE;
- sp->fr_end = msp->recv_ptr;
- sp->wraplen = (RECV_BUF_END - sp->fr_start) * 4;
- sp->wrapptr = (void *) &buffer_mem[RECV_BUF_START];
-
- return 1;
-}
-
-void
-mac_discard_frame(sp)
- struct mac_buf *sp;
-{
- mac->rpr = sp->fr_end;
-}
-
-/*
- * Return the number of bytes free in the async 0 transmit queue.
- */
-int
-mac_xmit_space(void)
-{
- struct formac_state *msp = &this_mac_state;
- int nw;
-
- if (msp->xmit_free > msp->xmit_start) {
- nw = XMIT_BUF_END - msp->xmit_free;
- if (nw < msp->xmit_start - XMIT_BUF_START)
- nw = msp->xmit_start - XMIT_BUF_START;
- } else
- nw = msp->xmit_start - msp->xmit_free;
- return nw <= 2? 0: (nw - 2) << 2;
-}
-
-/*
- * Return the number of bytes of frames available in the receive queue.
- */
-int
-mac_recv_level(void)
-{
- int nw;
-
- nw = mac->swpr - mac->rpr;
- if (nw < 0)
- nw += mac->earv - mac->eacb;
- return nw << 2;
-}
-
-/*
- * Return 1 iff all transmission has been completed, 0 otherwise.
- */
-int mac_xmit_done(void)
-{
- struct formac_state *msp = &this_mac_state;
-
- return msp->xmit_chains == 0;
-}
-
-/*
- * Append skbuff packet to queue.
- */
-int mac_queue_append (struct sk_buff *skb)
-{
- struct mac_queue *el;
- unsigned flags;
- save_flags(flags); cli();
-
-#if MAC_DEBUG
- printk("Appending queue element skb 0x%x\n", skb);
-#endif
-
- if ((el = (struct mac_queue *)kmalloc(sizeof(*el), GFP_ATOMIC)) == NULL) {
- restore_flags(flags);
- return 1;
- }
- el->next = NULL;
- el->skb = skb;
-
- if (mac_queue_top == NULL) {
- mac_queue_top = mac_queue_bottom = el;
- }
- else {
- mac_queue_bottom->next = el;
- mac_queue_bottom = el;
- }
- restore_flags(flags);
- return 0;
-}
-
-/*
- * If the packet originated from the same FDDI subnet as we are on,
- * there is no need to perform checksumming as FDDI will does this
- * us.
- */
-#define CHECK_IF_CHECKSUM_REQUIRED(skb) \
- if ((skb)->protocol == ETH_P_IP) { \
- extern struct cap_init cap_init; \
- int *from_ip = (int *)((skb)->data+12); \
- int *to_ip = (int *)((skb)->data+16); \
- if ((*from_ip & cap_init.netmask) == (*to_ip & cap_init.netmask)) \
- (skb)->ip_summed = CHECKSUM_UNNECESSARY; \
- }
-
-/*
- * Try to send and/or recv frames.
- */
-void mac_process(void)
-{
- volatile struct dma_chan *dma = (volatile struct dma_chan *) DMA3;
- struct formac_state *msp = &this_mac_state;
- struct mac_queue *el;
- int nw=0, mrl = 0, fstart, send_buffer_full = 0;
- unsigned flags;
-
- save_flags(flags); cli();
-
-#if MAC_DEBUG
- printk("In mac_process()\n");
-#endif
-
- /*
- * Check if the DMA is being used.
- */
- if (msp->dma_state != IDLE) {
- restore_flags(flags);
- return;
- }
-
- while (mac_queue_top != NULL || /* Something to transmit */
- (mrl = mac_recv_level()) > 0) { /* Frames in receive buffer */
- send_buffer_full = 0;
-#if MAC_DEBUG
- printk("mac_process(): something to do... mqt %x mrl is %d\n",
- mac_queue_top, mrl);
-#endif
- if (mac_queue_top != NULL && mrl < RECV_THRESHOLD) {
- el = (struct mac_queue *)mac_queue_top;
-
- /*
- * Check there is enough space in the FDDI send buffer.
- */
- if (mac_xmit_space() < el->skb->len) {
-#if MAC_DEBUG
- printk("process_queue(): FDDI send buffer is full\n");
-#endif
- send_buffer_full = 1;
- }
- else {
-#if MAC_DEBUG
- printk("mac_process(): sending a frame\n");
-#endif
- /*
- * Update mac_queue_top.
- */
- mac_queue_top = mac_queue_top->next;
-
- /*
- * Allocate space in the FDDI send buffer.
- */
- msp->cur_mbuf.length = el->skb->len-3;
- mac_xmit_alloc((struct mac_buf *)&msp->cur_mbuf, 3);
-
- /*
- * If message size is greater than DMA_XMIT_THRESHOLD, send
- * using DMA, otherwise use memcpy().
- */
- if (el->skb->len > DMA_XMIT_THRESHOLD) {
- /*
- * Start the DMA.
- */
-#if MAC_DEBUG
- printk("mac_process(): Starting send DMA...\n");
-#endif
- nw = msp->cur_mbuf.fr_end - msp->cur_mbuf.fr_start + 1;
- mac->wpxa0 = msp->cur_mbuf.fr_start + 1;
-
- *csr0 |= CS0_HREQ_WA0;
-
- msp->cur_macq = el;
- msp->dma_state = XMITTING;
- dma->st = DMA_DMST_RST;
- dma->st = DMA_RESET_MASKS;
- dma->hskip = 1; /* skip = 0, count = 1 */
- dma->vskip = 1; /* skip = 0, count = 1 */
- dma->maddr = (u_char *)
- mmu_v2p((unsigned long)el->skb->data);
- dma->cmd = DMA_DCMD_ST + DMA_DCMD_TYP_AUTO +
- DMA_DCMD_TD_MD + nw;
- *csr0 &= ~CS0_DMA_RECV;
- *csr0 |= CS0_DMA_ENABLE;
-
- /*
- * Don't process any more packets since the DMA is
- * being used.
- */
- break;
- }
- else { /* el->skb->len <= DMA_XMIT_THRESHOLD */
- /*
- * Copy the data directly into the FDDI buffer.
- */
-#if MAC_DEBUG
- printk("mac_proces(): Copying send data...\n");
-#endif
- memcpy(msp->cur_mbuf.ptr - 3, el->skb->data,
- ROUND4(el->skb->len));
- mac_queue_frame((struct mac_buf *)&msp->cur_mbuf);
- dev_kfree_skb(el->skb);
- kfree_s(el, sizeof(*el));
- continue;
- }
- }
-
- /*
- * We have reached here if there is not enough space in the
- * send buffer. Try to receive some packets instead.
- */
- }
-
- if (mac_recv_frame((struct mac_buf *)&msp->cur_mbuf)) {
- volatile int fc, llc_header_word2;
- int pkt_len = 0;
-
-#if MAC_DEBUG
- printk("mac_process(): Receiving frames...\n");
-#endif
- /*
- * Get the fc, note only word accesses are allowed from the
- * FDDI buffers.
- */
- if (msp->cur_mbuf.wraplen > 4) {
- fc = *(int *)(msp->cur_mbuf.ptr+4);
- }
- else {
- /*
- * fc_word must be at the start of the FDDI buffer.
- */
-#if MAC_DEBUG
- printk("Grabbed fc_word from wrapptr, wraplen %d\n",
- msp->cur_mbuf.wraplen);
-#endif
- fc = *(int *)msp->cur_mbuf.wrapptr;
- }
- fc &= 0xff;
-
-#if MAC_DEBUG
- printk("fc is 0x%x\n", fc);
-#endif
- if (fc < 0x50 || fc > 0x57) {
- mac_discard_frame((struct mac_buf *)&msp->cur_mbuf);
- continue;
- }
-
- /*
- * Determine the size of the packet data and allocate a socket
- * buffer.
- */
- pkt_len = msp->cur_mbuf.length - FDDI_HARDHDR_LEN;
-#if MAC_DEBUG
- printk("Packet of length %d\n", pkt_len);
-#endif
- msp->cur_skb = dev_alloc_skb(ROUND4(pkt_len));
-
- if (msp->cur_skb == NULL) {
- printk("mac_process(): Memory squeeze, dropping packet.\n");
- apfddi_stats->rx_dropped++;
- restore_flags(flags);
- return;
- }
- msp->cur_skb->dev = apfddi_device;
-
- /*
- * Hardware header isn't copied to skbuff.
- */
- msp->cur_skb->mac.raw = msp->cur_skb->data;
- apfddi_stats->rx_packets++;
-
- /*
- * Determine protocol from llc header.
- */
- if (msp->cur_mbuf.wraplen < FDDI_HARDHDR_LEN) {
- llc_header_word2 = *(int *)(msp->cur_mbuf.wrapptr +
- (FDDI_HARDHDR_LEN -
- msp->cur_mbuf.wraplen - 4));
- }
- else {
- llc_header_word2 = *(int *)(msp->cur_mbuf.ptr +
- FDDI_HARDHDR_LEN - 4);
- }
- msp->cur_skb->protocol = llc_header_word2 & 0xFFFF;
-#if MAC_DEBUG
- printk("Got protocol 0x%x\n", msp->cur_skb->protocol);
-#endif
-
- /*
- * Copy data into socket buffer, which may be wrapped around the
- * FDDI buffer. Use memcpy if the size of the data is less
- * than DMA_RECV_THRESHOLD. Note if DMA is used, then wrap-
- * arounds are handled automatically.
- */
- if (pkt_len < DMA_RECV_THRESHOLD) {
- if (msp->cur_mbuf.length < msp->cur_mbuf.wraplen) {
- memcpy(skb_put(msp->cur_skb, ROUND4(pkt_len)),
- msp->cur_mbuf.ptr + FDDI_HARDHDR_LEN,
- ROUND4(pkt_len));
- }
- else if (msp->cur_mbuf.wraplen < FDDI_HARDHDR_LEN) {
-#if MAC_DEBUG
- printk("Wrap case 2\n");
-#endif
- memcpy(skb_put(msp->cur_skb, ROUND4(pkt_len)),
- msp->cur_mbuf.wrapptr +
- (FDDI_HARDHDR_LEN - msp->cur_mbuf.wraplen),
- ROUND4(pkt_len));
- }
- else {
-#if MAC_DEBUG
- printk("wrap case 3\n");
-#endif
- memcpy(skb_put(msp->cur_skb,
- ROUND4(msp->cur_mbuf.wraplen-
- FDDI_HARDHDR_LEN)),
- msp->cur_mbuf.ptr + FDDI_HARDHDR_LEN,
- ROUND4(msp->cur_mbuf.wraplen - FDDI_HARDHDR_LEN));
- memcpy(skb_put(msp->cur_skb,
- ROUND4(msp->cur_mbuf.length -
- msp->cur_mbuf.wraplen)),
- msp->cur_mbuf.wrapptr,
- ROUND4(msp->cur_mbuf.length -
- msp->cur_mbuf.wraplen));
- }
-
-#if MAC_DEBUG
- if (msp->cur_skb->protocol == ETH_P_IP) {
- dump_packet("apfddi_rx:", msp->cur_skb->data, pkt_len, 0);
- }
- else if (msp->cur_skb->protocol == ETH_P_ARP) {
- struct arphdr *arp = (struct arphdr *)msp->cur_skb->data;
- printk("arp->ar_op is 0x%x ar_hrd %d ar_pro 0x%x ar_hln %d ar_ln %d\n",
- arp->ar_op, arp->ar_hrd, arp->ar_pro, arp->ar_hln,
- arp->ar_pln);
- printk("sender hardware address: %x:%x:%x:%x:%x:%x\n",
- *((u_char *)msp->cur_skb->data+8),
- *((u_char *)msp->cur_skb->data+9),
- *((u_char *)msp->cur_skb->data+10),
- *((u_char *)msp->cur_skb->data+11),
- *((u_char *)msp->cur_skb->data+12),
- *((u_char *)msp->cur_skb->data+13));
- printk("sender IP number %d.%d.%d.%d\n",
- *((u_char *)msp->cur_skb->data+14),
- *((u_char *)msp->cur_skb->data+15),
- *((u_char *)msp->cur_skb->data+16),
- *((u_char *)msp->cur_skb->data+17));
- printk("receiver hardware address: %x:%x:%x:%x:%x:%x\n",
- *((u_char *)msp->cur_skb->data+18),
- *((u_char *)msp->cur_skb->data+19),
- *((u_char *)msp->cur_skb->data+20),
- *((u_char *)msp->cur_skb->data+21),
- *((u_char *)msp->cur_skb->data+22),
- *((u_char *)msp->cur_skb->data+23));
- printk("receiver IP number %d.%d.%d.%d\n",
- *((u_char *)msp->cur_skb->data+24),
- *((u_char *)msp->cur_skb->data+25),
- *((u_char *)msp->cur_skb->data+26),
- *((u_char *)msp->cur_skb->data+27));
- }
-#endif
- CHECK_IF_CHECKSUM_REQUIRED(msp->cur_skb);
-
- /*
- * Inform the network layer of the new packet.
- */
-#if MAC_DEBUG
- printk("Calling netif_rx()\n");
-#endif
- netif_rx(msp->cur_skb);
-
- /*
- * Remove frame from FDDI buffer.
- */
- mac_discard_frame((struct mac_buf *)&msp->cur_mbuf);
- continue;
- }
- else {
- /*
- * Set up dma and break.
- */
-#if MAC_DEBUG
- printk("mac_process(): Starting receive DMA...\n");
-#endif
- nw = NWORDS(pkt_len);
- msp->dma_state = RECVING;
- *csr0 &= ~(CS0_HREQ | CS0_DMA_ENABLE);
-/* *csr1 |= CS1_RESET_FIFO;
- *csr1 &= ~CS1_RESET_FIFO; */
- if ((*csr1 & CS1_FIFO_LEVEL) != 0) {
- int x;
- printk("fifo not empty! (csr1 = 0x%x) emptying...", *csr1);
- do {
- x = *fifo;
- } while ((*csr1 & CS1_FIFO_LEVEL) != 0);
- printk("done\n");
- }
- fstart = msp->cur_mbuf.fr_start + NWORDS(FDDI_HARDHDR_LEN);
- if (fstart >= RECV_BUF_END)
- fstart -= RECV_BUF_SIZE;
- mac->rpr = fstart;
-#if MAC_DEBUG
- printk("rpr=0x%x, nw=0x%x, stat=0x%x\n",
- mac->rpr, nw, buffer_mem[msp->cur_mbuf.fr_start]);
-#endif
- dma->st = DMA_DMST_RST;
- dma->st = DMA_RESET_MASKS;
- dma->hskip = 1; /* skip = 0, count = 1 */
- dma->vskip = 1; /* skip = 0, count = 1 */
- dma->maddr = (u_char *)
- mmu_v2p((unsigned long)
- skb_put(msp->cur_skb, ROUND4(pkt_len)));
- dma->cmd = DMA_DCMD_ST + DMA_DCMD_TYP_AUTO + DMA_DCMD_TD_DM
- + nw - 4;
- *csr0 |= CS0_HREQ_RECV | CS0_DMA_RECV;
- *csr0 |= CS0_DMA_ENABLE;
-#if MAC_DEBUG
- printk("mac_process(): DMA is away!\n");
-#endif
- break;
- }
- }
- else {
-#if MAC_DEBUG
- printk("mac_recv_frame failed\n");
-#endif
- if (msp->recv_empty && send_buffer_full)
- break;
- }
- }
- /*
- * Update mac_queue_bottom.
- */
- if (mac_queue_top == NULL)
- mac_queue_bottom = NULL;
-
-#if MAC_DEBUG
- printk("End of mac_process()\n");
-#endif
- restore_flags(flags);
-}
-
-
-#define DMA_IN(reg) (*(volatile unsigned *)(reg))
-#define DMA_OUT(reg,v) (*(volatile unsigned *)(reg) = (v))
-
-/*
- * DMA completion handler.
- */
-void mac_dma_complete(void)
-{
- volatile struct dma_chan *dma;
- struct formac_state *msp = &this_mac_state;
- unsigned a;
-
- a = DMA_IN(DMA3_DMST);
- if (!(a & DMA_INTR_REQS)) {
- if (msp->dma_state != IDLE && (a & DMA_DMST_AC) == 0) {
- printk("dma completed but no interrupt!\n");
- msp->dma_state = IDLE;
- }
- return;
- }
-
- DMA_OUT(DMA3_DMST,AP_CLR_INTR_REQ<<DMA_INTR_NORMAL_SH);
- DMA_OUT(DMA3_DMST,AP_CLR_INTR_REQ<<DMA_INTR_ERROR_SH);
-
- dma = (volatile struct dma_chan *) DMA3;
-
-#if MAC_DEBUG
- printk("In mac_dma_complete\n");
-#endif
-
- if (msp->dma_state == XMITTING && ((dma->st & DMA_DMST_AC) == 0)) {
- /*
- * Transmit DMA finished.
- */
- int i = 20;
-#if MAC_DEBUG
- printk("In mac_dma_complete for transmit complete\n");
-#endif
- while (*csr1 & CS1_FIFO_LEVEL) {
- if (--i <= 0) {
- printk("csr0=0x%x csr1=0x%x: fifo not emptying\n", *csr0,
- *csr1);
- return;
- }
- }
- *csr0 &= ~(CS0_HREQ | CS0_DMA_ENABLE);
- msp->dma_state = IDLE;
-#if MAC_DEBUG
- printk("mac_dma_complete(): Calling mac_queue_frame\n");
-#endif
- mac_queue_frame((struct mac_buf *)&msp->cur_mbuf);
- dev_kfree_skb(msp->cur_macq->skb);
- kfree_s((struct mac_buf *)msp->cur_macq, sizeof(*(msp->cur_macq)));
- msp->cur_macq = NULL;
-#if MAC_DEBUG
- printk("mac_dma_complete(): Calling mac_process()\n");
-#endif
- mac_process();
-#if MAC_DEBUG
- printk("End of mac_dma_complete transmitting\n");
-#endif
- }
- else if (msp->dma_state == RECVING && ((dma->st & DMA_DMST_AC) == 0)) {
- /*
- * Receive DMA finished. Copy the last four words from the
- * fifo into the buffer, after turning off the host requests.
- * We do this to avoid reading past the end of frame.
- */
- int *ip, i;
-
-#if MAC_DEBUG
- printk("In mac_dma_complete for receive complete\n");
-#endif
- msp->dma_state = IDLE;
- ip = (int *)mmu_p2v((unsigned long)dma->cmaddr);
-
-#if MAC_DEBUG
- printk("ip is 0x%x, skb->data is 0x%x\n", ip, msp->cur_skb->data);
-#endif
-
- *csr0 &= ~(CS0_DMA_ENABLE | CS0_HREQ);
-
- for (i = 0; (*csr1 & CS1_FIFO_LEVEL); ++i)
- ip[i] = *fifo;
- if (i != 4)
- printk("mac_dma_complete(): not four words remaining in fifo?\n");
-#if MAC_DEBUG
- printk("Copied last four words out of fifo\n");
-#endif
-
- /*
- * Remove the frame from the FDDI receive buffer.
- */
- mac_discard_frame((struct mac_buf *)&msp->cur_mbuf);
-
- CHECK_IF_CHECKSUM_REQUIRED(msp->cur_skb);
-
- /*
- * Now inject the packet into the network system.
- */
- netif_rx(msp->cur_skb);
-
-#if MAC_DEBUG
- dump_packet("mac_dma_complete:", msp->cur_skb->data, 0, 0);
-#endif
-
- /*
- * Check if any more frames can be processed.
- */
- mac_process();
-
-#if MAC_DEBUG
- printk("End of mac_dma_complete receiving\n");
-#endif
- }
-#if MAC_DEBUG
- printk("End of mac_dma_complete()\n");
-#endif
-}
-
-static void mac_print_state(void)
-{
- struct formac_state *msp = &this_mac_state;
-
- printk("DMA3_DMST is 0x%x dma_state is %d\n", DMA_IN(DMA3_DMST),
- msp->dma_state);
- printk("csr0 = 0x%x, csr1 = 0x%x\n", *csr0, *csr1);
-}
-
-
diff --git a/drivers/ap1000/mac.h b/drivers/ap1000/mac.h
deleted file mode 100644
index 85f02b4a3..000000000
--- a/drivers/ap1000/mac.h
+++ /dev/null
@@ -1,82 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * Definitions of MAC state structures etc.
- */
-
-struct mac_info {
- TimerTwosComplement tmax;
- TimerTwosComplement tvx;
- TimerTwosComplement treq;
- ShortAddressType s_address;
- LongAddressType l_address;
- ShortAddressType s_group_adrs;
- LongAddressType l_group_adrs;
- int rcv_own_frames;
- int only_good_frames;
-};
-
-
-struct mac_buf {
- struct mac_buf *next;
- int ack;
- int length;
- void *ptr;
- int wraplen;
- void *wrapptr;
- int fr_start;
- int fr_end;
-};
-
-int mac_xmit_space(void);
-void mac_xmit_alloc(struct mac_buf *, int);
-void mac_queue_frame(struct mac_buf *);
-int mac_recv_frame(struct mac_buf *);
-void mac_discard_frame(struct mac_buf *);
-int mac_init(struct mac_info *mip);
-int mac_inited(struct mac_info *mip);
-void mac_reset(LoopbackType loopback);
-void mac_claim(void);
-void mac_sleep(void);
-void mac_poll(void);
-void mac_disable(void);
-void mac_make_spframes(void);
-int mac_xalloc(int nwords);
-int mac_xmit_dma(struct sk_buff *skb);
-void mac_dma_complete(void);
-void mac_process(void);
-int mac_queue_append(struct sk_buff *skb);
-
-struct dma_chan {
- int cmd; /* cmd << 16 + size */
- int st; /* status << 16 + current size */
- int hskip; /* hskip << 16 + hcnt */
- int vskip; /* vskip << 16 + vcnt */
- unsigned char *maddr; /* memory address */
- unsigned char *cmaddr; /* current memory address */
- int ccount; /* h_count << 16 + v_count */
- int *tblp; /* table pointer */
- int *ctblp; /* current table pointer */
- unsigned char *hdptr; /* header pointer */
-};
-
-#define ROUND4(x) (((x) + 3) & -4)
-#define ROUND8(x) (((x) + 7) & -8)
-#define ROUND16(x) (((x) + 15) & -16)
-#define ROUNDLINE(x) ROUND16(x)
-
-#define NWORDS(x) (((x) + 3) >> 2)
-#define NLINES(x) (((x) + 15) >> 4)
-
-/*
- * Queue element used to queue transmit requests on the FDDI.
- */
-struct mac_queue {
- volatile struct mac_queue *next;
- struct sk_buff *skb;
-};
diff --git a/drivers/ap1000/plc.c b/drivers/ap1000/plc.c
deleted file mode 100644
index b29b1a4c2..000000000
--- a/drivers/ap1000/plc.c
+++ /dev/null
@@ -1,393 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * Routines for controlling the Am79c864 physical layer controller.
- *
- * This chip implements some parts of the FDDI SMT standard
- * (PCM: physical connection management, LEM: link error monitor, etc.)
- * as well as the FDDI PHY standard.
- */
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-#include "apfddi.h"
-#include "smt-types.h"
-#include "am79c864.h"
-#include "plc.h"
-#include "apfddi-reg.h"
-
-typedef enum {
- off,
- signalling,
- doing_lct,
- joining,
- active
-} PlcPhase;
-
-struct plc_state {
- LoopbackType loopback;
- char t_val[16];
- char r_val[16];
- int n;
- PortType peer_type;
- PlcPhase phase;
-};
-
-struct plc_info *this_plc_info;
-struct plc_state this_plc_state;
-
-void plc_init(struct plc_info *pip)
-{
- int class, x;
- struct plc_state *psp = &this_plc_state;
-
- this_plc_info = pip;
-
- /* first turn it off, clear registers */
- class = pip->port_type == pt_s? CB_CLASS_S: 0;
- plc->ctrl_b = CB_PC_STOP + class;
- plc->intr_mask = IE_NP_ERROR;
- x = plc->intr_event; /* these register clear when read */
- x = plc->viol_sym_ct;
- x = plc->min_idle_ct;
- x = plc->link_err_ct;
-
- /* initialize registers */
- plc->ctrl_a = 0;
- plc->ctrl_b = class;
- plc->c_min = pip->c_min >> 8;
- plc->tl_min = pip->tl_min >> 8;
- plc->tb_min = pip->tb_min >> 8;
- plc->t_out = pip->t_out >> 8;
- plc->t_scrub = pip->t_scrub >> 8;
- plc->ns_max = pip->ns_max >> 2;
-
- psp->phase = off;
-}
-
-int
-plc_inited(struct plc_info *pip)
-{
- int class, x;
- struct plc_state *psp = &this_plc_state;
-
- class = pip->port_type == pt_s? CB_CLASS_S: 0;
- if ((plc->ctrl_a & (CA_LOOPBACK|CA_FOT_OFF|CA_EB_LOOP|CA_LM_LOOP)) != 0)
- return 1;
- if ((plc->ctrl_b & (CB_CONFIG_CTRL|CB_CLASS_S|CB_PC_MAINT)) != class)
- return 2;
- if (plc->status_a & SA_SIG_DETECT)
- return 3;
- if ((plc->status_b & (SB_PCI_STATE|SB_PCM_STATE))
- != (SB_PCI_STATE_INSERTED|SB_PCM_STATE_ACTIVE))
- return 4;
-
- /* all seems OK, reset the timers and counters just to be sure */
- plc->intr_mask = IE_NP_ERROR;
- x = plc->intr_event; /* these register clear when read */
- x = plc->viol_sym_ct;
- x = plc->min_idle_ct;
- x = plc->link_err_ct;
-
- plc->c_min = pip->c_min >> 8;
- plc->tl_min = pip->tl_min >> 8;
- plc->tb_min = pip->tb_min >> 8;
- plc->t_out = pip->t_out >> 8;
- plc->t_scrub = pip->t_scrub >> 8;
- plc->ns_max = pip->ns_max >> 2;
-
- psp->phase = active;
- /* XXX should initialize other fields of this_plc_state */
-
- return 0;
-}
-
-void plc_sleep(void)
-{
-}
-
-void pc_start(LoopbackType loopback)
-{
- int x;
- struct plc_info *pip = this_plc_info;
- struct plc_state *psp = &this_plc_state;
-
- /* make sure it's off */
- plc->ctrl_b &= ~CB_PCM_CTRL;
- plc->ctrl_b |= CB_PC_STOP;
-
- /* set up loopback required */
- psp->loopback = loopback;
- x = 0;
- switch (loopback) {
- case loop_plc_lm:
- x = CA_LM_LOOP;
- break;
- case loop_plc_eb:
- x = CA_EB_LOOP;
- break;
- case loop_pdx:
- x = CA_LOOPBACK;
- break;
- default:
- x = 0;
- }
- plc->ctrl_a = x;
-
- /* set up bits to be exchanged */
- psp->t_val[0] = 0;
- psp->t_val[1] = ((int) pip->port_type >> 1) & 1;
- psp->t_val[2] = (int) pip->port_type & 1;
- psp->t_val[4] = 0; /* XXX assume we want short LCT */
- psp->t_val[5] = 0;
- psp->t_val[6] = 0; /* XXX too lazy to fire up my MAC for LCT */
- psp->t_val[8] = 0; /* XXX don't wanna local loop */
- psp->t_val[9] = 1; /* gotta MAC on port output */
-
- pc_restart();
-}
-
-void pc_restart(void)
-{
- struct plc_state *psp = &this_plc_state;
-
- if (psp->phase != off)
- printk("restarting pcm\n");
- if (psp->phase == active)
- set_cf_join(0); /* we're down :-( */
-
- psp->n = 0;
- plc->vec_length = 3 - 1;
- plc->xmit_vector = psp->t_val[0] + (psp->t_val[1] << 1)
- + (psp->t_val[2] << 2);
-
- plc->intr_mask = IE_NP_ERROR | IE_PCM_BREAK | IE_PCM_CODE;
- plc->ctrl_b &= ~CB_PCM_CTRL;
- plc->ctrl_b |= CB_PC_START; /* light blue paper and stand clear */
-
- psp->phase = signalling;
-}
-
-void pc_stop(void)
-{
- struct plc_state *psp = &this_plc_state;
-
- if (psp->phase == active)
- set_cf_join(0);
- plc->ctrl_b &= ~CB_PCM_CTRL;
- plc->ctrl_b |= CB_PC_STOP;
- plc->intr_mask = IE_NP_ERROR;
- psp->phase = off;
-}
-
-void plc_poll(void)
-{
- struct plc_state *psp = &this_plc_state;
- int events, i;
-
- if ((*csr0 & CS0_PHY_IRQ) == 0)
- return;
- events = plc->intr_event & plc->intr_mask;
- if (events & IE_NP_ERROR) {
- printk("plc: NP error!\n");
- }
- if (events & IE_PCM_BREAK) {
- i = plc->status_b & SB_BREAK_REASON;
- if (i > SB_BREAK_REASON_START) {
- if (psp->phase == signalling || psp->phase == doing_lct)
- pcm_dump_rtcodes();
- printk("pcm: break reason %d\n", i);
- if (psp->phase != off)
- pc_restart();
- /* XXX need to check for trace? */
- }
- }
- if (events & IE_PCM_CODE) {
- if (psp->phase == signalling)
- pcm_pseudo_code();
- else if (psp->phase == doing_lct)
- pcm_lct_done();
- else
- printk("XXX pcm_code interrupt in phase %d?\n", psp->phase);
- }
- if (events & IE_PCM_ENABLED) {
- if (psp->phase == joining)
- pcm_enabled();
- else
- printk("XXX pcm_enabled interrupt in phase %d?\n", psp->phase);
- }
- if (events & IE_TRACE_PROP) {
- if (psp->phase == active)
- pcm_trace_prop();
- else
- printk("XXX trace_prop interrupt in phase %d\n", psp->phase);
- }
-}
-
-void pcm_pseudo_code(void)
-{
- struct plc_info *pip = this_plc_info;
- struct plc_state *psp = &this_plc_state;
- int i, nb, lct, hislct;
-
- /* unpack the bits from the peer */
- nb = plc->vec_length + 1;
- i = plc->rcv_vector;
- do {
- psp->r_val[psp->n++] = i & 1;
- i >>= 1;
- } while (--nb > 0);
-
- /* send some more, do LCT, whatever */
- switch (psp->n) {
- case 3:
- /*
- * Got escape flag, port type; send compatibility,
- * LCT duration, MAC for LCT flag.
- */
- if (psp->r_val[0]) {
- /* help! what do I do now? */
- pcm_dump_rtcodes();
- pc_restart();
- break;
- }
- psp->peer_type = (PortType) ((psp->r_val[1] << 1) + psp->r_val[2]);
- /* XXX we're type S, we talk to anybody */
- psp->t_val[3] = 1;
-
- plc->vec_length = 4 - 1;
- plc->xmit_vector = psp->t_val[3] + (psp->t_val[4] << 1)
- + (psp->t_val[5] << 2) + (psp->t_val[6] << 3);
- break;
-
- case 7:
- /*
- * Got compatibility, LCT duration, MAC for LCT flag;
- * time to do the LCT.
- */
- lct = (psp->t_val[4] << 1) + psp->t_val[5];
- hislct = (psp->r_val[4] << 1) + psp->r_val[5];
- if (hislct > lct)
- lct = hislct;
-
- /* set LCT duration */
- switch (lct) {
- case 0:
- plc->lc_length = pip->lc_short >> 8;
- plc->ctrl_b &= ~CB_LONG_LCT;
- break;
- case 1:
- plc->lc_length = pip->lc_medium >> 8;
- plc->ctrl_b &= ~CB_LONG_LCT;
- break;
- case 2:
- plc->ctrl_b |= CB_LONG_LCT;
- /* XXX set up a timeout for pip->lc_long */
- break;
- case 3:
- plc->ctrl_b |= CB_LONG_LCT;
- /* XXX set up a timeout for pip->lc_extended */
- break;
- }
-
- /* start the LCT */
- i = plc->link_err_ct; /* clear the register */
- plc->ctrl_b &= ~CB_PC_LCT;
- /* XXX assume we're not using the MAC for LCT;
- if he's got a MAC, loop his stuff back, otherwise send idle. */
- if (psp->r_val[6])
- plc->ctrl_b |= CB_PC_LCT_LOOP;
- else
- plc->ctrl_b |= CB_PC_LCT_IDLE;
- psp->phase = doing_lct;
- break;
-
- case 8:
- /*
- * Got LCT result, send MAC for local loop and MAC on port
- * output flags.
- */
- if (psp->t_val[7] || psp->r_val[7]) {
- printk("LCT failed, restarting.\n");
- /* LCT failed - do at least a medium length test next time. */
- if (psp->t_val[4] == 0 && psp->t_val[5] == 0)
- psp->t_val[5] = 1;
- pcm_dump_rtcodes();
- pc_restart();
- break;
- }
- plc->vec_length = 2 - 1;
- plc->xmit_vector = psp->t_val[8] + (psp->t_val[9] << 1);
- break;
-
- case 10:
- /*
- * Got MAC for local loop and MAC on port output flags.
- * Let's join.
- */
- plc->intr_mask = IE_NP_ERROR | IE_PCM_BREAK | IE_PCM_ENABLED;
- plc->ctrl_b |= CB_PC_JOIN;
- psp->phase = joining;
- /* printk("pcm: joining\n"); */
- break;
-
- default:
- printk("pcm_pseudo_code bug: n = %d\n", psp->n);
- }
-}
-
-void pcm_lct_done(void)
-{
- struct plc_state *psp = &this_plc_state;
- int i;
-
- i = plc->link_err_ct;
- psp->t_val[7] = i > 0;
- printk("pcm: lct %s (%d errors)\n", psp->t_val[7]? "failed": "passed", i);
- plc->ctrl_b &= ~(CB_PC_LCT | CB_LONG_LCT);
- plc->vec_length = 1 - 1;
- plc->xmit_vector = psp->t_val[7];
- psp->phase = signalling;
-}
-
-void pcm_dump_rtcodes(void)
-{
- struct plc_state *psp = &this_plc_state;
- int i;
-
- if (psp->n > 0) {
- printk("pcm signalling interrupted after %d bits:\nt_val:", psp->n);
- for (i = 0; i < psp->n; ++i)
- printk(" %d", psp->t_val[i]);
- printk("\nr_val:");
- for (i = 0; i < psp->n; ++i)
- printk(" %d", psp->r_val[i]);
- printk("\n");
- }
-}
-
-void pcm_enabled(void)
-{
- struct plc_state *psp = &this_plc_state;
- int i;
-
- printk("pcm: enabled\n");
- psp->phase = active;
- i = plc->link_err_ct; /* clear the register */
- /* XXX should set up LEM here */
- /* XXX do we want to count violation symbols, minimum idle gaps,
- or elasticity buffer errors? */
- plc->intr_mask = IE_NP_ERROR | IE_PCM_BREAK | IE_TRACE_PROP;
- set_cf_join(1); /* we're up :-) */
-}
-
-void pcm_trace_prop(void)
-{
- /* XXX help! what do I do now? */
- pc_stop();
-}
diff --git a/drivers/ap1000/plc.h b/drivers/ap1000/plc.h
deleted file mode 100644
index f87783f57..000000000
--- a/drivers/ap1000/plc.h
+++ /dev/null
@@ -1,53 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * Definitions for PLC state structures etc.
- */
-
-struct plc_info {
- PortType port_type;
- TimerTwosComplement c_min;
- TimerTwosComplement tl_min;
- TimerTwosComplement tb_min;
- TimerTwosComplement t_out;
- TimerTwosComplement lc_short;
- TimerTwosComplement lc_medium;
- TimerTwosComplement lc_long;
- TimerTwosComplement lc_extended;
- TimerTwosComplement t_scrub;
- TimerTwosComplement ns_max;
- Counter link_errors;
- Counter viol_syms;
- Counter mini_occur;
- int min_idle_gap;
- double link_error_rate;
-};
-
-void plc_init(struct plc_info *pip);
-int plc_inited(struct plc_info *pip);
-void pc_start(LoopbackType loopback);
-void plc_sleep(void);
-void plc_poll(void);
-void pc_stop(void);
-void pc_restart(void);
-void pcm_dump_rtcodes(void);
-void pcm_pseudo_code(void);
-void pcm_lct_done(void);
-void pcm_enabled(void);
-void pcm_trace_prop(void);
-
-
-
-
-
-
-
-
-
-
-
diff --git a/drivers/ap1000/ringbuf.c b/drivers/ap1000/ringbuf.c
deleted file mode 100644
index 8acb617b6..000000000
--- a/drivers/ap1000/ringbuf.c
+++ /dev/null
@@ -1,311 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * linux/drivers/ap1000/ringbuf.c
- *
- * This provides the /proc/XX/ringbuf interface to the Tnet ring buffer
- */
-#define _APLIB_
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/malloc.h>
-#include <linux/mm.h>
-
-#include <asm/page.h>
-#include <asm/segment.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
-
-#include <asm/ap1000/pgtapmmu.h>
-#include <asm/ap1000/apreg.h>
-#include <asm/ap1000/apservice.h>
-
-
-/* we have a small number of reserved ring buffers to ensure that at
- least one parallel program can always run */
-#define RBUF_RESERVED 4
-#define RBUF_RESERVED_ORDER 5
-static struct {
- char *rb_ptr;
- char *shared_ptr;
- int used;
-} reserved_ringbuf[RBUF_RESERVED];
-
-
-void ap_ringbuf_init(void)
-{
- int i,j;
- char *rb_ptr, *shared_ptr;
- int rb_size = PAGE_SIZE * (1<<RBUF_RESERVED_ORDER);
-
- /* preallocate some ringbuffers */
- for (i=0;i<RBUF_RESERVED;i++) {
- if (!(rb_ptr = (char *)__get_free_pages(GFP_ATOMIC,RBUF_RESERVED_ORDER))) {
- printk("failed to preallocate ringbuf %d\n",i);
- return;
- }
- for (j = MAP_NR(rb_ptr); j <= MAP_NR(rb_ptr+rb_size-1); j++) {
- set_bit(PG_reserved,&mem_map[j].flags);
- }
-
- if (!(shared_ptr = (char *)__get_free_page(GFP_ATOMIC))) {
- printk("failed to preallocate shared ptr %d\n",i);
- return;
- }
- set_bit(PG_reserved,&mem_map[MAP_NR(shared_ptr)].flags);
-
- reserved_ringbuf[i].used = 0;
- reserved_ringbuf[i].rb_ptr = rb_ptr;
- reserved_ringbuf[i].shared_ptr = shared_ptr;
- }
-}
-
-
-
-void exit_ringbuf(struct task_struct *tsk)
-{
- int i;
-
- if (!tsk->ringbuf) return;
-
- if (tsk->ringbuf->ringbuf) {
- char *rb_ptr = tsk->ringbuf->ringbuf;
- char *shared_ptr = tsk->ringbuf->shared;
- int order = tsk->ringbuf->order;
- int rb_size = PAGE_SIZE * (1<<order);
-
- for (i=0;i<RBUF_RESERVED;i++)
- if (rb_ptr == reserved_ringbuf[i].rb_ptr) break;
-
- if (i < RBUF_RESERVED) {
- reserved_ringbuf[i].used = 0;
- } else {
- for (i = MAP_NR(rb_ptr); i <= MAP_NR(rb_ptr+rb_size-1); i++) {
- clear_bit(PG_reserved, &mem_map[i].flags);
- }
- free_pages((unsigned)rb_ptr,order);
-
- i = MAP_NR(shared_ptr);
- clear_bit(PG_reserved,&mem_map[i]);
- free_page((unsigned)shared_ptr);
- }
- }
-
- kfree_s(tsk->ringbuf,sizeof(*(tsk->ringbuf)));
- tsk->ringbuf = NULL;
-}
-
-
-/*
- * map the ring buffer into users memory
- */
-static int cap_map(int rb_size)
-{
- struct task_struct *tsk=current;
- int i;
- char *rb_ptr=NULL;
- char *shared_ptr=NULL;
- int order = 0;
- int error,old_uid;
-
- error = verify_area(VERIFY_WRITE,(char *)RBUF_VBASE,rb_size);
- if (error) return error;
-
- if (!MPP_IS_PAR_TASK(tsk->taskid)) {
- printk("ringbuf_mmap called from non-parallel task\n");
- return -EINVAL;
- }
-
-
- if (tsk->ringbuf) return -EINVAL;
-
- rb_size -= RBUF_RING_BUFFER_OFFSET;
- rb_size >>= 1;
-
- switch (rb_size/1024) {
- case 128:
- order = 5;
- break;
- case 512:
- order = 7;
- break;
- case 2048:
- order = 9;
- break;
- case 8192:
- order = 11;
- break;
- default:
- printk("ringbuf_mmap with invalid size %d\n",rb_size);
- return -EINVAL;
- }
-
- if (order == RBUF_RESERVED_ORDER) {
- for (i=0;i<RBUF_RESERVED;i++)
- if (!reserved_ringbuf[i].used) {
- rb_ptr = reserved_ringbuf[i].rb_ptr;
- shared_ptr = reserved_ringbuf[i].shared_ptr;
- reserved_ringbuf[i].used = 1;
- break;
- }
- }
-
- if (!rb_ptr) {
- rb_ptr = (char *)__get_free_pages(GFP_USER,order);
- if (!rb_ptr) return -ENOMEM;
-
- for (i = MAP_NR(rb_ptr); i <= MAP_NR(rb_ptr+rb_size-1); i++) {
- set_bit(PG_reserved,&mem_map[i].flags);
- }
-
- shared_ptr = (char *)__get_free_page(GFP_USER);
- if (!shared_ptr)
- return -ENOMEM;
- set_bit(PG_reserved,&mem_map[MAP_NR(shared_ptr)].flags);
- }
-
- if (!rb_ptr)
- return -ENOMEM;
-
- memset(rb_ptr,0,rb_size);
- memset(shared_ptr,0,PAGE_SIZE);
-
- if (remap_page_range(RBUF_VBASE + RBUF_RING_BUFFER_OFFSET,
- mmu_v2p((unsigned)rb_ptr),
- rb_size,APMMU_PAGE_SHARED))
- return -EAGAIN;
-
- if (remap_page_range(RBUF_VBASE + RBUF_RING_BUFFER_OFFSET + rb_size,
- mmu_v2p((unsigned)rb_ptr),
- rb_size,APMMU_PAGE_SHARED))
- return -EAGAIN;
-
- /* the shared area */
- if (remap_page_range(RBUF_VBASE + RBUF_SHARED_PAGE_OFF,
- mmu_v2p((unsigned)shared_ptr),
- PAGE_SIZE,APMMU_PAGE_SHARED))
- return -EAGAIN;
-
-#if 0
- /* lock the ringbuffer in memory */
- old_uid = current->euid;
- current->euid = 0;
- error = sys_mlock(RBUF_VBASE,2*rb_size+RBUF_RING_BUFFER_OFFSET);
- current->euid = old_uid;
- if (error) {
- printk("ringbuffer mlock failed\n");
- return error;
- }
-#endif
-
- /* the queue pages */
-#define MAP_QUEUE(offset,phys) \
- io_remap_page_range(RBUF_VBASE + offset, \
- phys<<PAGE_SHIFT,PAGE_SIZE,APMMU_PAGE_SHARED,0xa)
-
- MAP_QUEUE(RBUF_PUT_QUEUE, 0x00000);
- MAP_QUEUE(RBUF_GET_QUEUE, 0x00001);
- MAP_QUEUE(RBUF_SEND_QUEUE, 0x00040);
-
- MAP_QUEUE(RBUF_XY_QUEUE, 0x00640);
- MAP_QUEUE(RBUF_X_QUEUE, 0x00240);
- MAP_QUEUE(RBUF_Y_QUEUE, 0x00440);
- MAP_QUEUE(RBUF_XYG_QUEUE, 0x00600);
- MAP_QUEUE(RBUF_XG_QUEUE, 0x00200);
- MAP_QUEUE(RBUF_YG_QUEUE, 0x00400);
- MAP_QUEUE(RBUF_CSI_QUEUE, 0x02004);
- MAP_QUEUE(RBUF_FOP_QUEUE, 0x02005);
-
-#undef MAP_QUEUE
-
- if (!tsk->ringbuf) {
- tsk->ringbuf = (void *)kmalloc(sizeof(*(tsk->ringbuf)),GFP_ATOMIC);
- if (!tsk->ringbuf)
- return -ENOMEM;
- }
-
- memset(tsk->ringbuf,0,sizeof(*tsk->ringbuf));
- tsk->ringbuf->ringbuf = rb_ptr;
- tsk->ringbuf->shared = shared_ptr;
- tsk->ringbuf->order = order;
- tsk->ringbuf->write_ptr = mmu_v2p((unsigned)rb_ptr)<<1;
- tsk->ringbuf->vaddr = RBUF_VBASE;
-
- memset(tsk->ringbuf->vaddr+RBUF_SHARED_PAGE_OFF,0,PAGE_SIZE);
- {
- struct _kernel_cap_shared *_kernel =
- (struct _kernel_cap_shared *)tsk->ringbuf->vaddr;
- _kernel->rbuf_read_ptr = (rb_size>>5) - 1;
- }
-
- return 0;
-}
-
-
-static int
-ringbuf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
-{
- int numcells, *phys_cells;
- extern struct cap_init cap_init;
-
- switch (cmd) {
- case CAP_GETINIT:
- if (copy_to_user((char *)arg,(char *)&cap_init,sizeof(cap_init)))
- return -EFAULT;
- break;
-
- case CAP_SYNC:
- if (verify_area(VERIFY_READ, (void *) arg, sizeof(int)*2))
- return -EFAULT;
- if (get_user(numcells,(int *)arg)) return -EFAULT;
- if (get_user((unsigned)phys_cells,
- ((int *)arg)+1)) return -EFAULT;
- if (verify_area(VERIFY_READ,phys_cells,sizeof(int)*numcells))
- return -EFAULT;
- return ap_sync(numcells,phys_cells);
- break;
-
- case CAP_SETGANG:
- {
- int v;
- if (get_user(v,(int *)arg)) return -EFAULT;
- mpp_set_gang_factor(v);
- break;
- }
-
- case CAP_MAP:
- return cap_map(arg);
-
- default:
- printk("unknown ringbuf ioctl %d\n",cmd);
- return -EINVAL;
- }
- return 0;
-}
-
-
-static struct file_operations proc_ringbuf_operations = {
- NULL,
- NULL,
- NULL,
- NULL, /* readdir */
- NULL, /* poll */
- ringbuf_ioctl, /* ioctl */
- NULL, /* mmap */
- NULL, /* no special open code */
- NULL, /* flush */
- NULL, /* no special release code */
- NULL /* can't fsync */
-};
-
-struct inode_operations proc_ringbuf_inode_operations = {
- &proc_ringbuf_operations, /* default base directory file-ops */
-};
diff --git a/drivers/ap1000/smt-types.h b/drivers/ap1000/smt-types.h
deleted file mode 100644
index b17c83176..000000000
--- a/drivers/ap1000/smt-types.h
+++ /dev/null
@@ -1,167 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * Definitions for FDDI Station Management.
- */
-
-/*
- * FDDI-COMMON types.
- */
-
-typedef unsigned int Counter; /* 32-bit event counter */
-
-typedef enum {
- cp_isolated,
- cp_local,
- cp_secondary,
- cp_primary,
- cp_concatenated,
- cp_thru
-} CurrentPath;
-
-typedef char Flag;
-
-typedef unsigned char LongAddressType[6];
-
-typedef enum {
- pt_a,
- pt_b,
- pt_s,
- pt_m,
- pt_none
-} PortType;
-
-typedef unsigned short ResourceId;
-
-typedef int Time; /* time in 80ns units */
-#define FDDI_TIME_UNIT 80e-9 /* 80 nanoseconds */
-#define SECS_TO_FDDI_TIME(s) ((int)((s)/FDDI_TIME_UNIT+0.99))
-
-typedef int TimerTwosComplement;
-
-/*
- * FDDI-SMT types.
- */
-typedef enum {
- ec_Out,
- ec_In,
- ec_Trace,
- ec_Leave,
- ec_Path_Test,
- ec_Insert,
- ec_Check,
- ec_Deinsert
-} ECMState;
-
-/*
- * FDDI-MAC types.
- */
-typedef enum {
- dat_none,
- dat_pass,
- dat_fail
-} DupAddressTest;
-
-typedef unsigned short DupCondition;
-#define DC_MYDUP 1
-#define DC_UNADUP 2
-
-typedef unsigned short FS_Functions;
-#define FSF_FS_REPEATING 1
-#define FSF_FS_SETTING 2
-#define FSF_FS_CLEARING 4
-
-typedef unsigned char NACondition;
-#define NAC_UNACHANGE 1
-#define NAC_DNACHANGE 2
-
-typedef enum {
- rmt_Isolated,
- rmt_Non_Op,
- rmt_Ring_Op,
- rmt_Detect,
- rmt_Non_Op_Dup,
- rmt_Ring_Op_Dup,
- rmt_Directed,
- rmt_Trace
-} RMTState;
-
-typedef unsigned char ShortAddressType[2];
-
-/*
- * FDDI-PATH types.
- */
-typedef unsigned short TraceStatus;
-#define TS_TRACEINITIATED 1
-#define TS_TRACEPROPAGATED 2
-#define TS_TRACETERMINATED 4
-#define TS_TRACETIMEOUT 8
-
-/*
- * FDDI-PORT types.
- */
-typedef enum {
- PC_Maint,
- PC_Enable,
- PC_Disable,
- PC_Start,
- PC_Stop
-} ActionType;
-
-typedef unsigned char ConnectionPolicies;
-#define PC_MAC_LCT 1
-#define PC_MAC_LOOP 2
-
-typedef enum {
- cs_disabled,
- cs_connecting,
- cs_standby,
- cs_active
-} ConnectState;
-
-typedef enum {
- ls_qls,
- ls_ils,
- ls_mls,
- ls_hls,
- ls_pdr,
- ls_lsu,
- ls_nls
-} LineState;
-
-typedef enum {
- pc_Off,
- pc_Break,
- pc_Trace,
- pc_Connect,
- pc_Next,
- pc_Signal,
- pc_Join,
- pc_Verify,
- pc_Active,
- pc_Maint
-} PCMState;
-
-typedef enum {
- pcw_none,
- pcw_mm,
- pcw_otherincompatible,
- pcw_pathnotavailable
-} PC_Withhold;
-
-typedef enum {
- pmd_multimode,
- pmd_single_mode1,
- pmd_single_mode2,
- pmd_sonet,
- pmd_low_cost_fiber,
- pmd_twisted_pair,
- pmd_unknown,
- pmd_unspecified
-} PMDClass;
-
diff --git a/drivers/block/cmd64x.c b/drivers/block/cmd64x.c
index 6346f216e..8f5f04aea 100644
--- a/drivers/block/cmd64x.c
+++ b/drivers/block/cmd64x.c
@@ -7,7 +7,7 @@
* on the 646U2 and not on the 646U.
*
* Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
- * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1998 David S. Miller (davem@redhat.com)
* Copyright (C) 1999 Andre Hedrick (andre@suse.com)
*/
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c
index 3190c10b9..911bafe23 100644
--- a/drivers/block/swim3.c
+++ b/drivers/block/swim3.c
@@ -241,10 +241,6 @@ static int floppy_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long param);
static int floppy_open(struct inode *inode, struct file *filp);
static int floppy_release(struct inode *inode, struct file *filp);
-static ssize_t floppy_read(struct file *filp, char *buf,
- size_t count, loff_t *ppos);
-static ssize_t floppy_write(struct file *filp, const char *buf,
- size_t count, loff_t *ppos);
static int floppy_check_change(kdev_t dev);
static int floppy_revalidate(kdev_t dev);
static int swim3_add_device(struct device_node *swims);
@@ -988,42 +984,6 @@ static int floppy_revalidate(kdev_t dev)
return ret;
}
-static ssize_t floppy_read(struct file *filp, char *buf,
- size_t count, loff_t *ppos)
-{
- struct inode *inode = filp->f_dentry->d_inode;
- struct floppy_state *fs;
- int devnum = MINOR(inode->i_rdev);
-
- if (devnum >= floppy_count)
- return -ENODEV;
-
- fs = &floppy_states[devnum];
- if (fs->ejected)
- return -ENXIO;
- return block_read(filp, buf, count, ppos);
-}
-
-static ssize_t floppy_write(struct file * filp, const char * buf,
- size_t count, loff_t *ppos)
-{
- struct inode * inode = filp->f_dentry->d_inode;
- struct floppy_state *fs;
- int devnum = MINOR(inode->i_rdev);
-
- if (devnum >= floppy_count)
- return -ENODEV;
- check_disk_change(inode->i_rdev);
- fs = &floppy_states[devnum];
- if (fs->ejected)
- return -ENXIO;
- if (fs->write_prot < 0)
- fs->write_prot = swim3_readbit(fs, WRITE_PROT);
- if (fs->write_prot)
- return -EROFS;
- return block_write(filp, buf, count, ppos);
-}
-
static void floppy_off(unsigned int nr)
{
}
diff --git a/drivers/block/swim_iop.c b/drivers/block/swim_iop.c
index 6a74f9a0b..467cda26d 100644
--- a/drivers/block/swim_iop.c
+++ b/drivers/block/swim_iop.c
@@ -102,10 +102,6 @@ static void swimiop_receive(struct iop_msg *, struct pt_regs *);
static void swimiop_status_update(int, struct swim_drvstatus *);
static int swimiop_eject(struct floppy_state *fs);
-static ssize_t floppy_read(struct file *filp, char *buf,
- size_t count, loff_t *ppos);
-static ssize_t floppy_write(struct file *filp, const char *buf,
- size_t count, loff_t *ppos);
static int floppy_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd, unsigned long param);
static int floppy_open(struct inode *inode, struct file *filp);
@@ -338,40 +334,6 @@ static int swimiop_eject(struct floppy_state *fs)
return cmd->error;
}
-static ssize_t floppy_read(struct file *filp, char *buf,
- size_t count, loff_t *ppos)
-{
- struct inode *inode = filp->f_dentry->d_inode;
- struct floppy_state *fs;
- int devnum = MINOR(inode->i_rdev);
-
- if (devnum >= floppy_count)
- return -ENODEV;
-
- fs = &floppy_states[devnum];
- if (fs->ejected)
- return -ENXIO;
- return block_read(filp, buf, count, ppos);
-}
-
-static ssize_t floppy_write(struct file * filp, const char * buf,
- size_t count, loff_t *ppos)
-{
- struct inode * inode = filp->f_dentry->d_inode;
- struct floppy_state *fs;
- int devnum = MINOR(inode->i_rdev);
-
- if (devnum >= floppy_count)
- return -ENODEV;
- check_disk_change(inode->i_rdev);
- fs = &floppy_states[devnum];
- if (fs->ejected)
- return -ENXIO;
- if (fs->write_prot)
- return -EROFS;
- return block_write(filp, buf, count, ppos);
-}
-
static struct floppy_struct floppy_type =
{ 2880,18,2,80,0,0x1B,0x00,0xCF,0x6C,NULL }; /* 7 1.44MB 3.5" */
diff --git a/drivers/char/agp/agpgart_be.c b/drivers/char/agp/agpgart_be.c
index 27413489a..a83928a02 100644
--- a/drivers/char/agp/agpgart_be.c
+++ b/drivers/char/agp/agpgart_be.c
@@ -232,7 +232,6 @@ void agp_free_memory(agp_memory * curr)
}
if (curr->type != 0) {
agp_bridge.free_by_type(curr);
- MOD_DEC_USE_COUNT;
return;
}
if (curr->page_count != 0) {
@@ -260,15 +259,23 @@ agp_memory *agp_allocate_memory(size_t page_count, u32 type)
agp_bridge.max_memory_agp) {
return NULL;
}
+
if (type != 0) {
new = agp_bridge.alloc_by_type(page_count, type);
return new;
}
+ /* We always increase the module count, since free auto-decrements
+ * it
+ */
+
+ MOD_INC_USE_COUNT;
+
scratch_pages = (page_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE;
new = agp_create_memory(scratch_pages);
if (new == NULL) {
+ MOD_DEC_USE_COUNT;
return NULL;
}
for (i = 0; i < page_count; i++) {
@@ -286,7 +293,6 @@ agp_memory *agp_allocate_memory(size_t page_count, u32 type)
new->page_count++;
}
- MOD_INC_USE_COUNT;
return new;
}
@@ -781,11 +787,13 @@ static aper_size_info_fixed intel_i810_sizes[] =
};
#define AGP_DCACHE_MEMORY 1
+#define AGP_PHYS_MEMORY 2
static gatt_mask intel_i810_masks[] =
{
{I810_PTE_VALID, 0},
- {(I810_PTE_VALID | I810_PTE_LOCAL), AGP_DCACHE_MEMORY}
+ {(I810_PTE_VALID | I810_PTE_LOCAL), AGP_DCACHE_MEMORY},
+ {I810_PTE_VALID, 0}
};
static struct _intel_i810_private {
@@ -896,7 +904,7 @@ static int intel_i810_insert_entries(agp_memory * mem, off_t pg_start,
if ((type == AGP_DCACHE_MEMORY) &&
(mem->type == AGP_DCACHE_MEMORY)) {
/* special insert */
-
+ CACHE_FLUSH();
for (i = pg_start;
i < (pg_start + mem->page_count); i++) {
OUTREG32(intel_i810_private.registers,
@@ -904,20 +912,24 @@ static int intel_i810_insert_entries(agp_memory * mem, off_t pg_start,
(i * 4096) | I810_PTE_LOCAL |
I810_PTE_VALID);
}
-
+ CACHE_FLUSH();
agp_bridge.tlb_flush(mem);
return 0;
}
+ if((type == AGP_PHYS_MEMORY) &&
+ (mem->type == AGP_PHYS_MEMORY)) {
+ goto insert;
+ }
return -EINVAL;
}
- if (mem->is_flushed == FALSE) {
- CACHE_FLUSH();
- mem->is_flushed = TRUE;
- }
+
+insert:
+ CACHE_FLUSH();
for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
OUTREG32(intel_i810_private.registers,
I810_PTE_BASE + (j * 4), mem->memory[i]);
}
+ CACHE_FLUSH();
agp_bridge.tlb_flush(mem);
return 0;
@@ -955,15 +967,55 @@ static agp_memory *intel_i810_alloc_by_type(size_t pg_count, int type)
new->page_count = pg_count;
new->num_scratch_pages = 0;
vfree(new->memory);
+ MOD_INC_USE_COUNT;
return new;
}
+ if(type == AGP_PHYS_MEMORY) {
+ /* The I810 requires a physical address to program
+ * it's mouse pointer into hardware. However the
+ * Xserver still writes to it through the agp
+ * aperture
+ */
+ if (pg_count != 1) {
+ return NULL;
+ }
+ new = agp_create_memory(1);
+
+ if (new == NULL) {
+ return NULL;
+ }
+ MOD_INC_USE_COUNT;
+ new->memory[0] = agp_alloc_page();
+
+ if (new->memory[0] == 0) {
+ /* Free this structure */
+ agp_free_memory(new);
+ return NULL;
+ }
+ new->memory[0] =
+ agp_bridge.mask_memory(
+ virt_to_phys((void *) new->memory[0]),
+ type);
+ new->page_count = 1;
+ new->num_scratch_pages = 1;
+ new->type = AGP_PHYS_MEMORY;
+ new->physical = virt_to_phys((void *) new->memory[0]);
+ return new;
+ }
+
return NULL;
}
static void intel_i810_free_by_type(agp_memory * curr)
{
agp_free_key(curr->key);
+ if(curr->type == AGP_PHYS_MEMORY) {
+ agp_destroy_page((unsigned long)
+ phys_to_virt(curr->memory[0]));
+ vfree(curr->memory);
+ }
kfree(curr);
+ MOD_DEC_USE_COUNT;
}
static unsigned long intel_i810_mask_memory(unsigned long addr, int type)
@@ -1916,7 +1968,7 @@ static struct agp_max_table maxes_table[9] =
static int agp_find_max(void)
{
- long memory, t, index, result;
+ long memory, index, result;
memory = virt_to_phys(high_memory) >> 20;
index = 1;
@@ -1926,16 +1978,15 @@ static int agp_find_max(void)
index++;
}
- t = (memory - maxes_table[index - 1].mem) /
- (maxes_table[index].mem - maxes_table[index - 1].mem);
-
result = maxes_table[index - 1].agp +
- (t * (maxes_table[index].agp - maxes_table[index - 1].agp));
+ ( (memory - maxes_table[index - 1].mem) *
+ (maxes_table[index].agp - maxes_table[index - 1].agp)) /
+ (maxes_table[index].mem - maxes_table[index - 1].mem);
printk(KERN_INFO "agpgart: Maximum main memory to use "
"for agp memory: %ldM\n", result);
result = result << (20 - PAGE_SHIFT);
- return result;
+ return result;
}
#define AGPGART_VERSION_MAJOR 0
diff --git a/drivers/char/agp/agpgart_fe.c b/drivers/char/agp/agpgart_fe.c
index e098b4bab..ef915259e 100644
--- a/drivers/char/agp/agpgart_fe.c
+++ b/drivers/char/agp/agpgart_fe.c
@@ -298,7 +298,7 @@ static agp_memory *agp_allocate_memory_wrap(size_t pg_count, u32 type)
agp_memory *memory;
memory = agp_allocate_memory(pg_count, type);
-
+ printk("memory : %p\n", memory);
if (memory == NULL) {
return NULL;
}
@@ -911,6 +911,7 @@ static int agpioc_allocate_wrap(agp_file_private * priv, unsigned long arg)
return -ENOMEM;
}
alloc.key = memory->key;
+ alloc.physical = memory->physical;
if (copy_to_user((void *) arg, &alloc, sizeof(agp_allocate))) {
agp_free_memory_wrap(memory);
diff --git a/drivers/char/generic_serial.c b/drivers/char/generic_serial.c
index f4ecc75a5..95a6c4370 100644
--- a/drivers/char/generic_serial.c
+++ b/drivers/char/generic_serial.c
@@ -103,10 +103,6 @@ static inline int copy_from_user(void *to,const void *from, int c)
#include "generic_serial.h"
-#ifndef MODULE
-extern void my_hd (unsigned char *ptr, int n);
-#endif
-
static char * tmp_buf;
static DECLARE_MUTEX(tmp_buf_sem);
@@ -119,8 +115,8 @@ int gs_debug = 0;
#define gs_dprintk(f, str...) /* nothing */
#endif
-#define func_enter() gs_dprintk (SX_DEBUG_FLOW, "gs: enter " __FUNCTION__ "\n")
-#define func_exit() gs_dprintk (SX_DEBUG_FLOW, "gs: exit " __FUNCTION__ "\n")
+#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter " __FUNCTION__ "\n")
+#define func_exit() gs_dprintk (GS_DEBUG_FLOW, "gs: exit " __FUNCTION__ "\n")
@@ -856,7 +852,6 @@ void gs_set_termios (struct tty_struct * tty,
if (gs_debug & GS_DEBUG_TERMIOS) {
gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp);
- my_hd ((unsigned char *)tiosp, sizeof (struct termios));
}
#if 0
diff --git a/drivers/char/generic_serial.h b/drivers/char/generic_serial.h
index ca321af9b..2e44bee95 100644
--- a/drivers/char/generic_serial.h
+++ b/drivers/char/generic_serial.h
@@ -12,6 +12,8 @@
#ifndef GENERIC_SERIAL_H
#define GENERIC_SERIAL_H
+#define RS_EVENT_WRITE_WAKEUP 0
+
struct real_driver {
void (*disable_tx_interrupts) (void *);
void (*enable_tx_interrupts) (void *);
@@ -75,6 +77,7 @@ struct gs_port {
#define GS_DEBUG_TERMIOS 0x00000004
#define GS_DEBUG_STUFF 0x00000008
#define GS_DEBUG_CLOSE 0x00000010
+#define GS_DEBUG_FLOW 0x00000020
void gs_put_char(struct tty_struct *tty, unsigned char ch);
diff --git a/drivers/char/joystick/joy-creative.c b/drivers/char/joystick/joy-creative.c
index 7e97a677d..8faec5f82 100644
--- a/drivers/char/joystick/joy-creative.c
+++ b/drivers/char/joystick/joy-creative.c
@@ -66,7 +66,7 @@ static int js_cr_read_packet(int io, unsigned int *data)
int r[2], t[2], p[2];
int i, j, ret;
- for (i = 0; i < 2; i++); {
+ for (i = 0; i < 2; i++) {
r[i] = buf[i] = 0;
p[i] = t[i] = JS_CR_MAX_STROBE;
p[i] += JS_CR_MAX_STROBE;
diff --git a/drivers/char/scc.h b/drivers/char/scc.h
new file mode 100644
index 000000000..53a4cd2ae
--- /dev/null
+++ b/drivers/char/scc.h
@@ -0,0 +1,613 @@
+/*
+ * atari_SCC.h: Definitions for the Am8530 Serial Communications Controller
+ *
+ * Copyright 1994 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+
+
+#ifndef _SCC_H
+#define _SCC_H
+
+#include <linux/delay.h>
+
+/* Special configuration ioctls for the Atari SCC5380 Serial
+ * Communications Controller
+ */
+
+/* ioctl command codes */
+
+#define TIOCGATSCC 0x54c0 /* get SCC configuration */
+#define TIOCSATSCC 0x54c1 /* set SCC configuration */
+#define TIOCDATSCC 0x54c2 /* reset configuration to defaults */
+
+/* Clock sources */
+
+#define CLK_RTxC 0
+#define CLK_TRxC 1
+#define CLK_PCLK 2
+
+/* baud_bases for the common clocks in the Atari. These are the real
+ * frequencies divided by 16.
+ */
+
+#define SCC_BAUD_BASE_TIMC 19200 /* 0.3072 MHz from TT-MFP, Timer C */
+#define SCC_BAUD_BASE_BCLK 153600 /* 2.4576 MHz */
+#define SCC_BAUD_BASE_PCLK4 229500 /* 3.6720 MHz */
+#define SCC_BAUD_BASE_PCLK 503374 /* 8.0539763 MHz */
+#define SCC_BAUD_BASE_NONE 0 /* for not connected or unused
+ * clock sources */
+
+/* The SCC clock configuration structure */
+
+struct scc_clock_config {
+ unsigned RTxC_base; /* base_baud of RTxC */
+ unsigned TRxC_base; /* base_baud of TRxC */
+ unsigned PCLK_base; /* base_baud of PCLK, both channels! */
+ struct {
+ unsigned clksrc; /* CLK_RTxC, CLK_TRxC or CLK_PCLK */
+ unsigned divisor; /* divisor for base baud, valid values:
+ * see below */
+ } baud_table[17]; /* For 50, 75, 110, 135, 150, 200, 300,
+ * 600, 1200, 1800, 2400, 4800, 9600,
+ * 19200, 38400, 57600 and 115200 bps.
+ * The last two could be replaced by
+ * other rates > 38400 if they're not
+ * possible.
+ */
+};
+
+/* The following divisors are valid:
+ *
+ * - CLK_RTxC: 1 or even (1, 2 and 4 are the direct modes, > 4 use
+ * the BRG)
+ *
+ * - CLK_TRxC: 1, 2 or 4 (no BRG, only direct modes possible)
+ *
+ * - CLK_PCLK: >= 4 and even (no direct modes, only BRG)
+ *
+ */
+
+struct scc_port {
+ struct gs_port gs;
+ volatile unsigned char *ctrlp;
+ volatile unsigned char *datap;
+ int x_char; /* xon/xoff character */
+ int c_dcd;
+ int channel;
+ struct scc_port *port_a; /* Reference to port A and B */
+ struct scc_port *port_b; /* structs for reg access */
+};
+
+#define SCC_MAGIC 0x52696368
+
+/***********************************************************************/
+/* */
+/* Register Names */
+/* */
+/***********************************************************************/
+
+/* The SCC documentation gives no explicit names to the registers,
+ * they're just called WR0..15 and RR0..15. To make the source code
+ * better readable and make the transparent write reg read access (see
+ * below) possible, I christen them here with self-invented names.
+ * Note that (real) read registers are assigned numbers 16..31. WR7'
+ * has number 33.
+ */
+
+#define COMMAND_REG 0 /* wo */
+#define INT_AND_DMA_REG 1 /* wo */
+#define INT_VECTOR_REG 2 /* rw, common to both channels */
+#define RX_CTRL_REG 3 /* rw */
+#define AUX1_CTRL_REG 4 /* rw */
+#define TX_CTRL_REG 5 /* rw */
+#define SYNC_ADR_REG 6 /* wo */
+#define SYNC_CHAR_REG 7 /* wo */
+#define SDLC_OPTION_REG 33 /* wo */
+#define TX_DATA_REG 8 /* wo */
+#define MASTER_INT_CTRL 9 /* wo, common to both channels */
+#define AUX2_CTRL_REG 10 /* rw */
+#define CLK_CTRL_REG 11 /* wo */
+#define TIMER_LOW_REG 12 /* rw */
+#define TIMER_HIGH_REG 13 /* rw */
+#define DPLL_CTRL_REG 14 /* wo */
+#define INT_CTRL_REG 15 /* rw */
+
+#define STATUS_REG 16 /* ro */
+#define SPCOND_STATUS_REG 17 /* wo */
+/* RR2 is WR2 for Channel A, Channel B gives vector + current status: */
+#define CURR_VECTOR_REG 18 /* Ch. B only, Ch. A for rw */
+#define INT_PENDING_REG 19 /* Channel A only! */
+/* RR4 is WR4, if b6(MR7') == 1 */
+/* RR5 is WR5, if b6(MR7') == 1 */
+#define FS_FIFO_LOW_REG 22 /* ro */
+#define FS_FIFO_HIGH_REG 23 /* ro */
+#define RX_DATA_REG 24 /* ro */
+/* RR9 is WR3, if b6(MR7') == 1 */
+#define DPLL_STATUS_REG 26 /* ro */
+/* RR11 is WR10, if b6(MR7') == 1 */
+/* RR12 is WR12 */
+/* RR13 is WR13 */
+/* RR14 not present */
+/* RR15 is WR15 */
+
+
+/***********************************************************************/
+/* */
+/* Register Values */
+/* */
+/***********************************************************************/
+
+
+/* WR0: COMMAND_REG "CR" */
+
+#define CR_RX_CRC_RESET 0x40
+#define CR_TX_CRC_RESET 0x80
+#define CR_TX_UNDERRUN_RESET 0xc0
+
+#define CR_EXTSTAT_RESET 0x10
+#define CR_SEND_ABORT 0x18
+#define CR_ENAB_INT_NEXT_RX 0x20
+#define CR_TX_PENDING_RESET 0x28
+#define CR_ERROR_RESET 0x30
+#define CR_HIGHEST_IUS_RESET 0x38
+
+
+/* WR1: INT_AND_DMA_REG "IDR" */
+
+#define IDR_EXTSTAT_INT_ENAB 0x01
+#define IDR_TX_INT_ENAB 0x02
+#define IDR_PARERR_AS_SPCOND 0x04
+
+#define IDR_RX_INT_DISAB 0x00
+#define IDR_RX_INT_FIRST 0x08
+#define IDR_RX_INT_ALL 0x10
+#define IDR_RX_INT_SPCOND 0x18
+#define IDR_RX_INT_MASK 0x18
+
+#define IDR_WAITREQ_RX 0x20
+#define IDR_WAITREQ_IS_REQ 0x40
+#define IDR_WAITREQ_ENAB 0x80
+
+
+/* WR3: RX_CTRL_REG "RCR" */
+
+#define RCR_RX_ENAB 0x01
+#define RCR_DISCARD_SYNC_CHARS 0x02
+#define RCR_ADDR_SEARCH 0x04
+#define RCR_CRC_ENAB 0x08
+#define RCR_SEARCH_MODE 0x10
+#define RCR_AUTO_ENAB_MODE 0x20
+
+#define RCR_CHSIZE_MASK 0xc0
+#define RCR_CHSIZE_5 0x00
+#define RCR_CHSIZE_6 0x40
+#define RCR_CHSIZE_7 0x80
+#define RCR_CHSIZE_8 0xc0
+
+
+/* WR4: AUX1_CTRL_REG "A1CR" */
+
+#define A1CR_PARITY_MASK 0x03
+#define A1CR_PARITY_NONE 0x00
+#define A1CR_PARITY_ODD 0x01
+#define A1CR_PARITY_EVEN 0x03
+
+#define A1CR_MODE_MASK 0x0c
+#define A1CR_MODE_SYNCR 0x00
+#define A1CR_MODE_ASYNC_1 0x04
+#define A1CR_MODE_ASYNC_15 0x08
+#define A1CR_MODE_ASYNC_2 0x0c
+
+#define A1CR_SYNCR_MODE_MASK 0x30
+#define A1CR_SYNCR_MONOSYNC 0x00
+#define A1CR_SYNCR_BISYNC 0x10
+#define A1CR_SYNCR_SDLC 0x20
+#define A1CR_SYNCR_EXTCSYNC 0x30
+
+#define A1CR_CLKMODE_MASK 0xc0
+#define A1CR_CLKMODE_x1 0x00
+#define A1CR_CLKMODE_x16 0x40
+#define A1CR_CLKMODE_x32 0x80
+#define A1CR_CLKMODE_x64 0xc0
+
+
+/* WR5: TX_CTRL_REG "TCR" */
+
+#define TCR_TX_CRC_ENAB 0x01
+#define TCR_RTS 0x02
+#define TCR_USE_CRC_CCITT 0x00
+#define TCR_USE_CRC_16 0x04
+#define TCR_TX_ENAB 0x08
+#define TCR_SEND_BREAK 0x10
+
+#define TCR_CHSIZE_MASK 0x60
+#define TCR_CHSIZE_5 0x00
+#define TCR_CHSIZE_6 0x20
+#define TCR_CHSIZE_7 0x40
+#define TCR_CHSIZE_8 0x60
+
+#define TCR_DTR 0x80
+
+
+/* WR7': SLDC_OPTION_REG "SOR" */
+
+#define SOR_AUTO_TX_ENAB 0x01
+#define SOR_AUTO_EOM_RESET 0x02
+#define SOR_AUTO_RTS_MODE 0x04
+#define SOR_NRZI_DISAB_HIGH 0x08
+#define SOR_ALT_DTRREQ_TIMING 0x10
+#define SOR_READ_CRC_CHARS 0x20
+#define SOR_EXTENDED_REG_ACCESS 0x40
+
+
+/* WR9: MASTER_INT_CTRL "MIC" */
+
+#define MIC_VEC_INCL_STAT 0x01
+#define MIC_NO_VECTOR 0x02
+#define MIC_DISAB_LOWER_CHAIN 0x04
+#define MIC_MASTER_INT_ENAB 0x08
+#define MIC_STATUS_HIGH 0x10
+#define MIC_IGN_INTACK 0x20
+
+#define MIC_NO_RESET 0x00
+#define MIC_CH_A_RESET 0x40
+#define MIC_CH_B_RESET 0x80
+#define MIC_HARD_RESET 0xc0
+
+
+/* WR10: AUX2_CTRL_REG "A2CR" */
+
+#define A2CR_SYNC_6 0x01
+#define A2CR_LOOP_MODE 0x02
+#define A2CR_ABORT_ON_UNDERRUN 0x04
+#define A2CR_MARK_IDLE 0x08
+#define A2CR_GO_ACTIVE_ON_POLL 0x10
+
+#define A2CR_CODING_MASK 0x60
+#define A2CR_CODING_NRZ 0x00
+#define A2CR_CODING_NRZI 0x20
+#define A2CR_CODING_FM1 0x40
+#define A2CR_CODING_FM0 0x60
+
+#define A2CR_PRESET_CRC_1 0x80
+
+
+/* WR11: CLK_CTRL_REG "CCR" */
+
+#define CCR_TRxCOUT_MASK 0x03
+#define CCR_TRxCOUT_XTAL 0x00
+#define CCR_TRxCOUT_TXCLK 0x01
+#define CCR_TRxCOUT_BRG 0x02
+#define CCR_TRxCOUT_DPLL 0x03
+
+#define CCR_TRxC_OUTPUT 0x04
+
+#define CCR_TXCLK_MASK 0x18
+#define CCR_TXCLK_RTxC 0x00
+#define CCR_TXCLK_TRxC 0x08
+#define CCR_TXCLK_BRG 0x10
+#define CCR_TXCLK_DPLL 0x18
+
+#define CCR_RXCLK_MASK 0x60
+#define CCR_RXCLK_RTxC 0x00
+#define CCR_RXCLK_TRxC 0x20
+#define CCR_RXCLK_BRG 0x40
+#define CCR_RXCLK_DPLL 0x60
+
+#define CCR_RTxC_XTAL 0x80
+
+
+/* WR14: DPLL_CTRL_REG "DCR" */
+
+#define DCR_BRG_ENAB 0x01
+#define DCR_BRG_USE_PCLK 0x02
+#define DCR_DTRREQ_IS_REQ 0x04
+#define DCR_AUTO_ECHO 0x08
+#define DCR_LOCAL_LOOPBACK 0x10
+
+#define DCR_DPLL_EDGE_SEARCH 0x20
+#define DCR_DPLL_ERR_RESET 0x40
+#define DCR_DPLL_DISAB 0x60
+#define DCR_DPLL_CLK_BRG 0x80
+#define DCR_DPLL_CLK_RTxC 0xa0
+#define DCR_DPLL_FM 0xc0
+#define DCR_DPLL_NRZI 0xe0
+
+
+/* WR15: INT_CTRL_REG "ICR" */
+
+#define ICR_OPTIONREG_SELECT 0x01
+#define ICR_ENAB_BRG_ZERO_INT 0x02
+#define ICR_USE_FS_FIFO 0x04
+#define ICR_ENAB_DCD_INT 0x08
+#define ICR_ENAB_SYNC_INT 0x10
+#define ICR_ENAB_CTS_INT 0x20
+#define ICR_ENAB_UNDERRUN_INT 0x40
+#define ICR_ENAB_BREAK_INT 0x80
+
+
+/* RR0: STATUS_REG "SR" */
+
+#define SR_CHAR_AVAIL 0x01
+#define SR_BRG_ZERO 0x02
+#define SR_TX_BUF_EMPTY 0x04
+#define SR_DCD 0x08
+#define SR_SYNC_ABORT 0x10
+#define SR_CTS 0x20
+#define SR_TX_UNDERRUN 0x40
+#define SR_BREAK 0x80
+
+
+/* RR1: SPCOND_STATUS_REG "SCSR" */
+
+#define SCSR_ALL_SENT 0x01
+#define SCSR_RESIDUAL_MASK 0x0e
+#define SCSR_PARITY_ERR 0x10
+#define SCSR_RX_OVERRUN 0x20
+#define SCSR_CRC_FRAME_ERR 0x40
+#define SCSR_END_OF_FRAME 0x80
+
+
+/* RR3: INT_PENDING_REG "IPR" */
+
+#define IPR_B_EXTSTAT 0x01
+#define IPR_B_TX 0x02
+#define IPR_B_RX 0x04
+#define IPR_A_EXTSTAT 0x08
+#define IPR_A_TX 0x10
+#define IPR_A_RX 0x20
+
+
+/* RR7: FS_FIFO_HIGH_REG "FFHR" */
+
+#define FFHR_CNT_MASK 0x3f
+#define FFHR_IS_FROM_FIFO 0x40
+#define FFHR_FIFO_OVERRUN 0x80
+
+
+/* RR10: DPLL_STATUS_REG "DSR" */
+
+#define DSR_ON_LOOP 0x02
+#define DSR_ON_LOOP_SENDING 0x10
+#define DSR_TWO_CLK_MISSING 0x40
+#define DSR_ONE_CLK_MISSING 0x80
+
+/***********************************************************************/
+/* */
+/* Register Access */
+/* */
+/***********************************************************************/
+
+
+/* The SCC needs 3.5 PCLK cycles recovery time between to register
+ * accesses. PCLK runs with 8 MHz on an Atari, so this delay is 3.5 *
+ * 125 ns = 437.5 ns. This is too short for udelay().
+ * 10/16/95: A tstb mfp.par_dt_reg takes 600ns (sure?) and thus should be
+ * quite right
+ */
+
+#define scc_reg_delay() \
+ do { \
+ if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147) \
+ __asm__ __volatile__ ( " nop; nop"); \
+ else if (MACH_IS_ATARI) \
+ __asm__ __volatile__ ( "tstb %0" : : "g" (*_scc_del) : "cc" );\
+ } while (0)
+
+extern unsigned char scc_shadow[2][16];
+
+/* The following functions should relax the somehow complicated
+ * register access of the SCC. _SCCwrite() stores all written values
+ * (except for WR0 and WR8) in shadow registers for later recall. This
+ * removes the burden of remembering written values as needed. The
+ * extra work of storing the value doesn't count, since a delay is
+ * needed after a SCC access anyway. Additionally, _SCCwrite() manages
+ * writes to WR0 and WR8 differently, because these can be accessed
+ * directly with less overhead. Another special case are WR7 and WR7'.
+ * _SCCwrite automatically checks what of this registers is selected
+ * and changes b0 of WR15 if needed.
+ *
+ * _SCCread() for standard read registers is straightforward, except
+ * for RR2 (split into two "virtual" registers: one for the value
+ * written to WR2 (from the shadow) and one for the vector including
+ * status from RR2, Ch. B) and RR3. The latter must be read from
+ * Channel A, because it reads as all zeros on Ch. B. RR0 and RR8 can
+ * be accessed directly as before.
+ *
+ * The two inline function contain complicated switch statements. But
+ * I rely on regno and final_delay being constants, so gcc can reduce
+ * the whole stuff to just some assembler statements.
+ *
+ * _SCCwrite and _SCCread aren't intended to be used directly under
+ * normal circumstances. The macros SCCread[_ND] and SCCwrite[_ND] are
+ * for that purpose. They assume that a local variable 'port' is
+ * declared and pointing to the port's scc_struct entry. The
+ * variants with "_NB" appended should be used if no other SCC
+ * accesses follow immediatly (within 0.5 usecs). They just skip the
+ * final delay nops.
+ *
+ * Please note that accesses to SCC registers should only take place
+ * when interrupts are turned off (at least if SCC interrupts are
+ * enabled). Otherwise, an interrupt could interfere with the
+ * two-stage accessing process.
+ *
+ */
+
+
+static __inline__ void _SCCwrite(
+ struct scc_port *port,
+ unsigned char *shadow,
+ volatile unsigned char *_scc_del,
+ int regno,
+ unsigned char val, int final_delay )
+{
+ switch( regno ) {
+
+ case COMMAND_REG:
+ /* WR0 can be written directly without pointing */
+ *port->ctrlp = val;
+ break;
+
+ case SYNC_CHAR_REG:
+ /* For WR7, first set b0 of WR15 to 0, if needed */
+ if (shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT) {
+ *port->ctrlp = 15;
+ shadow[INT_CTRL_REG] &= ~ICR_OPTIONREG_SELECT;
+ scc_reg_delay();
+ *port->ctrlp = shadow[INT_CTRL_REG];
+ scc_reg_delay();
+ }
+ goto normal_case;
+
+ case SDLC_OPTION_REG:
+ /* For WR7', first set b0 of WR15 to 1, if needed */
+ if (!(shadow[INT_CTRL_REG] & ICR_OPTIONREG_SELECT)) {
+ *port->ctrlp = 15;
+ shadow[INT_CTRL_REG] |= ICR_OPTIONREG_SELECT;
+ scc_reg_delay();
+ *port->ctrlp = shadow[INT_CTRL_REG];
+ scc_reg_delay();
+ }
+ *port->ctrlp = 7;
+ shadow[8] = val; /* WR7' shadowed at WR8 */
+ scc_reg_delay();
+ *port->ctrlp = val;
+ break;
+
+ case TX_DATA_REG: /* WR8 */
+ /* TX_DATA_REG can be accessed directly on some h/w */
+ if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)
+ {
+ *port->ctrlp = regno;
+ scc_reg_delay();
+ *port->ctrlp = val;
+ }
+ else
+ *port->datap = val;
+ break;
+
+ case MASTER_INT_CTRL:
+ *port->ctrlp = regno;
+ val &= 0x3f; /* bits 6..7 are the reset commands */
+ scc_shadow[0][regno] = val;
+ scc_reg_delay();
+ *port->ctrlp = val;
+ break;
+
+ case DPLL_CTRL_REG:
+ *port->ctrlp = regno;
+ val &= 0x1f; /* bits 5..7 are the DPLL commands */
+ shadow[regno] = val;
+ scc_reg_delay();
+ *port->ctrlp = val;
+ break;
+
+ case 1 ... 6:
+ case 10 ... 13:
+ case 15:
+ normal_case:
+ *port->ctrlp = regno;
+ shadow[regno] = val;
+ scc_reg_delay();
+ *port->ctrlp = val;
+ break;
+
+ default:
+ printk( "Bad SCC write access to WR%d\n", regno );
+ break;
+
+ }
+
+ if (final_delay)
+ scc_reg_delay();
+}
+
+
+static __inline__ unsigned char _SCCread(
+ struct scc_port *port,
+ unsigned char *shadow,
+ volatile unsigned char *_scc_del,
+ int regno, int final_delay )
+{
+ unsigned char rv;
+
+ switch( regno ) {
+
+ /* --- real read registers --- */
+ case STATUS_REG:
+ rv = *port->ctrlp;
+ break;
+
+ case INT_PENDING_REG:
+ /* RR3: read only from Channel A! */
+ port = port->port_a;
+ goto normal_case;
+
+ case RX_DATA_REG:
+ /* RR8 can be accessed directly on some h/w */
+ if (MACH_IS_MVME16x || MACH_IS_BVME6000 || MACH_IS_MVME147)
+ {
+ *port->ctrlp = 8;
+ scc_reg_delay();
+ rv = *port->ctrlp;
+ }
+ else
+ rv = *port->datap;
+ break;
+
+ case CURR_VECTOR_REG:
+ /* RR2 (vector including status) from Ch. B */
+ port = port->port_b;
+ goto normal_case;
+
+ /* --- reading write registers: access the shadow --- */
+ case 1 ... 7:
+ case 10 ... 15:
+ return shadow[regno]; /* no final delay! */
+
+ /* WR7' is special, because it is shadowed at the place of WR8 */
+ case SDLC_OPTION_REG:
+ return shadow[8]; /* no final delay! */
+
+ /* WR9 is special too, because it is common for both channels */
+ case MASTER_INT_CTRL:
+ return scc_shadow[0][9]; /* no final delay! */
+
+ default:
+ printk( "Bad SCC read access to %cR%d\n", (regno & 16) ? 'R' : 'W',
+ regno & ~16 );
+ break;
+
+ case SPCOND_STATUS_REG:
+ case FS_FIFO_LOW_REG:
+ case FS_FIFO_HIGH_REG:
+ case DPLL_STATUS_REG:
+ normal_case:
+ *port->ctrlp = regno & 0x0f;
+ scc_reg_delay();
+ rv = *port->ctrlp;
+ break;
+
+ }
+
+ if (final_delay)
+ scc_reg_delay();
+ return rv;
+}
+
+#define SCC_ACCESS_INIT(port) \
+ unsigned char *_scc_shadow = &scc_shadow[port->channel][0]
+
+#define SCCwrite(reg,val) _SCCwrite(port,_scc_shadow,scc_del,(reg),(val),1)
+#define SCCwrite_NB(reg,val) _SCCwrite(port,_scc_shadow,scc_del,(reg),(val),0)
+#define SCCread(reg) _SCCread(port,_scc_shadow,scc_del,(reg),1)
+#define SCCread_NB(reg) _SCCread(port,_scc_shadow,scc_del,(reg),0)
+
+#define SCCmod(reg,and,or) SCCwrite((reg),(SCCread(reg)&(and))|(or))
+
+#endif /* _SCC_H */
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index 5142c8495..885b236fd 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -43,6 +43,7 @@
#include <linux/tty.h>
#include <linux/interrupt.h>
#include <linux/serial.h>
+#include <linux/serialP.h>
#include <linux/string.h>
#include <linux/fcntl.h>
#include <linux/ptrace.h>
@@ -57,6 +58,8 @@
#include <asm/segment.h>
#include <asm/bitops.h>
#include <asm/mvme16xhw.h>
+#include <asm/bootinfo.h>
+#include <asm/setup.h>
#include <linux/types.h>
#include <linux/kernel.h>
@@ -144,7 +147,7 @@ static struct termios *serial_termios_locked[NR_PORTS];
* memory if large numbers of serial ports are open.
*/
static unsigned char *tmp_buf = 0;
-static struct semaphore tmp_buf_sem = MUTEX;
+DECLARE_MUTEX(tmp_buf_sem);
/*
* This is used to look up the divisor speeds and the timeouts
@@ -2501,8 +2504,8 @@ scrn[1] = '\0';
info->tqueue.data = info;
info->callout_termios =cy_callout_driver.init_termios;
info->normal_termios = cy_serial_driver.init_termios;
- info->open_wait = 0;
- info->close_wait = 0;
+ init_waitqueue_head(&info->open_wait);
+ init_waitqueue_head(&info->close_wait);
/* info->session */
/* info->pgrp */
/*** !!!!!!!! this may expose new bugs !!!!!!!!! *********/
@@ -2728,7 +2731,7 @@ void console_setup(char *str, int *ints)
* that serial167_init() doesn't leave the chip non-functional.
*/
-void serial167_write(struct console *co, const char *str, unsigned count)
+void serial167_console_write(struct console *co, const char *str, unsigned count)
{
volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
unsigned long flags;
@@ -2788,6 +2791,95 @@ void serial167_write(struct console *co, const char *str, unsigned count)
restore_flags(flags);
}
+/* This is a hack; if there are multiple chars waiting in the chip we
+ * discard all but the last one, and return that. The cd2401 is not really
+ * designed to be driven in polled mode.
+ */
+
+int serial167_console_wait_key(struct console *co)
+{
+ volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
+ unsigned long flags;
+ volatile u_char sink;
+ u_char ier;
+ int port;
+ int keypress = 0;
+
+ save_flags(flags); cli();
+
+ /* Ensure receiver is enabled! */
+
+ port = 0;
+ base_addr[CyCAR] = (u_char)port;
+ while (base_addr[CyCCR])
+ ;
+ base_addr[CyCCR] = CyENB_RCVR;
+ ier = base_addr[CyIER];
+ base_addr[CyIER] = CyRxData;
+
+ while (!keypress) {
+ if (pcc2chip[PccSCCRICR] & 0x20)
+ {
+ /* We have an Rx int. Acknowledge it */
+ sink = pcc2chip[PccRPIACKR];
+ if ((base_addr[CyLICR] >> 2) == port) {
+ int cnt = base_addr[CyRFOC];
+ while (cnt-- > 0)
+ {
+ keypress = base_addr[CyRDR];
+ }
+ base_addr[CyREOIR] = 0;
+ }
+ else
+ base_addr[CyREOIR] = CyNOTRANS;
+ }
+ }
+
+ base_addr[CyIER] = ier;
+
+ restore_flags(flags);
+
+ return keypress;
+}
+
+
+static kdev_t serial167_console_device(struct console *c)
+{
+ return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+
+static int __init serial167_console_setup(struct console *co, char *options)
+{
+ return 0;
+}
+
+
+static struct console sercons = {
+ "ttyS",
+ serial167_console_write,
+ NULL,
+ serial167_console_device,
+ serial167_console_wait_key,
+ NULL,
+ serial167_console_setup,
+ CON_PRINTBUFFER,
+ -1,
+ 0,
+ NULL
+};
+
+
+void __init serial167_console_init(void)
+{
+ if (vme_brdtype == VME_TYPE_MVME166 ||
+ vme_brdtype == VME_TYPE_MVME167 ||
+ vme_brdtype == VME_TYPE_MVME177) {
+ mvme167_serial_console_setup(0);
+ register_console(&sercons);
+ }
+}
+
#ifdef CONFIG_REMOTE_DEBUG
void putDebugChar (int c)
{
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index c726f745c..b4194bb9b 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -128,6 +128,14 @@ static int tty_fasync(int fd, struct file * filp, int on);
#ifdef CONFIG_SX
extern int sx_init (void);
#endif
+#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC)
+extern int vme_scc_init (void);
+extern long vme_scc_console_init(void);
+#endif
+#ifdef CONFIG_SERIAL167
+extern int serial167_init(void);
+extern long serial167_console_init(void);
+#endif
#ifdef CONFIG_8xx
extern console_8xx_init(void);
extern int rs_8xx_init(void);
@@ -2090,9 +2098,15 @@ void __init console_init(void)
#ifdef CONFIG_SERIAL_CONSOLE
#ifdef CONFIG_8xx
console_8xx_init();
-#else
+#elif defined(CONFIG_SERIAL)
serial_console_init();
#endif /* CONFIG_8xx */
+#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC)
+ vme_scc_console_init();
+#endif
+#if defined(CONFIG_SERIAL167)
+ serial167_console_init();
+#endif
#endif
}
@@ -2176,6 +2190,9 @@ void __init tty_init(void)
#ifdef CONFIG_SERIAL
rs_init();
#endif
+#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_BVME6000_SCC) || defined(CONFIG_MVME147_SCC)
+ vme_scc_init();
+#endif
#ifdef CONFIG_COMPUTONE
ip2_init();
#endif
@@ -2185,7 +2202,7 @@ void __init tty_init(void)
#ifdef CONFIG_ROCKETPORT
rp_init();
#endif
-#ifdef CONFIG_MVME16x
+#ifdef CONFIG_SERIAL167
serial167_init();
#endif
#ifdef CONFIG_CYCLADES
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
new file mode 100644
index 000000000..15232f832
--- /dev/null
+++ b/drivers/char/vme_scc.c
@@ -0,0 +1,1136 @@
+/*
+ * drivers/char/vme_scc.c: MVME147, MVME162, BVME6000 SCC serial ports
+ * implementation.
+ * Copyright 1999 Richard Hirst <richard@sleepie.demon.co.uk>
+ *
+ * Based on atari_SCC.c which was
+ * Copyright 1994-95 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
+ * Partially based on PC-Linux serial.c by Linus Torvalds and Theodore Ts'o
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/kdev_t.h>
+#include <asm/io.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/mm.h>
+#include <linux/serial.h>
+#include <linux/fcntl.h>
+#include <linux/major.h>
+#include <linux/delay.h>
+#include <linux/tqueue.h>
+#include <linux/version.h>
+#include <linux/malloc.h>
+#include <linux/miscdevice.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <asm/setup.h>
+#include <asm/bootinfo.h>
+
+#ifdef CONFIG_MVME147_SCC
+#include <asm/mvme147hw.h>
+#endif
+#ifdef CONFIG_MVME162_SCC
+#include <asm/mvme16xhw.h>
+#endif
+#ifdef CONFIG_BVME6000_SCC
+#include <asm/bvme6000hw.h>
+#endif
+
+#include "generic_serial.h"
+#include "scc.h"
+
+
+#define CHANNEL_A 0
+#define CHANNEL_B 1
+
+#define SCC_MINOR_BASE 64
+
+/* Shadows for all SCC write registers */
+static unsigned char scc_shadow[2][16];
+
+/* Location to access for SCC register access delay */
+static volatile unsigned char *scc_del = NULL;
+
+/* To keep track of STATUS_REG state for detection of Ext/Status int source */
+static unsigned char scc_last_status_reg[2];
+
+/***************************** Prototypes *****************************/
+
+/* Function prototypes */
+static void scc_disable_tx_interrupts(void * ptr);
+static void scc_enable_tx_interrupts(void * ptr);
+static void scc_disable_rx_interrupts(void * ptr);
+static void scc_enable_rx_interrupts(void * ptr);
+static int scc_get_CD(void * ptr);
+static void scc_shutdown_port(void * ptr);
+static void scc_set_real_termios(void *ptr);
+static void scc_hungup(void *ptr);
+static void scc_close(void *ptr);
+static int scc_chars_in_buffer(void * ptr);
+static int scc_open(struct tty_struct * tty, struct file * filp);
+static int scc_ioctl(struct tty_struct * tty, struct file * filp,
+ unsigned int cmd, unsigned long arg);
+static void scc_throttle(struct tty_struct *tty);
+static void scc_unthrottle(struct tty_struct *tty);
+static void scc_tx_int(int irq, void *data, struct pt_regs *fp);
+static void scc_rx_int(int irq, void *data, struct pt_regs *fp);
+static void scc_stat_int(int irq, void *data, struct pt_regs *fp);
+static void scc_spcond_int(int irq, void *data, struct pt_regs *fp);
+static void scc_setsignals(struct scc_port *port, int dtr, int rts);
+static void scc_break_ctl(struct tty_struct *tty, int break_state);
+
+static struct tty_driver scc_driver, scc_callout_driver;
+
+static struct tty_struct *scc_table[2] = { NULL, };
+static struct termios * scc_termios[2];
+static struct termios * scc_termios_locked[2];
+struct scc_port scc_ports[2];
+
+int scc_refcount;
+int scc_initialized = 0;
+
+/*---------------------------------------------------------------------------
+ * Interface from generic_serial.c back here
+ *--------------------------------------------------------------------------*/
+
+static struct real_driver scc_real_driver = {
+ scc_disable_tx_interrupts,
+ scc_enable_tx_interrupts,
+ scc_disable_rx_interrupts,
+ scc_enable_rx_interrupts,
+ scc_get_CD,
+ scc_shutdown_port,
+ scc_set_real_termios,
+ scc_chars_in_buffer,
+ scc_close,
+ scc_hungup,
+ NULL
+};
+
+
+/*----------------------------------------------------------------------------
+ * vme_scc_init() and support functions
+ *---------------------------------------------------------------------------*/
+
+static int scc_init_drivers(void)
+{
+ int error;
+
+ memset(&scc_driver, 0, sizeof(scc_driver));
+ scc_driver.magic = TTY_DRIVER_MAGIC;
+ scc_driver.driver_name = "scc";
+ scc_driver.name = "ttyS";
+ scc_driver.major = TTY_MAJOR;
+ scc_driver.minor_start = SCC_MINOR_BASE;
+ scc_driver.num = 2;
+ scc_driver.type = TTY_DRIVER_TYPE_SERIAL;
+ scc_driver.subtype = SERIAL_TYPE_NORMAL;
+ scc_driver.init_termios = tty_std_termios;
+ scc_driver.init_termios.c_cflag =
+ B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+ scc_driver.flags = TTY_DRIVER_REAL_RAW;
+ scc_driver.refcount = &scc_refcount;
+ scc_driver.table = scc_table;
+ scc_driver.termios = scc_termios;
+ scc_driver.termios_locked = scc_termios_locked;
+
+ scc_driver.open = scc_open;
+ scc_driver.close = gs_close;
+ scc_driver.write = gs_write;
+ scc_driver.put_char = gs_put_char;
+ scc_driver.flush_chars = gs_flush_chars;
+ scc_driver.write_room = gs_write_room;
+ scc_driver.chars_in_buffer = gs_chars_in_buffer;
+ scc_driver.flush_buffer = gs_flush_buffer;
+ scc_driver.ioctl = scc_ioctl;
+ scc_driver.throttle = scc_throttle;
+ scc_driver.unthrottle = scc_unthrottle;
+ scc_driver.set_termios = gs_set_termios;
+ scc_driver.stop = gs_stop;
+ scc_driver.start = gs_start;
+ scc_driver.hangup = gs_hangup;
+ scc_driver.break_ctl = scc_break_ctl;
+
+ scc_callout_driver = scc_driver;
+ scc_callout_driver.name = "cua";
+ scc_callout_driver.major = TTYAUX_MAJOR;
+ scc_callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+
+ if ((error = tty_register_driver(&scc_driver))) {
+ printk(KERN_ERR "scc: Couldn't register scc driver, error = %d\n",
+ error);
+ return 1;
+ }
+ if ((error = tty_register_driver(&scc_callout_driver))) {
+ tty_unregister_driver(&scc_driver);
+ printk(KERN_ERR "scc: Couldn't register scc callout driver, error = %d\n",
+ error);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/* ports[] array is indexed by line no (i.e. [0] for ttyS0, [1] for ttyS1).
+ */
+
+static void scc_init_portstructs(void)
+{
+ struct scc_port *port;
+ int i;
+
+ for (i = 0; i < 2; i++) {
+ port = scc_ports + i;
+ port->gs.callout_termios = tty_std_termios;
+ port->gs.normal_termios = tty_std_termios;
+ port->gs.magic = SCC_MAGIC;
+ port->gs.close_delay = HZ/2;
+ port->gs.closing_wait = 30 * HZ;
+ port->gs.rd = &scc_real_driver;
+#ifdef NEW_WRITE_LOCKING
+ port->gs.port_write_sem = MUTEX;
+#endif
+ init_waitqueue_head(&port->gs.open_wait);
+ init_waitqueue_head(&port->gs.close_wait);
+ }
+}
+
+
+#ifdef CONFIG_MVME147_SCC
+static int mvme147_scc_init(void)
+{
+ struct scc_port *port;
+
+ printk("SCC: MVME147 Serial Driver\n");
+ /* Init channel A */
+ port = &scc_ports[0];
+ port->channel = CHANNEL_A;
+ port->ctrlp = (volatile unsigned char *)M147_SCC_A_ADDR;
+ port->datap = port->ctrlp + 1;
+ port->port_a = &scc_ports[0];
+ port->port_b = &scc_ports[1];
+ request_irq(MVME147_IRQ_SCCA_TX, scc_tx_int, SA_INTERRUPT,
+ "SCC-A TX", port);
+ request_irq(MVME147_IRQ_SCCA_STAT, scc_stat_int, SA_INTERRUPT,
+ "SCC-A status", port);
+ request_irq(MVME147_IRQ_SCCA_RX, scc_rx_int, SA_INTERRUPT,
+ "SCC-A RX", port);
+ request_irq(MVME147_IRQ_SCCA_SPCOND, scc_spcond_int, SA_INTERRUPT,
+ "SCC-A special cond", port);
+ {
+ SCC_ACCESS_INIT(port);
+
+ /* disable interrupts for this channel */
+ SCCwrite(INT_AND_DMA_REG, 0);
+ /* Set the interrupt vector */
+ SCCwrite(INT_VECTOR_REG, MVME147_IRQ_SCC_BASE);
+ /* Interrupt parameters: vector includes status, status low */
+ SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
+ SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
+ }
+
+ /* Init channel B */
+ port = &scc_ports[1];
+ port->channel = CHANNEL_B;
+ port->ctrlp = (volatile unsigned char *)M147_SCC_B_ADDR;
+ port->datap = port->ctrlp + 1;
+ port->port_a = &scc_ports[0];
+ port->port_b = &scc_ports[1];
+ request_irq(MVME147_IRQ_SCCB_TX, scc_tx_int, SA_INTERRUPT,
+ "SCC-B TX", port);
+ request_irq(MVME147_IRQ_SCCB_STAT, scc_stat_int, SA_INTERRUPT,
+ "SCC-B status", port);
+ request_irq(MVME147_IRQ_SCCB_RX, scc_rx_int, SA_INTERRUPT,
+ "SCC-B RX", port);
+ request_irq(MVME147_IRQ_SCCB_SPCOND, scc_spcond_int, SA_INTERRUPT,
+ "SCC-B special cond", port);
+ {
+ SCC_ACCESS_INIT(port);
+
+ /* disable interrupts for this channel */
+ SCCwrite(INT_AND_DMA_REG, 0);
+ }
+
+ /* Ensure interrupts are enabled in the PCC chip */
+ m147_pcc->serial_cntrl=PCC_LEVEL_SERIAL|PCC_INT_ENAB;
+
+ /* Initialise the tty driver structures and register */
+ scc_init_portstructs();
+ scc_init_drivers();
+
+ return 0;
+}
+#endif
+
+
+#ifdef CONFIG_MVME162_SCC
+static int mvme162_scc_init(void)
+{
+ struct scc_port *port;
+
+ if (!(mvme16x_config & MVME16x_CONFIG_GOT_SCCA))
+ return (-ENODEV);
+
+ printk("SCC: MVME162 Serial Driver\n");
+ /* Init channel A */
+ port = &scc_ports[0];
+ port->channel = CHANNEL_A;
+ port->ctrlp = (volatile unsigned char *)MVME_SCC_A_ADDR;
+ port->datap = port->ctrlp + 2;
+ port->port_a = &scc_ports[0];
+ port->port_b = &scc_ports[1];
+ request_irq(MVME162_IRQ_SCCA_TX, scc_tx_int, SA_INTERRUPT,
+ "SCC-A TX", port);
+ request_irq(MVME162_IRQ_SCCA_STAT, scc_stat_int, SA_INTERRUPT,
+ "SCC-A status", port);
+ request_irq(MVME162_IRQ_SCCA_RX, scc_rx_int, SA_INTERRUPT,
+ "SCC-A RX", port);
+ request_irq(MVME162_IRQ_SCCA_SPCOND, scc_spcond_int, SA_INTERRUPT,
+ "SCC-A special cond", port);
+ {
+ SCC_ACCESS_INIT(port);
+
+ /* disable interrupts for this channel */
+ SCCwrite(INT_AND_DMA_REG, 0);
+ /* Set the interrupt vector */
+ SCCwrite(INT_VECTOR_REG, MVME162_IRQ_SCC_BASE);
+ /* Interrupt parameters: vector includes status, status low */
+ SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
+ SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
+ }
+
+ /* Init channel B */
+ port = &scc_ports[1];
+ port->channel = CHANNEL_B;
+ port->ctrlp = (volatile unsigned char *)MVME_SCC_B_ADDR;
+ port->datap = port->ctrlp + 2;
+ port->port_a = &scc_ports[0];
+ port->port_b = &scc_ports[1];
+ request_irq(MVME162_IRQ_SCCB_TX, scc_tx_int, SA_INTERRUPT,
+ "SCC-B TX", port);
+ request_irq(MVME162_IRQ_SCCB_STAT, scc_stat_int, SA_INTERRUPT,
+ "SCC-B status", port);
+ request_irq(MVME162_IRQ_SCCB_RX, scc_rx_int, SA_INTERRUPT,
+ "SCC-B RX", port);
+ request_irq(MVME162_IRQ_SCCB_SPCOND, scc_spcond_int, SA_INTERRUPT,
+ "SCC-B special cond", port);
+
+ {
+ SCC_ACCESS_INIT(port); /* Either channel will do */
+
+ /* disable interrupts for this channel */
+ SCCwrite(INT_AND_DMA_REG, 0);
+ }
+
+ /* Ensure interrupts are enabled in the MC2 chip */
+ *(volatile char *)0xfff4201d = 0x14;
+
+ /* Initialise the tty driver structures and register */
+ scc_init_portstructs();
+ scc_init_drivers();
+
+ return 0;
+}
+#endif
+
+
+#ifdef CONFIG_BVME6000_SCC
+static int bvme6000_scc_init(void)
+{
+ struct scc_port *port;
+
+ printk("SCC: BVME6000 Serial Driver\n");
+ /* Init channel A */
+ port = &scc_ports[0];
+ port->channel = CHANNEL_A;
+ port->ctrlp = (volatile unsigned char *)BVME_SCC_A_ADDR;
+ port->datap = port->ctrlp + 4;
+ port->port_a = &scc_ports[0];
+ port->port_b = &scc_ports[1];
+ request_irq(BVME_IRQ_SCCA_TX, scc_tx_int, SA_INTERRUPT,
+ "SCC-A TX", port);
+ request_irq(BVME_IRQ_SCCA_STAT, scc_stat_int, SA_INTERRUPT,
+ "SCC-A status", port);
+ request_irq(BVME_IRQ_SCCA_RX, scc_rx_int, SA_INTERRUPT,
+ "SCC-A RX", port);
+ request_irq(BVME_IRQ_SCCA_SPCOND, scc_spcond_int, SA_INTERRUPT,
+ "SCC-A special cond", port);
+ {
+ SCC_ACCESS_INIT(port);
+
+ /* disable interrupts for this channel */
+ SCCwrite(INT_AND_DMA_REG, 0);
+ /* Set the interrupt vector */
+ SCCwrite(INT_VECTOR_REG, BVME_IRQ_SCC_BASE);
+ /* Interrupt parameters: vector includes status, status low */
+ SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
+ SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
+ }
+
+ /* Init channel B */
+ port = &scc_ports[1];
+ port->channel = CHANNEL_B;
+ port->ctrlp = (volatile unsigned char *)BVME_SCC_B_ADDR;
+ port->datap = port->ctrlp + 4;
+ port->port_a = &scc_ports[0];
+ port->port_b = &scc_ports[1];
+ request_irq(BVME_IRQ_SCCB_TX, scc_tx_int, SA_INTERRUPT,
+ "SCC-B TX", port);
+ request_irq(BVME_IRQ_SCCB_STAT, scc_stat_int, SA_INTERRUPT,
+ "SCC-B status", port);
+ request_irq(BVME_IRQ_SCCB_RX, scc_rx_int, SA_INTERRUPT,
+ "SCC-B RX", port);
+ request_irq(BVME_IRQ_SCCB_SPCOND, scc_spcond_int, SA_INTERRUPT,
+ "SCC-B special cond", port);
+
+ {
+ SCC_ACCESS_INIT(port); /* Either channel will do */
+
+ /* disable interrupts for this channel */
+ SCCwrite(INT_AND_DMA_REG, 0);
+ }
+
+ /* Initialise the tty driver structures and register */
+ scc_init_portstructs();
+ scc_init_drivers();
+
+ return 0;
+}
+#endif
+
+
+int vme_scc_init(void)
+{
+ int res = -ENODEV;
+ static int called = 0;
+
+ if (called)
+ return res;
+ called = 1;
+#ifdef CONFIG_MVME147_SCC
+ if (MACH_IS_MVME147)
+ res = mvme147_scc_init();
+#endif
+#ifdef CONFIG_MVME162_SCC
+ if (MACH_IS_MVME16x)
+ res = mvme162_scc_init();
+#endif
+#ifdef CONFIG_BVME6000_SCC
+ if (MACH_IS_BVME6000)
+ res = bvme6000_scc_init();
+#endif
+ return res;
+}
+
+
+/*---------------------------------------------------------------------------
+ * Interrupt handlers
+ *--------------------------------------------------------------------------*/
+
+static void scc_rx_int(int irq, void *data, struct pt_regs *fp)
+{
+ unsigned char ch;
+ struct scc_port *port = data;
+ struct tty_struct *tty = port->gs.tty;
+ SCC_ACCESS_INIT(port);
+
+ ch = SCCread_NB(RX_DATA_REG);
+ if (!tty) {
+ printk ("scc_rx_int with NULL tty!\n");
+ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+ return;
+ }
+ if (tty->flip.count < TTY_FLIPBUF_SIZE) {
+ *tty->flip.char_buf_ptr = ch;
+ *tty->flip.flag_buf_ptr = 0;
+ tty->flip.flag_buf_ptr++;
+ tty->flip.char_buf_ptr++;
+ tty->flip.count++;
+ }
+
+ /* Check if another character is already ready; in that case, the
+ * spcond_int() function must be used, because this character may have an
+ * error condition that isn't signalled by the interrupt vector used!
+ */
+ if (SCCread(INT_PENDING_REG) &
+ (port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX)) {
+ scc_spcond_int (irq, data, fp);
+ return;
+ }
+
+ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+
+ tty_flip_buffer_push(tty);
+}
+
+
+static void scc_spcond_int(int irq, void *data, struct pt_regs *fp)
+{
+ struct scc_port *port = data;
+ struct tty_struct *tty = port->gs.tty;
+ unsigned char stat, ch, err;
+ int int_pending_mask = port->channel == CHANNEL_A ?
+ IPR_A_RX : IPR_B_RX;
+ SCC_ACCESS_INIT(port);
+
+ if (!tty) {
+ printk ("scc_spcond_int with NULL tty!\n");
+ SCCwrite(COMMAND_REG, CR_ERROR_RESET);
+ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+ return;
+ }
+ do {
+ stat = SCCread(SPCOND_STATUS_REG);
+ ch = SCCread_NB(RX_DATA_REG);
+
+ if (stat & SCSR_RX_OVERRUN)
+ err = TTY_OVERRUN;
+ else if (stat & SCSR_PARITY_ERR)
+ err = TTY_PARITY;
+ else if (stat & SCSR_CRC_FRAME_ERR)
+ err = TTY_FRAME;
+ else
+ err = 0;
+
+ if (tty->flip.count < TTY_FLIPBUF_SIZE) {
+ *tty->flip.char_buf_ptr = ch;
+ *tty->flip.flag_buf_ptr = err;
+ tty->flip.flag_buf_ptr++;
+ tty->flip.char_buf_ptr++;
+ tty->flip.count++;
+ }
+
+ /* ++TeSche: *All* errors have to be cleared manually,
+ * else the condition persists for the next chars
+ */
+ if (err)
+ SCCwrite(COMMAND_REG, CR_ERROR_RESET);
+
+ } while(SCCread(INT_PENDING_REG) & int_pending_mask);
+
+ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+
+ tty_flip_buffer_push(tty);
+}
+
+
+static void scc_tx_int(int irq, void *data, struct pt_regs *fp)
+{
+ struct scc_port *port = data;
+ SCC_ACCESS_INIT(port);
+
+ if (!port->gs.tty) {
+ printk ("scc_tx_int with NULL tty!\n");
+ SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
+ SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
+ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+ return;
+ }
+ while ((SCCread_NB(STATUS_REG) & SR_TX_BUF_EMPTY)) {
+ if (port->x_char) {
+ SCCwrite(TX_DATA_REG, port->x_char);
+ port->x_char = 0;
+ }
+ else if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped ||
+ port->gs.tty->hw_stopped)
+ break;
+ else {
+ SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]);
+ port->gs.xmit_tail = port->gs.xmit_tail & (SERIAL_XMIT_SIZE-1);
+ if (--port->gs.xmit_cnt <= 0)
+ break;
+ }
+ }
+ if ((port->gs.xmit_cnt <= 0) || port->gs.tty->stopped ||
+ port->gs.tty->hw_stopped) {
+ /* disable tx interrupts */
+ SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
+ SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET); /* disable tx_int on next tx underrun? */
+ port->gs.flags &= ~GS_TX_INTEN;
+ }
+ if (port->gs.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars) {
+ if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+ port->gs.tty->ldisc.write_wakeup)
+ (port->gs.tty->ldisc.write_wakeup)(port->gs.tty);
+ wake_up_interruptible(&port->gs.tty->write_wait);
+ }
+
+ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+}
+
+
+static void scc_stat_int(int irq, void *data, struct pt_regs *fp)
+{
+ struct scc_port *port = data;
+ unsigned channel = port->channel;
+ unsigned char last_sr, sr, changed;
+ SCC_ACCESS_INIT(port);
+
+ last_sr = scc_last_status_reg[channel];
+ sr = scc_last_status_reg[channel] = SCCread_NB(STATUS_REG);
+ changed = last_sr ^ sr;
+
+ if (changed & SR_DCD) {
+ port->c_dcd = !!(sr & SR_DCD);
+ if (!(port->gs.flags & ASYNC_CHECK_CD))
+ ; /* Don't report DCD changes */
+ else if (port->c_dcd) {
+ if (~(port->gs.flags & ASYNC_NORMAL_ACTIVE) ||
+ ~(port->gs.flags & ASYNC_CALLOUT_ACTIVE)) {
+ /* Are we blocking in open?*/
+ wake_up_interruptible(&port->gs.open_wait);
+ }
+ }
+ else {
+ if (!((port->gs.flags & ASYNC_CALLOUT_ACTIVE) &&
+ (port->gs.flags & ASYNC_CALLOUT_NOHUP))) {
+ if (port->gs.tty)
+ tty_hangup (port->gs.tty);
+ }
+ }
+ }
+ SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET);
+ SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
+}
+
+
+/*---------------------------------------------------------------------------
+ * generic_serial.c callback funtions
+ *--------------------------------------------------------------------------*/
+
+static void scc_disable_tx_interrupts(void *ptr)
+{
+ struct scc_port *port = ptr;
+ unsigned long flags;
+ SCC_ACCESS_INIT(port);
+
+ save_flags(flags);
+ cli();
+ SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
+ port->gs.flags &= ~GS_TX_INTEN;
+ restore_flags(flags);
+}
+
+
+static void scc_enable_tx_interrupts(void *ptr)
+{
+ struct scc_port *port = ptr;
+ unsigned long flags;
+ SCC_ACCESS_INIT(port);
+
+ save_flags(flags);
+ cli();
+ SCCmod(INT_AND_DMA_REG, 0xff, IDR_TX_INT_ENAB);
+ /* restart the transmitter */
+ scc_tx_int (0, port, 0);
+ restore_flags(flags);
+}
+
+
+static void scc_disable_rx_interrupts(void *ptr)
+{
+ struct scc_port *port = ptr;
+ unsigned long flags;
+ SCC_ACCESS_INIT(port);
+
+ save_flags(flags);
+ cli();
+ SCCmod(INT_AND_DMA_REG,
+ ~(IDR_RX_INT_MASK|IDR_PARERR_AS_SPCOND|IDR_EXTSTAT_INT_ENAB), 0);
+ restore_flags(flags);
+}
+
+
+static void scc_enable_rx_interrupts(void *ptr)
+{
+ struct scc_port *port = ptr;
+ unsigned long flags;
+ SCC_ACCESS_INIT(port);
+
+ save_flags(flags);
+ cli();
+ SCCmod(INT_AND_DMA_REG, 0xff,
+ IDR_EXTSTAT_INT_ENAB|IDR_PARERR_AS_SPCOND|IDR_RX_INT_ALL);
+ restore_flags(flags);
+}
+
+
+static int scc_get_CD(void *ptr)
+{
+ struct scc_port *port = ptr;
+ unsigned channel = port->channel;
+
+ return !!(scc_last_status_reg[channel] & SR_DCD);
+}
+
+
+static void scc_shutdown_port(void *ptr)
+{
+ struct scc_port *port = ptr;
+
+ port->gs.flags &= ~ GS_ACTIVE;
+ if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) {
+ scc_setsignals (port, 0, 0);
+ }
+}
+
+
+static void scc_set_real_termios (void *ptr)
+{
+ /* the SCC has char sizes 5,7,6,8 in that order! */
+ static int chsize_map[4] = { 0, 2, 1, 3 };
+ unsigned cflag, baud, chsize, channel, brgval = 0;
+ unsigned long flags;
+ struct scc_port *port = ptr;
+ SCC_ACCESS_INIT(port);
+
+ if (!port->gs.tty || !port->gs.tty->termios) return;
+
+ channel = port->channel;
+
+ if (channel == CHANNEL_A)
+ return; /* Settings controlled by boot PROM */
+
+ cflag = port->gs.tty->termios->c_cflag;
+ baud = port->gs.baud;
+ chsize = (cflag & CSIZE) >> 4;
+
+ if (baud == 0) {
+ /* speed == 0 -> drop DTR */
+ save_flags(flags);
+ cli();
+ SCCmod(TX_CTRL_REG, ~TCR_DTR, 0);
+ restore_flags(flags);
+ return;
+ }
+ else if ((MACH_IS_MVME16x && (baud < 50 || baud > 38400)) ||
+ (MACH_IS_MVME147 && (baud < 50 || baud > 19200)) ||
+ (MACH_IS_BVME6000 &&(baud < 50 || baud > 76800))) {
+ printk("SCC: Bad speed requested, %d\n", baud);
+ return;
+ }
+
+ if (cflag & CLOCAL)
+ port->gs.flags &= ~ASYNC_CHECK_CD;
+ else
+ port->gs.flags |= ASYNC_CHECK_CD;
+
+#ifdef CONFIG_MVME147_SCC
+ if (MACH_IS_MVME147)
+ brgval = (M147_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2;
+ else
+#endif
+#ifdef CONFIG_MVME162_SCC
+ if (MACH_IS_MVME16x)
+ brgval = (MVME_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2;
+ else
+#endif
+#ifdef CONFIG_BVME6000_SCC
+ if (MACH_IS_BVME6000)
+ brgval = (BVME_SCC_RTxC + baud/2) / (16 * 2 * baud) - 2;
+#endif
+ /* Now we have all parameters and can go to set them: */
+ save_flags(flags);
+ cli();
+
+ /* receiver's character size and auto-enables */
+ SCCmod(RX_CTRL_REG, ~(RCR_CHSIZE_MASK|RCR_AUTO_ENAB_MODE),
+ (chsize_map[chsize] << 6) |
+ ((cflag & CRTSCTS) ? RCR_AUTO_ENAB_MODE : 0));
+ /* parity and stop bits (both, Tx and Rx), clock mode never changes */
+ SCCmod (AUX1_CTRL_REG,
+ ~(A1CR_PARITY_MASK | A1CR_MODE_MASK),
+ ((cflag & PARENB
+ ? (cflag & PARODD ? A1CR_PARITY_ODD : A1CR_PARITY_EVEN)
+ : A1CR_PARITY_NONE)
+ | (cflag & CSTOPB ? A1CR_MODE_ASYNC_2 : A1CR_MODE_ASYNC_1)));
+ /* sender's character size, set DTR for valid baud rate */
+ SCCmod(TX_CTRL_REG, ~TCR_CHSIZE_MASK, chsize_map[chsize] << 5 | TCR_DTR);
+ /* clock sources never change */
+ /* disable BRG before changing the value */
+ SCCmod(DPLL_CTRL_REG, ~DCR_BRG_ENAB, 0);
+ /* BRG value */
+ SCCwrite(TIMER_LOW_REG, brgval & 0xff);
+ SCCwrite(TIMER_HIGH_REG, (brgval >> 8) & 0xff);
+ /* BRG enable, and clock source never changes */
+ SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB);
+
+ restore_flags(flags);
+}
+
+
+static int scc_chars_in_buffer (void *ptr)
+{
+ struct scc_port *port = ptr;
+ SCC_ACCESS_INIT(port);
+
+ return (SCCread (SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0 : 1;
+}
+
+
+static void scc_hungup(void *ptr)
+{
+ scc_disable_tx_interrupts(ptr);
+ scc_disable_rx_interrupts(ptr);
+ MOD_DEC_USE_COUNT;
+}
+
+
+static void scc_close(void *ptr)
+{
+ scc_disable_tx_interrupts(ptr);
+ scc_disable_rx_interrupts(ptr);
+}
+
+
+/*---------------------------------------------------------------------------
+ * Internal support functions
+ *--------------------------------------------------------------------------*/
+
+static void scc_setsignals(struct scc_port *port, int dtr, int rts)
+{
+ unsigned long flags;
+ unsigned char t;
+ SCC_ACCESS_INIT(port);
+
+ save_flags(flags);
+ t = SCCread(TX_CTRL_REG);
+ if (dtr >= 0) t = dtr? (t | TCR_DTR): (t & ~TCR_DTR);
+ if (rts >= 0) t = rts? (t | TCR_RTS): (t & ~TCR_RTS);
+ SCCwrite(TX_CTRL_REG, t);
+ restore_flags(flags);
+}
+
+
+static void scc_send_xchar(struct tty_struct *tty, char ch)
+{
+ struct scc_port *port = (struct scc_port *)tty->driver_data;
+
+ port->x_char = ch;
+ if (ch)
+ scc_enable_tx_interrupts(port);
+}
+
+
+/*---------------------------------------------------------------------------
+ * Driver entrypoints referenced from above
+ *--------------------------------------------------------------------------*/
+
+static int scc_open (struct tty_struct * tty, struct file * filp)
+{
+ int line = MINOR(tty->device) - SCC_MINOR_BASE;
+ int retval;
+ struct scc_port *port = &scc_ports[line];
+ int i, channel = port->channel;
+ unsigned long flags;
+ SCC_ACCESS_INIT(port);
+#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_MVME147_SCC)
+ static const struct {
+ unsigned reg, val;
+ } mvme_init_tab[] = {
+ /* Values for MVME162 and MVME147 */
+ /* no parity, 1 stop bit, async, 1:16 */
+ { AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 },
+ /* parity error is special cond, ints disabled, no DMA */
+ { INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
+ /* Rx 8 bits/char, no auto enable, Rx off */
+ { RX_CTRL_REG, RCR_CHSIZE_8 },
+ /* DTR off, Tx 8 bits/char, RTS off, Tx off */
+ { TX_CTRL_REG, TCR_CHSIZE_8 },
+ /* special features off */
+ { AUX2_CTRL_REG, 0 },
+ { CLK_CTRL_REG, CCR_RXCLK_BRG | CCR_TXCLK_BRG },
+ { DPLL_CTRL_REG, DCR_BRG_ENAB | DCR_BRG_USE_PCLK },
+ /* Start Rx */
+ { RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
+ /* Start Tx */
+ { TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
+ /* Ext/Stat ints: DCD only */
+ { INT_CTRL_REG, ICR_ENAB_DCD_INT },
+ /* Reset Ext/Stat ints */
+ { COMMAND_REG, CR_EXTSTAT_RESET },
+ /* ...again */
+ { COMMAND_REG, CR_EXTSTAT_RESET },
+ };
+#endif
+#if defined(CONFIG_BVME6000_SCC)
+ static const struct {
+ unsigned reg, val;
+ } bvme_init_tab[] = {
+ /* Values for BVME6000 */
+ /* no parity, 1 stop bit, async, 1:16 */
+ { AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 },
+ /* parity error is special cond, ints disabled, no DMA */
+ { INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
+ /* Rx 8 bits/char, no auto enable, Rx off */
+ { RX_CTRL_REG, RCR_CHSIZE_8 },
+ /* DTR off, Tx 8 bits/char, RTS off, Tx off */
+ { TX_CTRL_REG, TCR_CHSIZE_8 },
+ /* special features off */
+ { AUX2_CTRL_REG, 0 },
+ { CLK_CTRL_REG, CCR_RTxC_XTAL | CCR_RXCLK_BRG | CCR_TXCLK_BRG },
+ { DPLL_CTRL_REG, DCR_BRG_ENAB },
+ /* Start Rx */
+ { RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
+ /* Start Tx */
+ { TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
+ /* Ext/Stat ints: DCD only */
+ { INT_CTRL_REG, ICR_ENAB_DCD_INT },
+ /* Reset Ext/Stat ints */
+ { COMMAND_REG, CR_EXTSTAT_RESET },
+ /* ...again */
+ { COMMAND_REG, CR_EXTSTAT_RESET },
+ };
+#endif
+ if (!(port->gs.flags & ASYNC_INITIALIZED)) {
+ save_flags(flags);
+ cli();
+#if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC)
+ if (MACH_IS_MVME147 || MACH_IS_MVME16x) {
+ for (i=0; i<sizeof(mvme_init_tab)/sizeof(*mvme_init_tab); ++i)
+ SCCwrite(mvme_init_tab[i].reg, mvme_init_tab[i].val);
+ }
+#endif
+#if defined(CONFIG_BVME6000_SCC)
+ if (MACH_IS_BVME6000) {
+ for (i=0; i<sizeof(bvme_init_tab)/sizeof(*bvme_init_tab); ++i)
+ SCCwrite(bvme_init_tab[i].reg, bvme_init_tab[i].val);
+ }
+#endif
+
+ /* remember status register for detection of DCD and CTS changes */
+ scc_last_status_reg[channel] = SCCread(STATUS_REG);
+
+ port->c_dcd = 0; /* Prevent initial 1->0 interrupt */
+ scc_setsignals (port, 1,1);
+ restore_flags(flags);
+ }
+
+ tty->driver_data = port;
+ port->gs.tty = tty;
+ port->gs.count++;
+ retval = gs_init_port(&port->gs);
+ if (retval) {
+ port->gs.count--;
+ return retval;
+ }
+ port->gs.flags |= GS_ACTIVE;
+ if (port->gs.count == 1) {
+ MOD_INC_USE_COUNT;
+ }
+ retval = block_til_ready(port, filp);
+
+ if (retval) {
+ MOD_DEC_USE_COUNT;
+ port->gs.count--;
+ return retval;
+ }
+
+ if ((port->gs.count == 1) && (port->gs.flags & ASYNC_SPLIT_TERMIOS)) {
+ if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+ *tty->termios = port->gs.normal_termios;
+ else
+ *tty->termios = port->gs.callout_termios;
+ scc_set_real_termios (port);
+ }
+
+ port->gs.session = current->session;
+ port->gs.pgrp = current->pgrp;
+ port->c_dcd = scc_get_CD (port);
+
+ scc_enable_rx_interrupts(port);
+
+ return 0;
+}
+
+
+static void scc_throttle (struct tty_struct * tty)
+{
+ struct scc_port *port = (struct scc_port *)tty->driver_data;
+ unsigned long flags;
+ SCC_ACCESS_INIT(port);
+
+ if (tty->termios->c_cflag & CRTSCTS) {
+ save_flags(flags);
+ cli();
+ SCCmod(TX_CTRL_REG, ~TCR_RTS, 0);
+ restore_flags(flags);
+ }
+ if (I_IXOFF(tty))
+ scc_send_xchar(tty, STOP_CHAR(tty));
+}
+
+
+static void scc_unthrottle (struct tty_struct * tty)
+{
+ struct scc_port *port = (struct scc_port *)tty->driver_data;
+ unsigned long flags;
+ SCC_ACCESS_INIT(port);
+
+ if (tty->termios->c_cflag & CRTSCTS) {
+ save_flags(flags);
+ cli();
+ SCCmod(TX_CTRL_REG, 0xff, TCR_RTS);
+ restore_flags(flags);
+ }
+ if (I_IXOFF(tty))
+ scc_send_xchar(tty, START_CHAR(tty));
+}
+
+
+static int scc_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ return -ENOIOCTLCMD;
+}
+
+
+static void scc_break_ctl(struct tty_struct *tty, int break_state)
+{
+ struct scc_port *port = (struct scc_port *)tty->driver_data;
+ unsigned long flags;
+ SCC_ACCESS_INIT(port);
+
+ save_flags(flags);
+ cli();
+ SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK,
+ break_state ? TCR_SEND_BREAK : 0);
+ restore_flags(flags);
+}
+
+
+/*---------------------------------------------------------------------------
+ * Serial console stuff...
+ *--------------------------------------------------------------------------*/
+
+#define scc_delay() do { __asm__ __volatile__ (" nop; nop"); } while (0)
+
+static void scc_ch_write (char ch)
+{
+ volatile char *p = NULL;
+
+#ifdef CONFIG_MVME147_SCC
+ if (MACH_IS_MVME147)
+ p = (volatile char *)M147_SCC_A_ADDR;
+#endif
+#ifdef CONFIG_MVME162_SCC
+ if (MACH_IS_MVME16x)
+ p = (volatile char *)MVME_SCC_A_ADDR;
+#endif
+#ifdef CONFIG_BVME6000_SCC
+ if (MACH_IS_BVME6000)
+ p = (volatile char *)BVME_SCC_A_ADDR;
+#endif
+
+ do {
+ scc_delay();
+ }
+ while (!(*p & 4));
+ scc_delay();
+ *p = 8;
+ scc_delay();
+ *p = ch;
+}
+
+
+static void scc_console_write (struct console *co, const char *str, unsigned count)
+{
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ while (count--)
+ {
+ if (*str == '\n')
+ scc_ch_write ('\r');
+ scc_ch_write (*str++);
+ }
+ restore_flags(flags);
+}
+
+
+static int scc_console_wait_key(struct console *co)
+{
+ unsigned long flags;
+ volatile char *p = NULL;
+ int c;
+
+#ifdef CONFIG_MVME147_SCC
+ if (MACH_IS_MVME147)
+ p = (volatile char *)M147_SCC_A_ADDR;
+#endif
+#ifdef CONFIG_MVME162_SCC
+ if (MACH_IS_MVME16x)
+ p = (volatile char *)MVME_SCC_A_ADDR;
+#endif
+#ifdef CONFIG_BVME6000_SCC
+ if (MACH_IS_BVME6000)
+ p = (volatile char *)BVME_SCC_A_ADDR;
+#endif
+
+ save_flags(flags);
+ cli();
+
+ /* wait for rx buf filled */
+ while ((*p & 0x01) == 0)
+ ;
+
+ *p = 8;
+ scc_delay();
+ c = *p;
+ restore_flags(flags);
+ return c;
+}
+
+
+static kdev_t scc_console_device(struct console *c)
+{
+ return MKDEV(TTY_MAJOR, SCC_MINOR_BASE + c->index);
+}
+
+
+static int __init scc_console_setup(struct console *co, char *options)
+{
+ return 0;
+}
+
+
+static struct console sercons = {
+ "ttyS",
+ scc_console_write,
+ NULL,
+ scc_console_device,
+ scc_console_wait_key,
+ NULL,
+ scc_console_setup,
+ CON_PRINTBUFFER,
+ -1,
+ 0,
+ NULL
+};
+
+
+void __init vme_scc_console_init(void)
+{
+ if (vme_brdtype == VME_TYPE_MVME147 ||
+ vme_brdtype == VME_TYPE_MVME162 ||
+ vme_brdtype == VME_TYPE_MVME172 ||
+ vme_brdtype == VME_TYPE_BVME4000 ||
+ vme_brdtype == VME_TYPE_BVME6000)
+ register_console(&sercons);
+}
+
diff --git a/drivers/i2c/Config.in b/drivers/i2c/Config.in
index ba533aac0..9050f3528 100644
--- a/drivers/i2c/Config.in
+++ b/drivers/i2c/Config.in
@@ -8,22 +8,22 @@ tristate 'I2C support' CONFIG_I2C
if [ "$CONFIG_I2C" != "n" ]; then
- dep_tristate 'I2C bit-banging interfaces' CONFIG_I2C_ALGOBIT $CONFIG_I2C
- if [ "$CONFIG_I2C_ALGOBIT" != "n" ]; then
- dep_tristate ' Philips style parallel port adapter' CONFIG_I2C_PHILIPSPAR $CONFIG_I2C_ALGOBIT
- dep_tristate ' ELV adapter' CONFIG_I2C_ELV $CONFIG_I2C_ALGOBIT
- dep_tristate ' Velleman K9000 adapter' CONFIG_I2C_VELLEMAN $CONFIG_I2C_ALGOBIT
- fi
+ dep_tristate 'I2C bit-banging interfaces' CONFIG_I2C_ALGOBIT $CONFIG_I2C
+ if [ "$CONFIG_I2C_ALGOBIT" != "n" ]; then
+ dep_tristate ' Philips style parallel port adapter' CONFIG_I2C_PHILIPSPAR $CONFIG_I2C_ALGOBIT
+ dep_tristate ' ELV adapter' CONFIG_I2C_ELV $CONFIG_I2C_ALGOBIT
+ dep_tristate ' Velleman K9000 adapter' CONFIG_I2C_VELLEMAN $CONFIG_I2C_ALGOBIT
+ fi
- dep_tristate 'I2C PCF 8584 interfaces' CONFIG_I2C_ALGOPCF $CONFIG_I2C
- if [ "$CONFIG_I2C_ALGOPCF" != "n" ]; then
- dep_tristate ' Elektor ISA card' CONFIG_I2C_ELEKTOR $CONFIG_I2C_ALGOPCF
- fi
+ dep_tristate 'I2C PCF 8584 interfaces' CONFIG_I2C_ALGOPCF $CONFIG_I2C
+ if [ "$CONFIG_I2C_ALGOPCF" != "n" ]; then
+ dep_tristate ' Elektor ISA card' CONFIG_I2C_ELEKTOR $CONFIG_I2C_ALGOPCF
+ fi
# This is needed for automatic patch generation: sensors code starts here
# This is needed for automatic patch generation: sensors code ends here
- dep_tristate 'I2C device interface' CONFIG_I2C_CHARDEV $CONFIG_I2C
+ dep_tristate 'I2C device interface' CONFIG_I2C_CHARDEV $CONFIG_I2C
fi
endmenu
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 3d88b6c39..e74337f5b 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -20,7 +20,7 @@
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>.
All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> */
-/* $Id: i2c-core.c,v 1.44 1999/12/21 23:45:58 frodo Exp $ */
+/* $Id: i2c-core.c,v 1.48 2000/01/24 21:41:19 frodo Exp $ */
#include <linux/module.h>
#include <linux/kernel.h>
@@ -33,37 +33,14 @@
/* ----- compatibility stuff ----------------------------------------------- */
-/* 2.0.0 kernel compatibility */
-#if LINUX_VERSION_CODE < 0x020100
-#define MODULE_AUTHOR(noone)
-#define MODULE_DESCRIPTION(none)
-#define MODULE_PARM(no,param)
-#define MODULE_PARM_DESC(no,description)
-#define EXPORT_SYMBOL(noexport)
-#define EXPORT_NO_SYMBOLS
-#endif
-
#include <linux/version.h>
-#ifndef KERNEL_VERSION
-#define KERNEL_VERSION(a,b,c) (((a) << 16) | ((b) << 8) | (c))
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,53)
#include <linux/init.h>
-#else
-#define __init
-#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,1)
#define init_MUTEX(s) do { *(s) = MUTEX; } while(0)
#endif
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,4))
-#define copy_from_user memcpy_fromfs
-#define copy_to_user memcpy_tofs
-#else
#include <asm/uaccess.h>
-#endif
/* ----- global defines ---------------------------------------------------- */
@@ -83,8 +60,8 @@
/* ----- global variables -------------------------------------------------- */
/**** lock for writing to global variables: the adapter & driver list */
-struct semaphore adap_lock;
-struct semaphore driver_lock;
+struct semaphore adap_lock;
+struct semaphore driver_lock;
/**** adapter list */
static struct i2c_adapter *adapters[I2C_ADAP_MAX];
@@ -104,73 +81,29 @@ static void i2c_dummy_client(struct i2c_client *client);
*----------------------------------------------------
*/
-/* Note that quite some things changed within the 2.1 kernel series.
- Some things below are somewhat difficult to read because of this. */
-
#ifdef CONFIG_PROC_FS
static int i2cproc_init(void);
static int i2cproc_cleanup(void);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) && \
- (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,27))
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,27))
static void monitor_bus_i2c(struct inode *inode, int fill);
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29))
-
static ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
loff_t *ppos);
static int read_bus_i2c(char *buf, char **start, off_t offset, int len,
int *eof , void *private);
-#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */
-
-static int i2cproc_bus_read(struct inode * inode, struct file * file,
- char * buf, int count);
-static int read_bus_i2c(char *buf, char **start, off_t offset, int len,
- int unused);
-
-static struct proc_dir_entry proc_bus_dir =
- {
- /* low_ino */ 0, /* Set by proc_register_dynamic */
- /* namelen */ 3,
- /* name */ "bus",
- /* mode */ S_IRUGO | S_IXUGO | S_IFDIR,
- /* nlink */ 2, /* Corrected by proc_register[_dynamic] */
- /* uid */ 0,
- /* gid */ 0,
- /* size */ 0,
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,0,36))
- /* ops */ &proc_dir_inode_operations,
-#endif
- };
-
-static struct proc_dir_entry proc_bus_i2c_dir =
- {
- /* low_ino */ 0, /* Set by proc_register_dynamic */
- /* namelen */ 3,
- /* name */ "i2c",
- /* mode */ S_IRUGO | S_IFREG,
- /* nlink */ 1,
- /* uid */ 0,
- /* gid */ 0,
- /* size */ 0,
- /* ops */ NULL,
- /* get_info */ &read_bus_i2c
- };
-
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */
-
/* To implement the dynamic /proc/bus/i2c-? files, we need our own
implementation of the read hook */
static struct file_operations i2cproc_operations = {
- NULL,
- i2cproc_bus_read,
+ NULL,
+ i2cproc_bus_read,
};
static struct inode_operations i2cproc_inode_operations = {
- &i2cproc_operations
+ &i2cproc_operations
};
static int i2cproc_initialized = 0;
@@ -183,7 +116,7 @@ static int i2cproc_initialized = 0;
#endif /* CONFIG_PROC_FS */
-/* ---------------------------------------------------
+/* ---------------------------------------------------
* registering functions
* ---------------------------------------------------
*/
@@ -222,55 +155,21 @@ int i2c_add_adapter(struct i2c_adapter *adap)
if (i2cproc_initialized) {
char name[8];
struct proc_dir_entry *proc_entry;
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29))
- int res;
-#endif
sprintf(name,"i2c-%d", i);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29))
proc_entry = create_proc_entry(name,0,proc_bus);
if (! proc_entry) {
printk("i2c-core.o: Could not create /proc/bus/%s\n",
- name);
+ name);
return -ENOENT;
- }
+ }
proc_entry->ops = &i2cproc_inode_operations;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,27))
proc_entry->owner = THIS_MODULE;
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58))
+#else
proc_entry->fill_inode = &monitor_bus_i2c;
#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) */
-#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */
- adap->proc_entry = NULL;
- if (!(proc_entry = kmalloc(sizeof(struct proc_dir_entry)+
- strlen(name)+1, GFP_KERNEL))) {
- printk("i2c-core.o: Out of memory!\n");
- return -ENOMEM;
- }
- memset(proc_entry,0,sizeof(struct proc_dir_entry));
- proc_entry->namelen = strlen(name);
- proc_entry->name = (char *) (proc_entry + 1);
- proc_entry->mode = S_IRUGO | S_IFREG;
- proc_entry->nlink = 1;
- proc_entry->ops = &i2cproc_inode_operations;
-
- /* Nasty stuff to keep GCC satisfied */
- {
- char *procname;
- (const char *) procname = proc_entry->name;
- strcpy (procname,name);
- }
-
- if ((res = proc_register_dynamic(&proc_bus_dir, proc_entry))) {
- printk("i2c-core.o: Could not create %s.\n",name);
- kfree(proc_entry);
- return res;
- }
-
- adap->proc_entry = proc_entry;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */
-
adap->inode = proc_entry->low_ino;
}
@@ -283,7 +182,8 @@ int i2c_add_adapter(struct i2c_adapter *adap)
drivers[j]->attach_adapter(adap);
DRV_UNLOCK();
- DEB(printk("i2c-core.o: adapter %s registered as adapter %d.\n",adap->name,i));
+ DEB(printk("i2c-core.o: adapter %s registered as adapter %d.\n",
+ adap->name,i));
return 0;
}
@@ -306,23 +206,9 @@ int i2c_del_adapter(struct i2c_adapter *adap)
i2c_dummy_adapter(adap); /* actually i2c_dummy->del_adapter */
#ifdef CONFIG_PROC_FS
if (i2cproc_initialized) {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29))
char name[8];
sprintf(name,"i2c-%d", i);
remove_proc_entry(name,proc_bus);
-#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */
- int res;
- if (adapters[i]->proc_entry) {
- if ((res = proc_unregister(&proc_bus_dir,
- adapters[i]->proc_entry->low_ino))) {
- printk("i2c-core.o: Deregistration of /proc "
- "entry failed\n");
- ADAP_UNLOCK();
- return res;
- }
- kfree(adapters[i]->proc_entry);
- }
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */
}
#endif /* def CONFIG_PROC_FS */
@@ -344,7 +230,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
ADAP_UNLOCK();
DEB(printk("i2c-core.o: adapter unregistered: %s\n",adap->name));
- return 0;
+ return 0;
}
@@ -384,7 +270,8 @@ int i2c_add_driver(struct i2c_driver *driver)
driver->attach_adapter(adapters[i]);
for (j=0; j<I2C_CLIENT_MAX; j++)
if (adapters[i]->clients[j])
- driver->detach_client(adapters[i]->clients[j]);
+ driver->detach_client(
+ adapters[i]->clients[j]);
}
}
ADAP_UNLOCK();
@@ -418,7 +305,7 @@ int i2c_del_driver(struct i2c_driver *driver)
}
/* Have a look at each adapter, if clients of this driver are still
* attached. If so, detach them to be able to kill the driver
- * afterwards.
+ * afterwards.
*/
DEB2(printk("i2c-core.o: unregister_driver - looking for clients.\n"));
/* removing clients does not depend on the notify flag, else
@@ -453,11 +340,11 @@ int i2c_del_driver(struct i2c_driver *driver)
int i2c_check_addr (struct i2c_adapter *adapter, int addr)
{
- int i;
- for (i = 0; i < I2C_CLIENT_MAX ; i++)
- if (adapter->clients[i] && (adapter->clients[i]->addr == addr))
- return -EBUSY;
- return 0;
+ int i;
+ for (i = 0; i < I2C_CLIENT_MAX ; i++)
+ if (adapter->clients[i] && (adapter->clients[i]->addr == addr))
+ return -EBUSY;
+ return 0;
}
int i2c_attach_client(struct i2c_client *client)
@@ -465,8 +352,8 @@ int i2c_attach_client(struct i2c_client *client)
struct i2c_adapter *adapter = client->adapter;
int i;
- if (i2c_check_addr(client->adapter,client->addr))
- return -EBUSY;
+ if (i2c_check_addr(client->adapter,client->addr))
+ return -EBUSY;
for (i = 0; i < I2C_CLIENT_MAX; i++)
if (NULL == adapter->clients[i])
@@ -513,7 +400,7 @@ int i2c_detach_client(struct i2c_client *client)
i2c_dummy_client(client);
DEB(printk("i2c-core.o: client [%s] unregistered.\n",client->name));
- return 0;
+ return 0;
}
void i2c_inc_use_client(struct i2c_client *client)
@@ -543,26 +430,21 @@ void i2c_dec_use_client(struct i2c_client *client)
#ifdef CONFIG_PROC_FS
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) && \
- (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,27))
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,27))
/* Monitor access to /proc/bus/i2c*; make unloading i2c-proc impossible
if some process still uses it or some file in it */
void monitor_bus_i2c(struct inode *inode, int fill)
{
- if (fill)
- MOD_INC_USE_COUNT;
- else
- MOD_DEC_USE_COUNT;
+ if (fill)
+ MOD_INC_USE_COUNT;
+ else
+ MOD_DEC_USE_COUNT;
}
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58)) */
+#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,37)) */
/* This function generates the output for /proc/bus/i2c */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29))
int read_bus_i2c(char *buf, char **start, off_t offset, int len, int *eof,
void *private)
-#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */
-int read_bus_i2c(char *buf, char **start, off_t offset, int len, int unused)
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */
{
int i;
int nr = 0;
@@ -571,7 +453,7 @@ int read_bus_i2c(char *buf, char **start, off_t offset, int len, int unused)
if (adapters[i]) {
nr += sprintf(buf+nr, "i2c-%d\t", i);
if (adapters[i]->algo->smbus_xfer) {
- if (adapters[i]->algo->master_xfer)
+ if (adapters[i]->algo->master_xfer)
nr += sprintf(buf+nr,"smbus/i2c");
else
nr += sprintf(buf+nr,"smbus ");
@@ -587,62 +469,55 @@ int read_bus_i2c(char *buf, char **start, off_t offset, int len, int unused)
}
/* This function generates the output for /proc/bus/i2c-? */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29))
ssize_t i2cproc_bus_read(struct file * file, char * buf,size_t count,
loff_t *ppos)
{
- struct inode * inode = file->f_dentry->d_inode;
-#else (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29))
-int i2cproc_bus_read(struct inode * inode, struct file * file,char * buf,
- int count)
-{
-#endif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29))
- char *kbuf;
- struct i2c_client *client;
- int i,j,len=0;
-
- if (count < 0)
- return -EINVAL;
- if (count > 4000)
- count = 4000;
- for (i = 0; i < I2C_ADAP_MAX; i++)
- if (adapters[i]->inode == inode->i_ino) {
- /* We need a bit of slack in the kernel buffer; this makes the
- sprintf safe. */
- if (! (kbuf = kmalloc(count + 80,GFP_KERNEL)))
- return -ENOMEM;
- for (j = 0; j < I2C_CLIENT_MAX; j++)
- if ((client = adapters[i]->clients[j]))
- /* Filter out dummy clients */
- if (client->driver->id != I2C_DRIVERID_I2CDEV)
- len += sprintf(kbuf+len,"%02x\t%-32s\t%-32s\n",
- client->addr,
- client->name,client->driver->name);
- if (file->f_pos+len > count)
- len = count - file->f_pos;
- len = len - file->f_pos;
- if (len < 0)
- len = 0;
- copy_to_user (buf,kbuf+file->f_pos,len);
- file->f_pos += len;
- kfree(kbuf);
- return len;
- }
- return -ENOENT;
+ struct inode * inode = file->f_dentry->d_inode;
+ char *kbuf;
+ struct i2c_client *client;
+ int i,j,len=0;
+
+ if (count < 0)
+ return -EINVAL;
+ if (count > 4000)
+ count = 4000;
+ for (i = 0; i < I2C_ADAP_MAX; i++)
+ if (adapters[i]->inode == inode->i_ino) {
+ /* We need a bit of slack in the kernel buffer; this makes the
+ sprintf safe. */
+ if (! (kbuf = kmalloc(count + 80,GFP_KERNEL)))
+ return -ENOMEM;
+ for (j = 0; j < I2C_CLIENT_MAX; j++)
+ if ((client = adapters[i]->clients[j]))
+ /* Filter out dummy clients */
+ if (client->driver->id != I2C_DRIVERID_I2CDEV)
+ len += sprintf(kbuf+len,"%02x\t%-32s\t%-32s\n",
+ client->addr,
+ client->name,client->driver->name);
+ if (file->f_pos+len > count)
+ len = count - file->f_pos;
+ len = len - file->f_pos;
+ if (len < 0)
+ len = 0;
+ if (copy_to_user (buf,kbuf+file->f_pos,
+ len)) {
+ kfree(kbuf);
+ return -EFAULT;
+ }
+ file->f_pos += len;
+ kfree(kbuf);
+ return len;
+ }
+ return -ENOENT;
}
int i2cproc_init(void)
{
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29))
struct proc_dir_entry *proc_bus_i2c;
-#else
- int res;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */
i2cproc_initialized = 0;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29))
if (! proc_bus) {
printk("i2c-core.o: /proc/bus/ does not exist");
i2cproc_cleanup();
@@ -657,29 +532,10 @@ int i2cproc_init(void)
proc_bus_i2c->read_proc = &read_bus_i2c;
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,27))
proc_bus_i2c->owner = THIS_MODULE;
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,58))
+#else
proc_bus_i2c->fill_inode = &monitor_bus_i2c;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,27)) */
i2cproc_initialized += 2;
-#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */
- /* In Linux 2.0.x, there is no /proc/bus! But I hope no other module
- introduced it, or we are fucked. And 2.0.35 and earlier does not
- export proc_dir_inode_operations, so we grab it from proc_net,
- which also uses it. Not nice. */
- proc_bus_dir.ops = proc_net.ops;
- if ((res = proc_register_dynamic(&proc_root, &proc_bus_dir))) {
- printk("i2c-core.o: Could not create /proc/bus/");
- i2cproc_cleanup();
- return res;
- }
- i2cproc_initialized ++;
- if ((res = proc_register_dynamic(&proc_bus_dir, &proc_bus_i2c_dir))) {
- printk("i2c-core.o: Could not create /proc/bus/i2c\n");
- i2cproc_cleanup();
- return res;
- }
- i2cproc_initialized ++;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */
return 0;
}
@@ -687,27 +543,8 @@ int i2cproc_cleanup(void)
{
if (i2cproc_initialized >= 1) {
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29))
remove_proc_entry("i2c",proc_bus);
i2cproc_initialized -= 2;
-#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,29)) */
- int res;
- if (i2cproc_initialized >= 2) {
- if ((res = proc_unregister(&proc_bus_dir,
- proc_bus_i2c_dir.low_ino))) {
- printk("i2c-core.o: could not delete "
- "/proc/bus/i2c, module not removed.");
- return res;
- }
- i2cproc_initialized --;
- }
- if ((res = proc_unregister(&proc_root,proc_bus_dir.low_ino))) {
- printk("i2c-core.o: could not delete /proc/bus/, "
- "module not removed.");
- return res;
- }
- i2cproc_initialized --;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,29)) */
}
return 0;
}
@@ -715,7 +552,7 @@ int i2cproc_cleanup(void)
#endif /* def CONFIG_PROC_FS */
-/* ---------------------------------------------------
+/* ---------------------------------------------------
* dummy driver notification
* ---------------------------------------------------
*/
@@ -724,16 +561,16 @@ static void i2c_dummy_adapter(struct i2c_adapter *adap)
{
int i;
for (i=0; i<I2C_DRIVER_MAX; i++)
- if (drivers[i] && (drivers[i]->flags & I2C_DF_DUMMY))
- drivers[i]->attach_adapter(adap);
+ if (drivers[i] && (drivers[i]->flags & I2C_DF_DUMMY))
+ drivers[i]->attach_adapter(adap);
}
static void i2c_dummy_client(struct i2c_client *client)
{
int i;
for (i=0; i<I2C_DRIVER_MAX; i++)
- if (drivers[i] && (drivers[i]->flags & I2C_DF_DUMMY))
- drivers[i]->detach_client(client);
+ if (drivers[i] && (drivers[i]->flags & I2C_DF_DUMMY))
+ drivers[i]->detach_client(client);
}
@@ -747,7 +584,8 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg msgs[],int num)
int ret;
if (adap->algo->master_xfer) {
- DEB2(printk("i2c-core.o: master_xfer: %s with %d msgs.\n",adap->name,num));
+ DEB2(printk("i2c-core.o: master_xfer: %s with %d msgs.\n",
+ adap->name,num));
I2C_LOCK(adap);
ret = adap->algo->master_xfer(adap,msgs,num);
@@ -756,7 +594,7 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg msgs[],int num)
return ret;
} else {
printk("i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",
- adap->id);
+ adap->id);
return -ENOSYS;
}
}
@@ -786,7 +624,7 @@ int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
return (ret == 1 )? count : ret;
} else {
printk("i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",
- client->adapter->id);
+ client->adapter->id);
return -ENOSYS;
}
}
@@ -819,7 +657,7 @@ int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
return (ret == 1 )? count : ret;
} else {
printk("i2c-core.o: I2C adapter %04x: I2C level transfers not supported\n",
- client->adapter->id);
+ client->adapter->id);
return -ENOSYS;
}
}
@@ -855,128 +693,124 @@ int i2c_probe(struct i2c_adapter *adapter,
struct i2c_client_address_data *address_data,
i2c_client_found_addr_proc *found_proc)
{
- int addr,i,found,err;
- int adap_id = i2c_adapter_id(adapter);
-
- /* Forget it if we can't probe using SMBUS_QUICK */
- if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK))
- return -1;
-
- for (addr = 0x00;
- addr <= 0x7f;
- addr++) {
-
- /* Skip if already in use */
- if (i2c_check_addr(adapter,addr))
- continue;
-
- /* If it is in one of the force entries, we don't do any detection
- at all */
- found = 0;
-
- for (i = 0;
- !found && (address_data->force[i] != I2C_CLIENT_END);
- i += 3) {
- if (((adap_id == address_data->force[i]) ||
- (address_data->force[i] == ANY_I2C_BUS)) &&
- (addr == address_data->force[i+1])) {
- DEB2(printk("i2c-core.o: found force parameter for adapter %d, addr %04x\n",
- adap_id,addr));
- if ((err = found_proc(adapter,addr,0,0)))
- return err;
- found = 1;
- }
- }
- if (found)
- continue;
-
- /* If this address is in one of the ignores, we can forget about it
- right now */
- for (i = 0;
- !found && (address_data->ignore[i] != I2C_CLIENT_END);
- i += 2) {
- if (((adap_id == address_data->ignore[i]) ||
- ((address_data->ignore[i] == ANY_I2C_BUS))) &&
- (addr == address_data->ignore[i+1])) {
- DEB2(printk("i2c-core.o: found ignore parameter for adapter %d, "
- "addr %04x\n", adap_id ,addr));
- found = 1;
- }
- }
- for (i = 0;
- !found && (address_data->ignore_range[i] != I2C_CLIENT_END);
- i += 3) {
- if (((adap_id == address_data->ignore_range[i]) ||
- ((address_data->ignore_range[i]==ANY_I2C_BUS))) &&
- (addr >= address_data->ignore_range[i+1]) &&
- (addr <= address_data->ignore_range[i+2])) {
- DEB2(printk("i2c-core.o: found ignore_range parameter for adapter %d, "
- "addr %04x\n", adap_id,addr));
- found = 1;
- }
- }
- if (found)
- continue;
-
- /* Now, we will do a detection, but only if it is in the normal or
- probe entries */
- for (i = 0;
- !found && (address_data->normal_i2c[i] != I2C_CLIENT_END);
- i += 1) {
- if (addr == address_data->normal_i2c[i]) {
- found = 1;
- DEB2(printk("i2c-core.o: found normal i2c entry for adapter %d, "
- "addr %02x", adap_id,addr));
- }
- }
-
- for (i = 0;
- !found && (address_data->normal_i2c_range[i] != I2C_CLIENT_END);
- i += 2) {
- if ((addr >= address_data->normal_i2c_range[i]) &&
- (addr <= address_data->normal_i2c_range[i+1])) {
- found = 1;
- DEB2(printk("i2c-core.o: found normal i2c_range entry for adapter %d, "
- "addr %04x\n", adap_id,addr));
- }
- }
-
- for (i = 0;
- !found && (address_data->probe[i] != I2C_CLIENT_END);
- i += 2) {
- if (((adap_id == address_data->probe[i]) ||
- ((address_data->probe[i] == ANY_I2C_BUS))) &&
- (addr == address_data->probe[i+1])) {
- found = 1;
- DEB2(printk("i2c-core.o: found probe parameter for adapter %d, "
- "addr %04x\n", adap_id,addr));
- }
- }
- for (i = 0;
- !found && (address_data->probe_range[i] != I2C_CLIENT_END);
- i += 3) {
- if (((adap_id == address_data->probe_range[i]) ||
- (address_data->probe_range[i] == ANY_I2C_BUS)) &&
- (addr >= address_data->probe_range[i+1]) &&
- (addr <= address_data->probe_range[i+2])) {
- found = 1;
- DEB2(printk("i2c-core.o: found probe_range parameter for adapter %d, "
- "addr %04x\n", adap_id,addr));
- }
- }
- if (!found)
- continue;
-
- /* OK, so we really should examine this address. First check
- whether there is some client here at all! */
- if (i2c_smbus_xfer(adapter,addr,0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
- if ((err = found_proc(adapter,addr,0,-1)))
- return err;
- }
- return 0;
+ int addr,i,found,err;
+ int adap_id = i2c_adapter_id(adapter);
+
+ /* Forget it if we can't probe using SMBUS_QUICK */
+ if (! i2c_check_functionality(adapter,I2C_FUNC_SMBUS_QUICK))
+ return -1;
+
+ for (addr = 0x00; addr <= 0x7f; addr++) {
+
+ /* Skip if already in use */
+ if (i2c_check_addr(adapter,addr))
+ continue;
+
+ /* If it is in one of the force entries, we don't do any detection
+ at all */
+ found = 0;
+
+ for (i = 0; !found && (address_data->force[i] != I2C_CLIENT_END); i += 3) {
+ if (((adap_id == address_data->force[i]) ||
+ (address_data->force[i] == ANY_I2C_BUS)) &&
+ (addr == address_data->force[i+1])) {
+ DEB2(printk("i2c-core.o: found force parameter for adapter %d, addr %04x\n",
+ adap_id,addr));
+ if ((err = found_proc(adapter,addr,0,0)))
+ return err;
+ found = 1;
+ }
+ }
+ if (found)
+ continue;
+
+ /* If this address is in one of the ignores, we can forget about
+ it right now */
+ for (i = 0;
+ !found && (address_data->ignore[i] != I2C_CLIENT_END);
+ i += 2) {
+ if (((adap_id == address_data->ignore[i]) ||
+ ((address_data->ignore[i] == ANY_I2C_BUS))) &&
+ (addr == address_data->ignore[i+1])) {
+ DEB2(printk("i2c-core.o: found ignore parameter for adapter %d, "
+ "addr %04x\n", adap_id ,addr));
+ found = 1;
+ }
+ }
+ for (i = 0;
+ !found && (address_data->ignore_range[i] != I2C_CLIENT_END);
+ i += 3) {
+ if (((adap_id == address_data->ignore_range[i]) ||
+ ((address_data->ignore_range[i]==ANY_I2C_BUS))) &&
+ (addr >= address_data->ignore_range[i+1]) &&
+ (addr <= address_data->ignore_range[i+2])) {
+ DEB2(printk("i2c-core.o: found ignore_range parameter for adapter %d, "
+ "addr %04x\n", adap_id,addr));
+ found = 1;
+ }
+ }
+ if (found)
+ continue;
+
+ /* Now, we will do a detection, but only if it is in the normal or
+ probe entries */
+ for (i = 0;
+ !found && (address_data->normal_i2c[i] != I2C_CLIENT_END);
+ i += 1) {
+ if (addr == address_data->normal_i2c[i]) {
+ found = 1;
+ DEB2(printk("i2c-core.o: found normal i2c entry for adapter %d, "
+ "addr %02x", adap_id,addr));
+ }
+ }
+
+ for (i = 0;
+ !found && (address_data->normal_i2c_range[i] != I2C_CLIENT_END);
+ i += 2) {
+ if ((addr >= address_data->normal_i2c_range[i]) &&
+ (addr <= address_data->normal_i2c_range[i+1])) {
+ found = 1;
+ DEB2(printk("i2c-core.o: found normal i2c_range entry for adapter %d, "
+ "addr %04x\n", adap_id,addr));
+ }
+ }
+
+ for (i = 0;
+ !found && (address_data->probe[i] != I2C_CLIENT_END);
+ i += 2) {
+ if (((adap_id == address_data->probe[i]) ||
+ ((address_data->probe[i] == ANY_I2C_BUS))) &&
+ (addr == address_data->probe[i+1])) {
+ found = 1;
+ DEB2(printk("i2c-core.o: found probe parameter for adapter %d, "
+ "addr %04x\n", adap_id,addr));
+ }
+ }
+ for (i = 0;
+ !found && (address_data->probe_range[i] != I2C_CLIENT_END);
+ i += 3) {
+ if (((adap_id == address_data->probe_range[i]) ||
+ (address_data->probe_range[i] == ANY_I2C_BUS)) &&
+ (addr >= address_data->probe_range[i+1]) &&
+ (addr <= address_data->probe_range[i+2])) {
+ found = 1;
+ DEB2(printk("i2c-core.o: found probe_range parameter for adapter %d, "
+ "addr %04x\n", adap_id,addr));
+ }
+ }
+ if (!found)
+ continue;
+
+ /* OK, so we really should examine this address. First check
+ whether there is some client here at all! */
+ if (i2c_smbus_xfer(adapter,addr,0,0,0,I2C_SMBUS_QUICK,NULL) >= 0)
+ if ((err = found_proc(adapter,addr,0,-1)))
+ return err;
+ }
+ return 0;
}
-/* +++ frodo
+/*
* return id number for a specific adapter
*/
int i2c_adapter_id(struct i2c_adapter *adap)
@@ -993,14 +827,14 @@ int i2c_adapter_id(struct i2c_adapter *adap)
extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value)
{
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- value,0,I2C_SMBUS_QUICK,NULL);
+ value,0,I2C_SMBUS_QUICK,NULL);
}
extern s32 i2c_smbus_read_byte(struct i2c_client * client)
{
union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_READ,0,I2C_SMBUS_BYTE, &data))
+ I2C_SMBUS_READ,0,I2C_SMBUS_BYTE, &data))
return -1;
else
return 0x0FF & data.byte;
@@ -1009,26 +843,26 @@ extern s32 i2c_smbus_read_byte(struct i2c_client * client)
extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value)
{
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,NULL);
+ I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,NULL);
}
extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command)
{
union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data))
+ I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data))
return -1;
else
return 0x0FF & data.byte;
}
-extern s32 i2c_smbus_write_byte_data(struct i2c_client * client,
- u8 command, u8 value)
+extern s32 i2c_smbus_write_byte_data(struct i2c_client * client, u8 command,
+ u8 value)
{
union i2c_smbus_data data;
data.byte = value;
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_WRITE,command,
I2C_SMBUS_BYTE_DATA,&data);
}
@@ -1036,7 +870,7 @@ extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command)
{
union i2c_smbus_data data;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA, &data))
+ I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA, &data))
return -1;
else
return 0x0FFFF & data.word;
@@ -1048,8 +882,8 @@ extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
union i2c_smbus_data data;
data.word = value;
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_WRITE,command,
- I2C_SMBUS_WORD_DATA,&data);
+ I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_WORD_DATA,&data);
}
extern s32 i2c_smbus_process_call(struct i2c_client * client,
@@ -1058,8 +892,8 @@ extern s32 i2c_smbus_process_call(struct i2c_client * client,
union i2c_smbus_data data;
data.word = value;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_WRITE,command,
- I2C_SMBUS_PROC_CALL, &data))
+ I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_PROC_CALL, &data))
return -1;
else
return 0x0FFFF & data.word;
@@ -1072,7 +906,7 @@ extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
union i2c_smbus_data data;
int i;
if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_READ,command,
+ I2C_SMBUS_READ,command,
I2C_SMBUS_BLOCK_DATA,&data))
return -1;
else {
@@ -1093,7 +927,7 @@ extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
data.block[i] = values[i-1];
data.block[0] = length;
return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_WRITE,command,
I2C_SMBUS_BLOCK_DATA,&data);
}
@@ -1177,7 +1011,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
size);
return -1;
}
-
+
if (i2c_transfer(adapter, msg, num) < 0)
return -1;
@@ -1193,8 +1027,8 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
case I2C_SMBUS_PROC_CALL:
data->word = msgbuf1[0] | (msgbuf1[1] << 8);
break;
- }
- return 0;
+ }
+ return 0;
}
@@ -1203,7 +1037,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
union i2c_smbus_data * data)
{
s32 res;
- flags = flags & I2C_M_TEN;
+ flags = flags & I2C_M_TEN;
if (adapter->algo->smbus_xfer) {
I2C_LOCK(adapter);
res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
@@ -1211,7 +1045,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
I2C_UNLOCK(adapter);
} else
res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
- command,size,data);
+ command,size,data);
return res;
}
@@ -1220,22 +1054,22 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
backward compatibility. */
u32 i2c_get_functionality (struct i2c_adapter *adap)
{
- if (adap->algo->functionality)
- return adap->algo->functionality(adap);
- else
- return 0xffffffff;
+ if (adap->algo->functionality)
+ return adap->algo->functionality(adap);
+ else
+ return 0xffffffff;
}
int i2c_check_functionality (struct i2c_adapter *adap, u32 func)
{
- u32 adap_func = i2c_get_functionality (adap);
- return (func & adap_func) == func;
+ u32 adap_func = i2c_get_functionality (adap);
+ return (func & adap_func) == func;
}
static int __init i2c_init(void)
{
- printk("i2c-core.o: i2c core module\n");
+ printk("i2c-core.o: i2c core module\n");
memset(adapters,0,sizeof(adapters));
memset(drivers,0,sizeof(drivers));
adap_count=0;
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 088d730fc..c2c51bef4 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -23,7 +23,7 @@
But I have used so much of his original code and ideas that it seems
only fair to recognize him as co-author -- Frodo */
-/* $Id: i2c-dev.c,v 1.18 1999/12/21 23:45:58 frodo Exp $ */
+/* $Id: i2c-dev.c,v 1.25 2000/01/26 14:14:20 frodo Exp $ */
#include <linux/kernel.h>
#include <linux/module.h>
@@ -34,34 +34,8 @@
/* If you want debugging uncomment: */
/* #define DEBUG */
-#ifndef KERNEL_VERSION
-#define KERNEL_VERSION(a,b,c) (((a) << 16) | ((b) << 8) | (c))
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,51)
#include <linux/init.h>
-#else
-#define __init
-#endif
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,1,4))
-#define copy_from_user memcpy_fromfs
-#define copy_to_user memcpy_tofs
-#define get_user_data(to,from) ((to) = get_user(from),0)
-#else
#include <asm/uaccess.h>
-#define get_user_data(to,from) get_user(to,from)
-#endif
-
-/* 2.0.0 kernel compatibility */
-#if LINUX_VERSION_CODE < 0x020100
-#define MODULE_AUTHOR(noone)
-#define MODULE_DESCRIPTION(none)
-#define MODULE_PARM(no,param)
-#define MODULE_PARM_DESC(no,description)
-#define EXPORT_SYMBOL(noexport)
-#define EXPORT_NO_SYMBOLS
-#endif
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
@@ -73,45 +47,18 @@ extern int cleanup_module(void);
/* struct file_operations changed too often in the 2.1 series for nice code */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,70))
static loff_t i2cdev_lseek (struct file *file, loff_t offset, int origin);
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,56))
-static long long i2cdev_lseek (struct file *file, long long offset, int origin);
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0))
-static long long i2cdev_llseek (struct inode *inode, struct file *file,
- long long offset, int origin);
-#else
-static int i2cdev_lseek (struct inode *inode, struct file *file, off_t offset,
- int origin);
-#endif
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,70))
static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
loff_t *offset);
static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
loff_t *offset);
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0))
-static long i2cdev_read (struct inode *inode, struct file *file, char *buf,
- unsigned long count);
-static long i2cdev_write (struct inode *inode, struct file *file,
- const char *buf, unsigned long offset);
-#else
-static int i2cdev_read(struct inode *inode, struct file *file, char *buf,
- int count);
-static int i2cdev_write(struct inode *inode, struct file *file,
- const char *buf, int count);
-#endif
static int i2cdev_ioctl (struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg);
static int i2cdev_open (struct inode *inode, struct file *file);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,31))
static int i2cdev_release (struct inode *inode, struct file *file);
-#else
-static void i2cdev_release (struct inode *inode, struct file *file);
-#endif
-
static int i2cdev_attach_adapter(struct i2c_adapter *adap);
static int i2cdev_detach_client(struct i2c_client *client);
@@ -127,413 +74,349 @@ extern
static int i2cdev_cleanup(void);
static struct file_operations i2cdev_fops = {
- i2cdev_lseek,
- i2cdev_read,
- i2cdev_write,
- NULL, /* i2cdev_readdir */
- NULL, /* i2cdev_select */
- i2cdev_ioctl,
- NULL, /* i2cdev_mmap */
- i2cdev_open,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,118)
- NULL, /* i2cdev_flush */
-#endif
- i2cdev_release,
+ i2cdev_lseek,
+ i2cdev_read,
+ i2cdev_write,
+ NULL, /* i2cdev_readdir */
+ NULL, /* i2cdev_select */
+ i2cdev_ioctl,
+ NULL, /* i2cdev_mmap */
+ i2cdev_open,
+ NULL, /* i2cdev_flush */
+ i2cdev_release,
};
#define I2CDEV_ADAPS_MAX I2C_ADAP_MAX
static struct i2c_adapter *i2cdev_adaps[I2CDEV_ADAPS_MAX];
static struct i2c_driver i2cdev_driver = {
- /* name */ "i2c-dev dummy driver",
- /* id */ I2C_DRIVERID_I2CDEV,
- /* flags */ I2C_DF_DUMMY,
- /* attach_adapter */ i2cdev_attach_adapter,
- /* detach_client */ i2cdev_detach_client,
- /* command */ i2cdev_command,
- /* inc_use */ NULL,
- /* dec_use */ NULL,
+ /* name */ "i2c-dev dummy driver",
+ /* id */ I2C_DRIVERID_I2CDEV,
+ /* flags */ I2C_DF_DUMMY,
+ /* attach_adapter */ i2cdev_attach_adapter,
+ /* detach_client */ i2cdev_detach_client,
+ /* command */ i2cdev_command,
+ /* inc_use */ NULL,
+ /* dec_use */ NULL,
};
static struct i2c_client i2cdev_client_template = {
- /* name */ "I2C /dev entry",
- /* id */ 1,
- /* flags */ 0,
- /* addr */ -1,
- /* adapter */ NULL,
- /* driver */ &i2cdev_driver,
- /* data */ NULL
+ /* name */ "I2C /dev entry",
+ /* id */ 1,
+ /* flags */ 0,
+ /* addr */ -1,
+ /* adapter */ NULL,
+ /* driver */ &i2cdev_driver,
+ /* data */ NULL
};
static int i2cdev_initialized;
/* Note that the lseek function is called llseek in 2.1 kernels. But things
are complicated enough as is. */
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,70))
loff_t i2cdev_lseek (struct file *file, loff_t offset, int origin)
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,56))
-long long i2cdev_lseek (struct file *file, long long offset, int origin)
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0))
-long long i2cdev_llseek (struct inode *inode, struct file *file,
- long long offset, int origin)
-#else
-int i2cdev_lseek (struct inode *inode, struct file *file, off_t offset,
- int origin)
-#endif
{
#ifdef DEBUG
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,56))
- struct inode *inode = file->f_dentry->d_inode;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,70)) */
- printk("i2c-dev,o: i2c-%d lseek to %ld bytes relative to %d.\n",
- MINOR(inode->i_rdev),(long) offset,origin);
+ struct inode *inode = file->f_dentry->d_inode;
+ printk("i2c-dev,o: i2c-%d lseek to %ld bytes relative to %d.\n",
+ MINOR(inode->i_rdev),(long) offset,origin);
#endif /* DEBUG */
- return -ESPIPE;
+ return -ESPIPE;
}
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,70))
static ssize_t i2cdev_read (struct file *file, char *buf, size_t count,
loff_t *offset)
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0))
-static long i2cdev_read (struct inode *inode, struct file *file, char *buf,
- unsigned long count)
-#else
-static int i2cdev_read(struct inode *inode, struct file *file, char *buf,
- int count)
-#endif
{
- char *tmp;
- int ret;
+ char *tmp;
+ int ret;
#ifdef DEBUG
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,70))
- struct inode *inode = file->f_dentry->d_inode;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,70)) */
+ struct inode *inode = file->f_dentry->d_inode;
#endif /* DEBUG */
- struct i2c_client *client = (struct i2c_client *)file->private_data;
+ struct i2c_client *client = (struct i2c_client *)file->private_data;
- /* copy user space data to kernel space. */
- tmp = kmalloc(count,GFP_KERNEL);
- if (tmp==NULL)
- return -ENOMEM;
+ /* copy user space data to kernel space. */
+ tmp = kmalloc(count,GFP_KERNEL);
+ if (tmp==NULL)
+ return -ENOMEM;
#ifdef DEBUG
- printk("i2c-dev,o: i2c-%d reading %d bytes.\n",MINOR(inode->i_rdev),count);
+ printk("i2c-dev,o: i2c-%d reading %d bytes.\n",MINOR(inode->i_rdev),
+ count);
#endif
- ret = i2c_master_recv(client,tmp,count);
- copy_to_user(buf,tmp,count);
- kfree(tmp);
- return ret;
+ ret = i2c_master_recv(client,tmp,count);
+ if (! ret)
+ ret = copy_to_user(buf,tmp,count)?-EFAULT:0;
+ kfree(tmp);
+ return ret;
}
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,70))
static ssize_t i2cdev_write (struct file *file, const char *buf, size_t count,
loff_t *offset)
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,0))
-static long i2cdev_write (struct inode *inode, struct file *file,
- const char *buf, unsigned long offset)
-#else
-static int i2cdev_write(struct inode *inode, struct file *file,
- const char *buf, int count)
-#endif
{
- int ret;
- char *tmp;
- struct i2c_client *client = (struct i2c_client *)file->private_data;
+ int ret;
+ char *tmp;
+ struct i2c_client *client = (struct i2c_client *)file->private_data;
#ifdef DEBUG
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,70))
- struct inode *inode = file->f_dentry->d_inode;
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,70)) */
+ struct inode *inode = file->f_dentry->d_inode;
#endif /* DEBUG */
- /* copy user space data to kernel space. */
- tmp = kmalloc(count,GFP_KERNEL);
- if (tmp==NULL)
- return -ENOMEM;
- copy_from_user(tmp,buf,count);
+ /* copy user space data to kernel space. */
+ tmp = kmalloc(count,GFP_KERNEL);
+ if (tmp==NULL)
+ return -ENOMEM;
+ if (copy_from_user(tmp,buf,count)) {
+ kfree(tmp);
+ return -EFAULT;
+ }
#ifdef DEBUG
- printk("i2c-dev,o: i2c-%d writing %d bytes.\n",MINOR(inode->i_rdev),count);
+ printk("i2c-dev,o: i2c-%d writing %d bytes.\n",MINOR(inode->i_rdev),
+ count);
#endif
- ret = i2c_master_send(client,tmp,count);
- kfree(tmp);
- return ret;
+ ret = i2c_master_send(client,tmp,count);
+ kfree(tmp);
+ return ret;
}
int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
- struct i2c_client *client = (struct i2c_client *)file->private_data;
- struct i2c_smbus_ioctl_data data_arg;
- union i2c_smbus_data temp;
- int ver,datasize,res;
- unsigned long funcs;
+ struct i2c_client *client = (struct i2c_client *)file->private_data;
+ struct i2c_smbus_ioctl_data data_arg;
+ union i2c_smbus_data temp;
+ int datasize,res;
+ unsigned long funcs;
#ifdef DEBUG
- printk("i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n",
- MINOR(inode->i_rdev),cmd, arg);
+ printk("i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n",
+ MINOR(inode->i_rdev),cmd, arg);
#endif /* DEBUG */
- switch ( cmd ) {
- case I2C_SLAVE:
- case I2C_SLAVE_FORCE:
- if ((arg > 0x3ff) || (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
- return -EINVAL;
- if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg))
- return -EBUSY;
- client->addr = arg;
- return 0;
- case I2C_TENBIT:
- if (arg)
- client->flags |= I2C_M_TEN;
- else
- client->flags &= ~I2C_M_TEN;
- return 0;
- case I2C_FUNCS:
- if (! arg) {
-#ifdef DEBUG
- printk("i2c-dev.o: NULL argument pointer in ioctl I2C_SMBUS.\n");
-#endif
- return -EINVAL;
- }
- if (verify_area(VERIFY_WRITE,(unsigned long *) arg,
- sizeof(unsigned long))) {
+ switch ( cmd ) {
+ case I2C_SLAVE:
+ case I2C_SLAVE_FORCE:
+ if ((arg > 0x3ff) ||
+ (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
+ return -EINVAL;
+ if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg))
+ return -EBUSY;
+ client->addr = arg;
+ return 0;
+ case I2C_TENBIT:
+ if (arg)
+ client->flags |= I2C_M_TEN;
+ else
+ client->flags &= ~I2C_M_TEN;
+ return 0;
+ case I2C_FUNCS:
+ funcs = i2c_get_functionality(client->adapter);
+ return (copy_to_user((unsigned long *)arg,&funcs,
+ sizeof(unsigned long)))?-EFAULT:0;
+ case I2C_SMBUS:
+ copy_from_user_ret(&data_arg,
+ (struct i2c_smbus_ioctl_data *) arg,
+ sizeof(struct i2c_smbus_ioctl_data),
+ -EFAULT);
+ if ((data_arg.size != I2C_SMBUS_BYTE) &&
+ (data_arg.size != I2C_SMBUS_QUICK) &&
+ (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
+ (data_arg.size != I2C_SMBUS_WORD_DATA) &&
+ (data_arg.size != I2C_SMBUS_PROC_CALL) &&
+ (data_arg.size != I2C_SMBUS_BLOCK_DATA)) {
#ifdef DEBUG
- printk("i2c-dev.o: invalid argument pointer (%ld) "
- "in IOCTL I2C_SMBUS.\n", arg);
+ printk("i2c-dev.o: size out of range (%x) in ioctl I2C_SMBUS.\n",
+ data_arg.size);
#endif
- return -EINVAL;
- }
-
- funcs = i2c_get_functionality(client->adapter);
- copy_to_user((unsigned long *)arg,&funcs,sizeof(unsigned long));
- return 0;
- case I2C_SMBUS:
- if (! arg) {
+ return -EINVAL;
+ }
+ /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
+ so the check is valid if size==I2C_SMBUS_QUICK too. */
+ if ((data_arg.read_write != I2C_SMBUS_READ) &&
+ (data_arg.read_write != I2C_SMBUS_WRITE)) {
#ifdef DEBUG
- printk("i2c-dev.o: NULL argument pointer in ioctl I2C_SMBUS.\n");
+ printk("i2c-dev.o: read_write out of range (%x) in ioctl I2C_SMBUS.\n",
+ data_arg.read_write);
#endif
- return -EINVAL;
- }
- if (verify_area(VERIFY_READ,(struct i2c_smbus_ioctl_data *) arg,
- sizeof(struct i2c_smbus_ioctl_data))) {
+ return -EINVAL;
+ }
+
+ /* Note that command values are always valid! */
+
+ if ((data_arg.size == I2C_SMBUS_QUICK) ||
+ ((data_arg.size == I2C_SMBUS_BYTE) &&
+ (data_arg.read_write == I2C_SMBUS_WRITE)))
+ /* These are special: we do not use data */
+ return i2c_smbus_xfer(client->adapter, client->addr,
+ client->flags,
+ data_arg.read_write,
+ data_arg.command,
+ data_arg.size, NULL);
+
+ if (data_arg.data == NULL) {
#ifdef DEBUG
- printk("i2c-dev.o: invalid argument pointer (%ld) "
- "in IOCTL I2C_SMBUS.\n", arg);
+ printk("i2c-dev.o: data is NULL pointer in ioctl I2C_SMBUS.\n");
#endif
- return -EINVAL;
- }
- copy_from_user(&data_arg,(struct i2c_smbus_ioctl_data *) arg,
- sizeof(struct i2c_smbus_ioctl_data));
- if ((data_arg.size != I2C_SMBUS_BYTE) &&
- (data_arg.size != I2C_SMBUS_QUICK) &&
- (data_arg.size != I2C_SMBUS_BYTE_DATA) &&
- (data_arg.size != I2C_SMBUS_WORD_DATA) &&
- (data_arg.size != I2C_SMBUS_PROC_CALL) &&
- (data_arg.size != I2C_SMBUS_BLOCK_DATA)) {
-#ifdef DEBUG
- printk("i2c-dev.o: size out of range (%x) in ioctl I2C_SMBUS.\n",
- data_arg.size);
-#endif
- return -EINVAL;
- }
- /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1,
- so the check is valid if size==I2C_SMBUS_QUICK too. */
- if ((data_arg.read_write != I2C_SMBUS_READ) &&
- (data_arg.read_write != I2C_SMBUS_WRITE)) {
-#ifdef DEBUG
- printk("i2c-dev.o: read_write out of range (%x) in ioctl I2C_SMBUS.\n",
- data_arg.read_write);
-#endif
- return -EINVAL;
- }
-
- /* Note that command values are always valid! */
-
- if ((data_arg.size == I2C_SMBUS_QUICK) ||
- ((data_arg.size == I2C_SMBUS_BYTE) &&
- (data_arg.read_write == I2C_SMBUS_WRITE)))
- /* These are special: we do not use data */
- return i2c_smbus_xfer(client->adapter, client->addr, client->flags,
- data_arg.read_write, data_arg.command,
- data_arg.size, NULL);
-
- if (data_arg.data == NULL) {
-#ifdef DEBUG
- printk("i2c-dev.o: data is NULL pointer in ioctl I2C_SMBUS.\n");
-#endif
- return -EINVAL;
- }
-
- /* This seems unlogical but it is not: if the user wants to read a
- value, we must write that value to user memory! */
- ver = ((data_arg.read_write == I2C_SMBUS_WRITE) &&
- (data_arg.size != I2C_SMBUS_PROC_CALL))?VERIFY_READ:VERIFY_WRITE;
-
- if ((data_arg.size == I2C_SMBUS_BYTE_DATA) || (data_arg.size == I2C_SMBUS_BYTE))
- datasize = sizeof(data_arg.data->byte);
- else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
- (data_arg.size == I2C_SMBUS_PROC_CALL))
- datasize = sizeof(data_arg.data->word);
- else /* size == I2C_SMBUS_BLOCK_DATA */
- datasize = sizeof(data_arg.data->block);
-
- if (verify_area(ver,data_arg.data,datasize)) {
-#ifdef DEBUG
- printk("i2c-dev.o: invalid pointer data (%p) in ioctl I2C_SMBUS.\n",
- data_arg.data);
-#endif
- return -EINVAL;
- }
-
- if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
- (data_arg.read_write == I2C_SMBUS_WRITE))
- copy_from_user(&temp,data_arg.data,datasize);
- res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
- data_arg.read_write,
- data_arg.command,data_arg.size,&temp);
- if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
- (data_arg.read_write == I2C_SMBUS_READ)))
- copy_to_user(data_arg.data,&temp,datasize);
- return res;
-
- default:
- return i2c_control(client,cmd,arg);
- }
- return 0;
+ return -EINVAL;
+ }
+
+ if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
+ (data_arg.size == I2C_SMBUS_BYTE))
+ datasize = sizeof(data_arg.data->byte);
+ else if ((data_arg.size == I2C_SMBUS_WORD_DATA) ||
+ (data_arg.size == I2C_SMBUS_PROC_CALL))
+ datasize = sizeof(data_arg.data->word);
+ else /* size == I2C_SMBUS_BLOCK_DATA */
+ datasize = sizeof(data_arg.data->block);
+
+ if ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
+ (data_arg.read_write == I2C_SMBUS_WRITE))
+ copy_from_user_ret(&temp,data_arg.data,datasize,
+ -EFAULT);
+ res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
+ data_arg.read_write,
+ data_arg.command,data_arg.size,&temp);
+ if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) ||
+ (data_arg.read_write == I2C_SMBUS_READ)))
+ copy_to_user_ret(data_arg.data,&temp,datasize,-EFAULT);
+ return res;
+
+ default:
+ return i2c_control(client,cmd,arg);
+ }
+ return 0;
}
int i2cdev_open (struct inode *inode, struct file *file)
{
- unsigned int minor = MINOR(inode->i_rdev);
- struct i2c_client *client;
+ unsigned int minor = MINOR(inode->i_rdev);
+ struct i2c_client *client;
- if ((minor >= I2CDEV_ADAPS_MAX) || ! (i2cdev_adaps[minor])) {
+ if ((minor >= I2CDEV_ADAPS_MAX) || ! (i2cdev_adaps[minor])) {
#ifdef DEBUG
- printk("i2c-dev.o: Trying to open unattached adapter i2c-%d\n",minor);
+ printk("i2c-dev.o: Trying to open unattached adapter i2c-%d\n",
+ minor);
#endif
- return -ENODEV;
- }
+ return -ENODEV;
+ }
- /* Note that we here allocate a client for later use, but we will *not*
- register this client! Yes, this is safe. No, it is not very clean. */
- if(! (client = kmalloc(sizeof(struct i2c_client),GFP_KERNEL)))
- return -ENOMEM;
- memcpy(client,&i2cdev_client_template,sizeof(struct i2c_client));
- client->adapter = i2cdev_adaps[minor];
- file->private_data = client;
+ /* Note that we here allocate a client for later use, but we will *not*
+ register this client! Yes, this is safe. No, it is not very clean. */
+ if(! (client = kmalloc(sizeof(struct i2c_client),GFP_KERNEL)))
+ return -ENOMEM;
+ memcpy(client,&i2cdev_client_template,sizeof(struct i2c_client));
+ client->adapter = i2cdev_adaps[minor];
+ file->private_data = client;
- i2cdev_adaps[minor]->inc_use(i2cdev_adaps[minor]);
- MOD_INC_USE_COUNT;
+ if (i2cdev_adaps[minor]->inc_use)
+ i2cdev_adaps[minor]->inc_use(i2cdev_adaps[minor]);
+ MOD_INC_USE_COUNT;
#ifdef DEBUG
- printk("i2c-dev.o: opened i2c-%d\n",minor);
+ printk("i2c-dev.o: opened i2c-%d\n",minor);
#endif
- return 0;
+ return 0;
}
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,31))
static int i2cdev_release (struct inode *inode, struct file *file)
-#else
-static void i2cdev_release (struct inode *inode, struct file *file)
-#endif
{
- unsigned int minor = MINOR(inode->i_rdev);
- kfree(file->private_data);
- file->private_data=NULL;
+ unsigned int minor = MINOR(inode->i_rdev);
+ kfree(file->private_data);
+ file->private_data=NULL;
#ifdef DEBUG
- printk("i2c-dev.o: Closed: i2c-%d\n", minor);
-#endif
- MOD_DEC_USE_COUNT;
- i2cdev_adaps[minor]->dec_use(i2cdev_adaps[minor]);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,31))
- return 0;
+ printk("i2c-dev.o: Closed: i2c-%d\n", minor);
#endif
+ MOD_DEC_USE_COUNT;
+ if (i2cdev_adaps[minor]->dec_use)
+ i2cdev_adaps[minor]->dec_use(i2cdev_adaps[minor]);
+ return 0;
}
int i2cdev_attach_adapter(struct i2c_adapter *adap)
{
- int i;
-
- if ((i = i2c_adapter_id(adap)) < 0) {
- printk("i2c-dev.o: Unknown adapter ?!?\n");
- return -ENODEV;
- }
- if (i >= I2CDEV_ADAPS_MAX) {
- printk("i2c-dev.o: Adapter number too large?!? (%d)\n",i);
- return -ENODEV;
- }
-
- if (! i2cdev_adaps[i]) {
- i2cdev_adaps[i] = adap;
- printk("i2c-dev.o: Registered '%s' as minor %d\n",adap->name,i);
- } else {
- i2cdev_adaps[i] = NULL;
+ int i;
+
+ if ((i = i2c_adapter_id(adap)) < 0) {
+ printk("i2c-dev.o: Unknown adapter ?!?\n");
+ return -ENODEV;
+ }
+ if (i >= I2CDEV_ADAPS_MAX) {
+ printk("i2c-dev.o: Adapter number too large?!? (%d)\n",i);
+ return -ENODEV;
+ }
+
+ if (! i2cdev_adaps[i]) {
+ i2cdev_adaps[i] = adap;
+ printk("i2c-dev.o: Registered '%s' as minor %d\n",adap->name,i);
+ } else {
+ i2cdev_adaps[i] = NULL;
#ifdef DEBUG
- printk("i2c-dev.o: Adapter unregistered: %s\n",adap->name);
+ printk("i2c-dev.o: Adapter unregistered: %s\n",adap->name);
#endif
- }
+ }
- return 0;
+ return 0;
}
int i2cdev_detach_client(struct i2c_client *client)
{
- return 0;
+ return 0;
}
static int i2cdev_command(struct i2c_client *client, unsigned int cmd,
void *arg)
{
- return -1;
+ return -1;
}
int __init i2c_dev_init(void)
{
- int res;
-
- printk("i2c-dev.o: i2c /dev entries driver module\n");
-
- i2cdev_initialized = 0;
- if (register_chrdev(I2C_MAJOR,"i2c",&i2cdev_fops)) {
- printk("i2c-dev.o: unable to get major %d for i2c bus\n",I2C_MAJOR);
- return -EIO;
- }
- i2cdev_initialized ++;
-
- if ((res = i2c_add_driver(&i2cdev_driver))) {
- printk("i2c-dev.o: Driver registration failed, module not inserted.\n");
- i2cdev_cleanup();
- return res;
- }
- i2cdev_initialized ++;
- return 0;
+ int res;
+
+ printk("i2c-dev.o: i2c /dev entries driver module\n");
+
+ i2cdev_initialized = 0;
+ if (register_chrdev(I2C_MAJOR,"i2c",&i2cdev_fops)) {
+ printk("i2c-dev.o: unable to get major %d for i2c bus\n",
+ I2C_MAJOR);
+ return -EIO;
+ }
+ i2cdev_initialized ++;
+
+ if ((res = i2c_add_driver(&i2cdev_driver))) {
+ printk("i2c-dev.o: Driver registration failed, module not inserted.\n");
+ i2cdev_cleanup();
+ return res;
+ }
+ i2cdev_initialized ++;
+ return 0;
}
int i2cdev_cleanup(void)
{
- int res;
-
- if (i2cdev_initialized >= 2) {
- if ((res = i2c_del_driver(&i2cdev_driver))) {
- printk("i2c-dev.o: Driver deregistration failed, "
- "module not removed.\n");
- return res;
- }
- i2cdev_initialized ++;
- }
-
- if (i2cdev_initialized >= 1) {
- if ((res = unregister_chrdev(I2C_MAJOR,"i2c"))) {
- printk("i2c-dev.o: unable to release major %d for i2c bus\n",I2C_MAJOR);
- return res;
- }
- i2cdev_initialized --;
- }
- return 0;
+ int res;
+
+ if (i2cdev_initialized >= 2) {
+ if ((res = i2c_del_driver(&i2cdev_driver))) {
+ printk("i2c-dev.o: Driver deregistration failed, "
+ "module not removed.\n");
+ return res;
+ }
+ i2cdev_initialized ++;
+ }
+
+ if (i2cdev_initialized >= 1) {
+ if ((res = unregister_chrdev(I2C_MAJOR,"i2c"))) {
+ printk("i2c-dev.o: unable to release major %d for i2c bus\n",
+ I2C_MAJOR);
+ return res;
+ }
+ i2cdev_initialized --;
+ }
+ return 0;
}
EXPORT_NO_SYMBOLS;
@@ -545,12 +428,12 @@ MODULE_DESCRIPTION("I2C /dev entries driver");
int init_module(void)
{
- return i2c_dev_init();
+ return i2c_dev_init();
}
int cleanup_module(void)
{
- return i2cdev_cleanup();
+ return i2cdev_cleanup();
}
#endif /* def MODULE */
diff --git a/drivers/i2c/i2c-elektor.c b/drivers/i2c/i2c-elektor.c
index fb965df0f..ad7b9d41c 100644
--- a/drivers/i2c/i2c-elektor.c
+++ b/drivers/i2c/i2c-elektor.c
@@ -22,7 +22,7 @@
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
-/* $Id: i2c-elektor.c,v 1.13 1999/12/21 23:45:58 frodo Exp $ */
+/* $Id: i2c-elektor.c,v 1.16 2000/01/24 02:06:33 mds Exp $ */
#include <linux/kernel.h>
#include <linux/ioport.h>
@@ -30,24 +30,10 @@
#include <linux/delay.h>
#include <linux/malloc.h>
#include <linux/version.h>
-#if LINUX_VERSION_CODE >= 0x020135
#include <linux/init.h>
-#else
-#define __init
-#endif
#include <asm/irq.h>
#include <asm/io.h>
-/* 2.0.0 kernel compatibility */
-#if LINUX_VERSION_CODE < 0x020100
-#define MODULE_AUTHOR(noone)
-#define MODULE_DESCRIPTION(none)
-#define MODULE_PARM(no,param)
-#define MODULE_PARM_DESC(no,description)
-#define EXPORT_SYMBOL(noexport)
-#define EXPORT_NO_SYMBOLS
-#endif
-
#include <linux/i2c.h>
#include <linux/i2c-algo-pcf.h>
#include <linux/i2c-elektor.h>
@@ -87,56 +73,48 @@ static int pcf_pending;
static void pcf_isa_setbyte(void *data, int ctl, int val)
{
- if (ctl) {
- if (gpi.pi_irq > 0) {
- DEB3(printk("i2c-elektor.o: Write control 0x%x\n", val|I2C_PCF_ENI));
- outb(val | I2C_PCF_ENI, CTRL);
- } else {
- DEB3(printk("i2c-elektor.o: Write control 0x%x\n", val));
- outb(val, CTRL);
- }
- } else {
- DEB3(printk("i2c-elektor.o: Write data 0x%x\n", val));
- outb(val, DATA);
- }
+ if (ctl) {
+ if (gpi.pi_irq > 0) {
+ DEB3(printk("i2c-elektor.o: Write control 0x%x\n",
+ val|I2C_PCF_ENI));
+ outb(val | I2C_PCF_ENI, CTRL);
+ } else {
+ DEB3(printk("i2c-elektor.o: Write control 0x%x\n", val));
+ outb(val, CTRL);
+ }
+ } else {
+ DEB3(printk("i2c-elektor.o: Write data 0x%x\n", val));
+ outb(val, DATA);
+ }
}
static int pcf_isa_getbyte(void *data, int ctl)
{
- int val;
-
- if (ctl) {
- val = inb(CTRL);
- DEB3(printk("i2c-elektor.o: Read control 0x%x\n", val));
- } else {
- val = inb(DATA);
- DEB3(printk("i2c-elektor.o: Read data 0x%x\n", val));
- }
- return (val);
+ int val;
+
+ if (ctl) {
+ val = inb(CTRL);
+ DEB3(printk("i2c-elektor.o: Read control 0x%x\n", val));
+ } else {
+ val = inb(DATA);
+ DEB3(printk("i2c-elektor.o: Read data 0x%x\n", val));
+ }
+ return (val);
}
static int pcf_isa_getown(void *data)
{
- return (gpi.pi_own);
+ return (gpi.pi_own);
}
static int pcf_isa_getclock(void *data)
{
- return (gpi.pi_clock);
+ return (gpi.pi_clock);
}
-#if LINUX_VERSION_CODE < 0x02017f
-static void schedule_timeout(int j)
-{
- current->state = TASK_INTERRUPTIBLE;
- current->timeout = jiffies + j;
- schedule();
-}
-#endif
-
#if 0
static void pcf_isa_sleep(unsigned long timeout)
{
@@ -147,64 +125,53 @@ static void pcf_isa_sleep(unsigned long timeout)
static void pcf_isa_waitforpin(void) {
- int timeout = 2;
-
- if (gpi.pi_irq > 0) {
- cli();
- if (pcf_pending == 0) {
-#if LINUX_VERSION_CODE < 0x02017f
- current->timeout = jiffies + timeout * HZ;
- interruptible_sleep_on(&pcf_wait);
-#else
- interruptible_sleep_on_timeout(&pcf_wait, timeout*HZ );
-#endif
- }
- else
- pcf_pending = 0;
- sti();
-#if LINUX_VERSION_CODE < 0x02017f
- current->timeout = 0;
-#endif
- }
- else {
- udelay(100);
- }
+ int timeout = 2;
+
+ if (gpi.pi_irq > 0) {
+ cli();
+ if (pcf_pending == 0) {
+ interruptible_sleep_on_timeout(&pcf_wait, timeout*HZ );
+ } else
+ pcf_pending = 0;
+ sti();
+ } else {
+ udelay(100);
+ }
}
static void pcf_isa_handler(int this_irq, void *dev_id, struct pt_regs *regs) {
-
- pcf_pending = 1;
- wake_up_interruptible(&pcf_wait);
+ pcf_pending = 1;
+ wake_up_interruptible(&pcf_wait);
}
static int pcf_isa_init(void)
{
- if (check_region(gpi.pi_base, 2) < 0 ) {
- return -ENODEV;
- } else {
- request_region(gpi.pi_base, 2, "i2c (isa bus adapter)");
- }
- if (gpi.pi_irq > 0) {
- if (request_irq(gpi.pi_irq, pcf_isa_handler, 0, "PCF8584", 0) < 0) {
- printk("i2c-elektor.o: Request irq%d failed\n", gpi.pi_irq);
- gpi.pi_irq = 0;
- }
- else
- enable_irq(gpi.pi_irq);
- }
- return 0;
+ if (check_region(gpi.pi_base, 2) < 0 ) {
+ return -ENODEV;
+ } else {
+ request_region(gpi.pi_base, 2, "i2c (isa bus adapter)");
+ }
+ if (gpi.pi_irq > 0) {
+ if (request_irq(gpi.pi_irq, pcf_isa_handler, 0, "PCF8584", 0)
+ < 0) {
+ printk("i2c-elektor.o: Request irq%d failed\n", gpi.pi_irq);
+ gpi.pi_irq = 0;
+ } else
+ enable_irq(gpi.pi_irq);
+ }
+ return 0;
}
static void pcf_isa_exit(void)
{
- if (gpi.pi_irq > 0) {
- disable_irq(gpi.pi_irq);
- free_irq(gpi.pi_irq, 0);
- }
- release_region(gpi.pi_base , 2);
+ if (gpi.pi_irq > 0) {
+ disable_irq(gpi.pi_irq);
+ free_irq(gpi.pi_irq, 0);
+ }
+ release_region(gpi.pi_base , 2);
}
@@ -222,14 +189,14 @@ static int pcf_isa_unreg(struct i2c_client *client)
static void pcf_isa_inc_use(struct i2c_adapter *adap)
{
#ifdef MODULE
- MOD_INC_USE_COUNT;
+ MOD_INC_USE_COUNT;
#endif
}
static void pcf_isa_dec_use(struct i2c_adapter *adap)
{
#ifdef MODULE
- MOD_DEC_USE_COUNT;
+ MOD_DEC_USE_COUNT;
#endif
}
@@ -262,41 +229,41 @@ static struct i2c_adapter pcf_isa_ops = {
int __init i2c_pcfisa_init(void)
{
- struct i2c_pcf_isa *pisa = &gpi;
+ struct i2c_pcf_isa *pisa = &gpi;
- printk("i2c-elektor.o: i2c pcf8584-isa adapter module\n");
- if (base == 0)
- pisa->pi_base = DEFAULT_BASE;
- else
- pisa->pi_base = base;
+ printk("i2c-elektor.o: i2c pcf8584-isa adapter module\n");
+ if (base == 0)
+ pisa->pi_base = DEFAULT_BASE;
+ else
+ pisa->pi_base = base;
- if (irq == 0)
- pisa->pi_irq = DEFAULT_IRQ;
- else
- pisa->pi_irq = irq;
+ if (irq == 0)
+ pisa->pi_irq = DEFAULT_IRQ;
+ else
+ pisa->pi_irq = irq;
- if (clock == 0)
- pisa->pi_clock = DEFAULT_CLOCK;
- else
- pisa->pi_clock = clock;
+ if (clock == 0)
+ pisa->pi_clock = DEFAULT_CLOCK;
+ else
+ pisa->pi_clock = clock;
- if (own == 0)
- pisa->pi_own = DEFAULT_OWN;
- else
- pisa->pi_own = own;
+ if (own == 0)
+ pisa->pi_own = DEFAULT_OWN;
+ else
+ pisa->pi_own = own;
- pcf_isa_data.data = (void *)pisa;
+ pcf_isa_data.data = (void *)pisa;
#if (LINUX_VERSION_CODE >= 0x020301)
- init_waitqueue_head(&pcf_wait);
+ init_waitqueue_head(&pcf_wait);
#endif
- if (pcf_isa_init() == 0) {
- if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
- return -ENODEV;
- } else {
- return -ENODEV;
- }
- printk("i2c-elektor.o: found device at %#x.\n", pisa->pi_base);
- return 0;
+ if (pcf_isa_init() == 0) {
+ if (i2c_pcf_add_bus(&pcf_isa_ops) < 0)
+ return -ENODEV;
+ } else {
+ return -ENODEV;
+ }
+ printk("i2c-elektor.o: found device at %#x.\n", pisa->pi_base);
+ return 0;
}
@@ -313,7 +280,7 @@ MODULE_PARM(own, "i");
int init_module(void)
{
- return i2c_pcfisa_init();
+ return i2c_pcfisa_init();
}
void cleanup_module(void)
diff --git a/drivers/i2c/i2c-pcf8584.h b/drivers/i2c/i2c-pcf8584.h
index 7dabbd9a9..9f0874012 100644
--- a/drivers/i2c/i2c-pcf8584.h
+++ b/drivers/i2c/i2c-pcf8584.h
@@ -21,20 +21,20 @@
/* With some changes from Frodo Looijaard <frodol@dds.nl> */
-/* $Id: i2c-pcf8584.h,v 1.2 1999/12/21 23:45:58 frodo Exp $ */
+/* $Id: i2c-pcf8584.h,v 1.3 2000/01/18 23:54:07 frodo Exp $ */
#ifndef I2C_PCF8584_H
#define I2C_PCF8584_H 1
/* ----- Control register bits ---------------------------------------- */
-#define I2C_PCF_PIN 0x80
-#define I2C_PCF_ESO 0x40
-#define I2C_PCF_ES1 0x20
-#define I2C_PCF_ES2 0x10
-#define I2C_PCF_ENI 0x08
-#define I2C_PCF_STA 0x04
-#define I2C_PCF_STO 0x02
-#define I2C_PCF_ACK 0x01
+#define I2C_PCF_PIN 0x80
+#define I2C_PCF_ESO 0x40
+#define I2C_PCF_ES1 0x20
+#define I2C_PCF_ES2 0x10
+#define I2C_PCF_ENI 0x08
+#define I2C_PCF_STA 0x04
+#define I2C_PCF_STO 0x02
+#define I2C_PCF_ACK 0x01
#define I2C_PCF_START (I2C_PCF_PIN | I2C_PCF_ESO | I2C_PCF_STA | I2C_PCF_ACK)
#define I2C_PCF_STOP (I2C_PCF_PIN | I2C_PCF_ESO | I2C_PCF_STO | I2C_PCF_ACK)
@@ -45,7 +45,7 @@
/*#define I2C_PCF_PIN 0x80 as above*/
#define I2C_PCF_INI 0x40 /* 1 if not initialized */
-#define I2C_PCF_STS 0x20
+#define I2C_PCF_STS 0x20
#define I2C_PCF_BER 0x10
#define I2C_PCF_AD0 0x08
#define I2C_PCF_LRB 0x08
@@ -54,17 +54,17 @@
#define I2C_PCF_BB 0x01
/* ----- Chip clock frequencies --------------------------------------- */
-#define I2C_PCF_CLK3 0x00
-#define I2C_PCF_CLK443 0x10
-#define I2C_PCF_CLK6 0x14
-#define I2C_PCF_CLK8 0x18
-#define I2C_PCF_CLK12 0x1c
+#define I2C_PCF_CLK3 0x00
+#define I2C_PCF_CLK443 0x10
+#define I2C_PCF_CLK6 0x14
+#define I2C_PCF_CLK 0x18
+#define I2C_PCF_CLK12 0x1c
/* ----- transmission frequencies ------------------------------------- */
-#define I2C_PCF_TRNS90 0x00 /* 90 kHz */
-#define I2C_PCF_TRNS45 0x01 /* 45 kHz */
-#define I2C_PCF_TRNS11 0x02 /* 11 kHz */
-#define I2C_PCF_TRNS15 0x03 /* 1.5 kHz */
+#define I2C_PCF_TRNS90 0x00 /* 90 kHz */
+#define I2C_PCF_TRNS45 0x01 /* 45 kHz */
+#define I2C_PCF_TRNS11 0x02 /* 11 kHz */
+#define I2C_PCF_TRNS15 0x03 /* 1.5 kHz */
/* ----- Access to internal registers according to ES1,ES2 ------------ */
diff --git a/drivers/ieee1394/ieee1394_syms.c b/drivers/ieee1394/ieee1394_syms.c
index e4d92fa0f..ee4bde182 100644
--- a/drivers/ieee1394/ieee1394_syms.c
+++ b/drivers/ieee1394/ieee1394_syms.c
@@ -39,6 +39,7 @@ EXPORT_SYMBOL(hpsb_make_readqpacket);
EXPORT_SYMBOL(hpsb_make_readbpacket);
EXPORT_SYMBOL(hpsb_make_writeqpacket);
EXPORT_SYMBOL(hpsb_make_writebpacket);
+EXPORT_SYMBOL(hpsb_make_lockpacket);
EXPORT_SYMBOL(hpsb_read);
EXPORT_SYMBOL(hpsb_write);
EXPORT_SYMBOL(hpsb_lock);
diff --git a/drivers/ieee1394/ieee1394_transactions.c b/drivers/ieee1394/ieee1394_transactions.c
index c50bce62a..e2eeffc68 100644
--- a/drivers/ieee1394/ieee1394_transactions.c
+++ b/drivers/ieee1394/ieee1394_transactions.c
@@ -329,6 +329,30 @@ struct hpsb_packet *hpsb_make_writebpacket(struct hpsb_host *host,
return p;
}
+struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
+ u64 addr, int extcode)
+{
+ struct hpsb_packet *p;
+
+ p = alloc_hpsb_packet(8);
+ if (!p) return NULL;
+
+ p->host = host;
+ p->tlabel = get_tlabel(host, node, 1);
+ p->node_id = node;
+
+ switch (extcode) {
+ case EXTCODE_FETCH_ADD:
+ case EXTCODE_LITTLE_ADD:
+ fill_async_lock(p, addr, extcode, 4);
+ break;
+ default:
+ fill_async_lock(p, addr, extcode, 8);
+ break;
+ }
+
+ return p;
+}
/*
* FIXME - these functions should probably read from / write to user space to
diff --git a/drivers/ieee1394/ieee1394_transactions.h b/drivers/ieee1394/ieee1394_transactions.h
index 136d4f7d9..ebec602a9 100644
--- a/drivers/ieee1394/ieee1394_transactions.h
+++ b/drivers/ieee1394/ieee1394_transactions.h
@@ -39,6 +39,9 @@ struct hpsb_packet *hpsb_make_writeqpacket(struct hpsb_host *host,
struct hpsb_packet *hpsb_make_writebpacket(struct hpsb_host *host,
nodeid_t node, u64 addr,
size_t length);
+struct hpsb_packet *hpsb_make_lockpacket(struct hpsb_host *host, nodeid_t node,
+ u64 addr, int extcode);
+
/*
* hpsb_packet_success - Make sense of the ack and reply codes and
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c
index f39a8de86..4da40f6c4 100644
--- a/drivers/ieee1394/ohci1394.c
+++ b/drivers/ieee1394/ohci1394.c
@@ -1,5 +1,5 @@
/*
- * ti_ohci1394.c - Texas Instruments Ohci1394 driver
+ * ohci1394.c - driver for OHCI 1394 boards
* Copyright (C)1999,2000 Sebastien Rougeaux <sebastien.rougeaux@anu.edu.au>
* Gord Peters <GordPeters@smarttech.com>
*
@@ -18,6 +18,7 @@
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
@@ -40,8 +41,6 @@
#include "ieee1394_core.h"
#include "ohci1394.h"
-#undef CONFIG_PROC_FS
-
/* print general (card independent) information */
#define PRINT_G(level, fmt, args...) \
printk(level "ohci1394: " fmt "\n" , ## args)
@@ -68,7 +67,6 @@ static int init_driver(void);
* IEEE-1394 functionality section *
***********************************/
-
#if 0 /* not needed at this time */
static int get_phy_reg(struct ti_ohci *ohci, int addr)
{
@@ -324,31 +322,53 @@ static int ohci_initialize(struct hpsb_host *host)
}
/* Initialize AR dma */
- ohci->AR_resp_prg->control=0x283C << 16 | AR_RESP_BUF_SIZE;
- ohci->AR_resp_prg->address=virt_to_bus(ohci->AR_resp_buf);
- ohci->AR_resp_prg->status=AR_RESP_BUF_SIZE;
- PRINT(KERN_INFO, ohci->id, "AR control: %x",
- ohci->AR_resp_prg->control);
- PRINT(KERN_INFO, ohci->id, "AR status: %x %d",
- ohci->AR_resp_prg->status & 0xffff,
- ohci->AR_resp_prg->status & 0xffff);
-
- /* Tell the controller where the AR program is */
- reg_write(ohci, OHCI1394_AsRspRcvCommandPtr,
- virt_to_bus(ohci->AR_resp_prg)|0x00000001);
+ /* make sure the context isn't running, dead, or active */
+ if (!(reg_read(ohci, OHCI1394_AsRspRcvContextControlSet) & 0x00008F00)) {
-#if 1
- /* Accept phy packets into AR request context */
- reg_write(ohci, OHCI1394_LinkControlSet, 0x00000400);
-#endif
+ /* initialize AR program */
+ for (i= 0; i < AR_RESP_NUM_DESC; i++) {
- /* Run AR context */
- reg_write(ohci, OHCI1394_AsRspRcvContextControlSet, 0x00008000);
+ /* end of descriptor list? */
+ if ((i + 1) < AR_RESP_NUM_DESC) {
+ ohci->AR_resp_prg[i]->control=
+ (0x283C << 16) | AR_RESP_BUF_SIZE;
+ ohci->AR_resp_prg[i]->branchAddress=
+ (virt_to_bus(ohci->AR_resp_prg[i + 1])
+ & 0xfffffff0) | 0x1;
+ } else {
+ ohci->AR_resp_prg[i]->control=
+ (0x283C << 16) | AR_RESP_BUF_SIZE;
+ ohci->AR_resp_prg[i]->branchAddress=
+ (virt_to_bus(ohci->AR_resp_prg[0])
+ & 0xfffffff0) | 0x1;
+ }
+
+ ohci->AR_resp_prg[i]->address=
+ virt_to_bus(ohci->AR_resp_buf[i]);
+ ohci->AR_resp_prg[i]->status= AR_RESP_BUF_SIZE;
+ }
+
+ /* Tell the controller where the first AR program is */
+ reg_write(ohci, OHCI1394_AsRspRcvCommandPtr,
+ virt_to_bus(ohci->AR_resp_prg[0]) | 0x1 );
+
+ /* Accept phy packets into AR request context */
+ reg_write(ohci, OHCI1394_LinkControlSet, 0x00000400);
+
+ /* Run AR context */
+ reg_write(ohci, OHCI1394_AsRspRcvContextControlSet, 0x00008000);
+ }
+
+ /* Specify AT retries */
+ reg_write(ohci, OHCI1394_ATRetries,
+ OHCI1394_MAX_AT_REQ_RETRIES |
+ (OHCI1394_MAX_AT_RESP_RETRIES<<4) |
+ (OHCI1394_MAX_PHYS_RESP_RETRIES<<8));
#ifndef __BIG_ENDIAN
- reg_write(ohci, OHCI1394_HCControlSet, 0x40000000);
-#else
reg_write(ohci, OHCI1394_HCControlClear, 0x40000000);
+#else
+ reg_write(ohci, OHCI1394_HCControlSet, 0x40000000);
#endif
/* Enable interrupts */
@@ -386,8 +406,9 @@ static void send_next_async(struct ti_ohci *ohci)
int i=0;
struct hpsb_packet *packet = ohci->async_queue;
struct dma_cmd prg;
+#if 0
quadlet_t *ptr = (quadlet_t *)ohci->AT_req_prg;
-
+#endif
//HPSB_TRACE();
/* stop the channel program if it's still running */
@@ -435,14 +456,14 @@ static void send_next_async(struct ti_ohci *ohci)
prg.status = 0;
memcpy(ohci->AT_req_prg, &prg, 16);
memcpy(ohci->AT_req_prg + 1, packet->header, 16);
-
+#if 0
PRINT(KERN_INFO, ohci->id,
"dma_cmd: %08x %08x %08x %08x",
*ptr, *(ptr+1), *(ptr+2), *(ptr+3));
PRINT(KERN_INFO, ohci->id,
"header: %08x %08x %08x %08x",
*(ptr+4), *(ptr+5), *(ptr+6), *(ptr+7));
-
+#endif
reg_write(ohci, OHCI1394_AsReqTrCommandPtr,
virt_to_bus(ohci->AT_req_prg)|0x2);
}
@@ -455,11 +476,11 @@ static void send_next_async(struct ti_ohci *ohci)
prg.branchAddress = 0;
prg.status = 0;
memcpy(ohci->AT_req_prg, &prg, 16);
-
+#if 0
PRINT(KERN_INFO, ohci->id,
"dma_cmd: %08x %08x %08x %08x",
*ptr, *(ptr+1), *(ptr+2), *(ptr+3));
-
+#endif
reg_write(ohci, OHCI1394_AsReqTrCommandPtr,
virt_to_bus(ohci->AT_req_prg)|0x2);
}
@@ -638,6 +659,26 @@ static int ohci_devctl(struct hpsb_host *host, enum devctl_cmd cmd, int arg)
* Global stuff (interrupt handler, init/shutdown code) *
********************************************************/
+static void stop_ar_resp_context(struct ti_ohci *ohci, char *msg)
+{
+ int i=0;
+
+ /* stop the channel program if it's still running */
+ reg_write(ohci, OHCI1394_AsRspRcvContextControlClear, 0x8000);
+
+ /* Wait until it effectively stops */
+ while (reg_read(ohci, OHCI1394_AsRspRcvContextControlSet)
+ & 0x400) {
+ i++;
+ if (i>5000) {
+ PRINT(KERN_ERR, ohci->id,
+ "runaway loop in Dma Ar Resp. bailing out...");
+ break;
+ }
+ }
+ PRINT(KERN_ERR, ohci->id, "%s\n async response receive dma stopped\n", msg);
+}
+
static void ohci_irq_handler(int irq, void *dev_id,
struct pt_regs *regs_are_unused)
{
@@ -656,15 +697,14 @@ static void ohci_irq_handler(int irq, void *dev_id,
event,reg_read(ohci, OHCI1394_IntMaskSet)); */
if (event & OHCI1394_busReset) {
+#if 0
PRINT(KERN_INFO, ohci->id, "bus reset interrupt");
+#endif
if (!host->in_bus_reset) {
hpsb_bus_reset(host);
}
ohci->NumBusResets++;
}
- if (event & OHCI1394_reqTxComplete) {
- PRINT(KERN_INFO, ohci->id, "reqTxComplete int received");
- }
if (event & OHCI1394_RQPkt) {
PRINT(KERN_INFO, ohci->id, "RQPkt int received");
}
@@ -673,58 +713,55 @@ static void ohci_irq_handler(int irq, void *dev_id,
reg_read(ohci, OHCI1394_AsReqRcvContextControlSet));
}
if (event & OHCI1394_RSPkt) {
- int rcv_bytes;
- int i=0;
-
- /* we calculate the number of received bytes from the
- residual count field */
- rcv_bytes = AR_RESP_BUF_SIZE -
- (ohci->AR_resp_prg->status & 0xFFFF);
-
- PRINT(KERN_INFO, ohci->id, "AR_status 0x%x %d, %d bytes read",
- ohci->AR_resp_prg->status,
- ohci->AR_resp_prg->status & 0xffff,
- rcv_bytes);
-
- ohci->AR_resp_active = 0;
-
- if ((ohci->AR_resp_prg->status & 0x84000000)
- && (ohci->AR_resp_prg->status & 0xFFFF) >= 8 ) {
- hpsb_packet_received(host, ohci->AR_resp_buf,
- rcv_bytes);
- } else {
- //HPSB_TRACE();
- PRINT(KERN_ERR, ohci->id,
- "AR resp DMA program status value 0x%x is incorrect!",
- ohci->AR_resp_prg->status);
- }
-
-
- /* --------------- FIXME ---------------------------------
- this is a complete hack... we stop the dma prg
- and start it again so as to reset the dma buffer address
- Very slow, very bad design... to change ASAP */
-
- /* stop the channel program if it's still running */
- reg_write(ohci, OHCI1394_AsRspRcvContextControlClear, 0x8000);
-
- /* Wait until it effectively stops */
- while (reg_read(ohci, OHCI1394_AsRspRcvContextControlSet)
- & 0x400) {
- i++;
- if (i>5000) {
- PRINT(KERN_ERR, ohci->id,
- "runaway loop in DmaAT. bailing out...");
- break;
+ unsigned int idx,offset,rescount;
+
+ spin_lock(&ohci->AR_resp_lock);
+
+ idx = ohci->AR_resp_buf_th_ind;
+ offset = ohci->AR_resp_buf_th_offset;
+
+ rescount = ohci->AR_resp_prg[idx]->status&0xffff;
+ ohci->AR_resp_bytes_left += AR_RESP_BUF_SIZE - rescount - offset;
+ offset = AR_RESP_BUF_SIZE - rescount;
+
+ if (!rescount) { /* We cross a buffer boundary */
+ idx = (idx+1) % AR_RESP_NUM_DESC;
+
+#if 0
+ /* This bit of code does not work */
+ /* Let's see how many bytes were written in the async response
+ receive buf since last interrupt. This is done by finding
+ the next active context (See OHCI Spec p91) */
+ while (ohci->AR_resp_bytes_left <= AR_RESP_TOTAL_BUF_SIZE) {
+ if (ohci->AR_resp_prg[idx]->status&0x04000000) break;
+ idx = (idx+1) % AR_RESP_NUM_DESC;
+ PRINT(KERN_INFO,ohci->id,"crossing more than one buffer boundary !!!");
+ ohci->AR_resp_bytes_left += AR_RESP_BUF_SIZE;
}
+#endif
+ /* ASSUMPTION: only one buffer boundary is crossed */
+ rescount = ohci->AR_resp_prg[idx]->status&0xffff;
+ offset = AR_RESP_BUF_SIZE - rescount;
+ ohci->AR_resp_bytes_left += offset;
}
+ if (offset==AR_RESP_BUF_SIZE) {
+ offset=0;
+ idx = (idx+1) % AR_RESP_NUM_DESC;
+ }
+ ohci->AR_resp_buf_th_ind = idx;
+ ohci->AR_resp_buf_th_offset = offset;
- reg_write(ohci, OHCI1394_AsRspRcvCommandPtr,
- virt_to_bus(ohci->AR_resp_prg)|0x00000001);
- ohci->AR_resp_prg->status=AR_RESP_BUF_SIZE;
- reg_write(ohci, OHCI1394_AsRspRcvContextControlSet, 0x8000);
+ /* is buffer processing too slow? (all buffers used) */
+ if (ohci->AR_resp_bytes_left > AR_RESP_TOTAL_BUF_SIZE) {
+ stop_ar_resp_context(ohci,"async response receive processing too slow");
+ spin_unlock(&ohci->AR_resp_lock);
+ return;
+ }
+ spin_unlock(&ohci->AR_resp_lock);
- /* ---------------- end of FIXME --------------------------*/
+ /* queue bottom half in immediate queue */
+ queue_task(&ohci->AR_resp_pdl_task, &tq_immediate);
+ mark_bh(IMMEDIATE_BH);
}
if (event & OHCI1394_isochRx) {
quadlet_t isoRecvIntEvent;
@@ -826,8 +863,10 @@ static void ohci_irq_handler(int irq, void *dev_id,
send_next_async(ohci);
}
spin_unlock(&ohci->async_queue_lock);
+#if 0
PRINT(KERN_INFO,ohci->id,
"packet sent with ack code %d",ack);
+#endif
hpsb_packet_sent(host, packet, ack);
} else
PRINT(KERN_INFO,ohci->id,
@@ -839,6 +878,129 @@ static void ohci_irq_handler(int irq, void *dev_id,
ohci->NumInterrupts++;
}
+
+/* This is the bottom half that processes async response receive descriptor buffers. */
+static void ohci_ar_resp_proc_desc(void *data)
+{
+ quadlet_t *buf_ptr;
+ char *split_ptr;
+ unsigned int split_left;
+ struct ti_ohci *ohci= (struct ti_ohci*)data;
+ unsigned int packet_length;
+ unsigned int idx,offset,tcode;
+ unsigned long flags;
+ char msg[256];
+
+ spin_lock_irqsave(&ohci->AR_resp_lock, flags);
+
+ idx = ohci->AR_resp_buf_bh_ind;
+ offset = ohci->AR_resp_buf_bh_offset;
+
+ buf_ptr = ohci->AR_resp_buf[idx];
+ buf_ptr += offset/4;
+
+ while(ohci->AR_resp_bytes_left > 0) {
+
+ /* check to see if a fatal error occurred */
+ if ((ohci->AR_resp_prg[idx]->status >> 16) & 0x800) {
+ sprintf(msg,"fatal async response receive error -- status is %d",
+ ohci->AR_resp_prg[idx]->status & 0x1F);
+ stop_ar_resp_context(ohci, msg);
+ spin_unlock_irqrestore(&ohci->AR_resp_lock, flags);
+ return;
+ }
+
+ spin_unlock_irqrestore(&ohci->AR_resp_lock, flags);
+
+ /* Let's see what kind of packet is in there */
+ tcode = (buf_ptr[0]>>4)&0xf;
+ if (tcode==2) /* no-data receive */
+ packet_length=16;
+ else if (tcode==6) /* quadlet receive */
+ packet_length=20;
+ else if (tcode==7) { /* block receive */
+ /* Where is the data length ? */
+ if (offset+12>=AR_RESP_BUF_SIZE)
+ packet_length=(ohci->AR_resp_buf[(idx+1)%AR_RESP_NUM_DESC]
+ [3-(AR_RESP_BUF_SIZE-offset)/4]>>16)+20;
+ else
+ packet_length=(buf_ptr[3]>>16)+20;
+ if (packet_length % 4)
+ packet_length += 4 - (packet_length % 4);
+ }
+ else /* something is wrong */ {
+ sprintf(msg,"unexpected packet tcode %d in async response receive buffer",tcode);
+ stop_ar_resp_context(ohci,msg);
+ return;
+ }
+ if ((offset+packet_length)>AR_RESP_BUF_SIZE) {
+ /* we have a split packet */
+ if (packet_length>AR_RESP_SPLIT_PACKET_BUF_SIZE) {
+ sprintf(msg,"packet size %d bytes exceed split packet buffer size %d bytes",
+ packet_length,AR_RESP_SPLIT_PACKET_BUF_SIZE);
+ stop_ar_resp_context(ohci, msg);
+ return;
+ }
+ split_left = packet_length;
+ split_ptr = (char *)ohci->AR_resp_spb;
+ while (split_left>0) {
+ memcpy(split_ptr,buf_ptr,AR_RESP_BUF_SIZE-offset);
+ split_left -= AR_RESP_BUF_SIZE-offset;
+ split_ptr += AR_RESP_BUF_SIZE-offset;
+ ohci->AR_resp_prg[idx]->status = AR_RESP_BUF_SIZE;
+ idx = (idx+1) % AR_RESP_NUM_DESC;
+ buf_ptr = ohci->AR_resp_buf[idx];
+ offset=0;
+ while (split_left >= AR_RESP_BUF_SIZE) {
+ memcpy(split_ptr,buf_ptr,AR_RESP_BUF_SIZE);
+ split_ptr += AR_RESP_BUF_SIZE;
+ split_left -= AR_RESP_BUF_SIZE;
+ ohci->AR_resp_prg[idx]->status = AR_RESP_BUF_SIZE;
+ idx = (idx+1) % AR_RESP_NUM_DESC;
+ buf_ptr = ohci->AR_resp_buf[idx];
+ }
+ if (split_left>0) {
+ memcpy(split_ptr,buf_ptr,split_left);
+ offset = split_left;
+ split_left=0;
+ buf_ptr += split_left/4;
+ }
+ }
+#if 0
+ PRINT(KERN_INFO,ohci->id,"AR resp: received split packet tcode=%d length=%d",
+ tcode,packet_length);
+#endif
+ hpsb_packet_received(ohci->host, ohci->AR_resp_spb, packet_length);
+ ohci->AR_resp_bytes_left -= packet_length;
+ }
+ else {
+#if 0
+ PRINT(KERN_INFO,ohci->id,"AR resp: received packet tcode=%d length=%d",
+ tcode,packet_length);
+#endif
+ hpsb_packet_received(ohci->host, buf_ptr, packet_length);
+ offset += packet_length;
+ buf_ptr += packet_length/4;
+ ohci->AR_resp_bytes_left -= packet_length;
+ if (offset==AR_RESP_BUF_SIZE) {
+ ohci->AR_resp_prg[idx]->status = AR_RESP_BUF_SIZE;
+ idx = (idx+1) % AR_RESP_NUM_DESC;
+ buf_ptr = ohci->AR_resp_buf[idx];
+ offset=0;
+ }
+ }
+
+ }
+
+ if (ohci->AR_resp_bytes_left<0)
+ stop_ar_resp_context(ohci, "Sync problem in AR resp dma buffer");
+
+ ohci->AR_resp_buf_bh_ind = idx;
+ ohci->AR_resp_buf_bh_offset = offset;
+
+ spin_unlock_irqrestore(&ohci->AR_resp_lock, flags);
+}
+
/* This is the bottom half that processes iso receive descriptor buffers. */
static void ohci_ir_proc_desc(void *data)
{
@@ -1023,23 +1185,61 @@ static int add_card(struct pci_dev *dev)
FAIL("failed to allocate DMA buffer for self-id packets");
}
- /* AR dma buffer allocation */
- ohci->AR_resp_buf = kmalloc(AR_RESP_BUF_SIZE, GFP_KERNEL);
- if (ohci->AR_resp_buf != NULL) {
- memset(ohci->AR_resp_buf, 0, AR_RESP_BUF_SIZE);
- } else {
- FAIL("failed to allocate AR response DMA buffer");
+ /* AR dma buffer and program allocation */
+ ohci->AR_resp_buf=
+ kmalloc(AR_RESP_NUM_DESC * sizeof(quadlet_t*),
+ GFP_KERNEL);
+
+ if (ohci->AR_resp_buf == NULL) {
+ FAIL("failed to allocate AR response receive DMA buffer");
}
- /* AR dma program allocation */
- ohci->AR_resp_prg = (struct dma_cmd *) kmalloc(AR_RESP_PRG_SIZE,
- GFP_KERNEL);
- if (ohci->AR_resp_prg != NULL) {
- memset(ohci->AR_resp_prg, 0, AR_RESP_PRG_SIZE);
- } else {
- FAIL("failed to allocate AR response DMA program");
+ ohci->AR_resp_prg=
+ kmalloc(AR_RESP_NUM_DESC * sizeof(struct dma_cmd*),
+ GFP_KERNEL);
+
+ if (ohci->AR_resp_prg == NULL) {
+ FAIL("failed to allocate AR response receive DMA program");
+ }
+
+ ohci->AR_resp_spb= kmalloc(AR_RESP_SPLIT_PACKET_BUF_SIZE, GFP_KERNEL);
+
+ if (ohci->AR_resp_spb == NULL) {
+ FAIL("failed to allocate AR response split packet buffer");
+ }
+
+ for (i= 0; i < AR_RESP_NUM_DESC; i++) {
+ ohci->AR_resp_buf[i]= kmalloc(AR_RESP_BUF_SIZE, GFP_KERNEL);
+
+ if (ohci->AR_resp_buf[i] != NULL) {
+ memset(ohci->AR_resp_buf[i], 0, AR_RESP_BUF_SIZE);
+ } else {
+ FAIL("failed to allocate AR response DMA buffer");
+ }
+
+ ohci->AR_resp_prg[i]= kmalloc(sizeof(struct dma_cmd),
+ GFP_KERNEL);
+
+ if (ohci->AR_resp_prg[i] != NULL) {
+ memset(ohci->AR_resp_prg[i], 0,
+ sizeof(struct dma_cmd));
+ } else {
+ FAIL("failed to allocate AR response DMA buffer");
+ }
+
}
+ ohci->AR_resp_buf_th_ind = 0;
+ ohci->AR_resp_buf_th_offset = 0;
+ ohci->AR_resp_buf_bh_ind = 0;
+ ohci->AR_resp_buf_bh_offset = 0;
+ ohci->AR_resp_bytes_left = 0;
+ spin_lock_init(&ohci->AR_resp_lock);
+
+ /* initialize AR response receive task */
+ ohci->AR_resp_pdl_task.routine= ohci_ar_resp_proc_desc;
+ ohci->AR_resp_pdl_task.data= (void*)ohci;
+
/* AT dma program allocation */
ohci->AT_req_prg = (struct dma_cmd *) kmalloc(AT_REQ_PRG_SIZE,
GFP_KERNEL);
@@ -1129,8 +1329,12 @@ static int add_card(struct pci_dev *dev)
p += sprintf(p,fmt,reg_read(ohci, reg0),\
reg_read(ohci, reg1),reg_read(ohci, reg2));
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+static int ohci_get_status(char *buf)
+#else
int ohci_get_info(char *buf, char **start, off_t fpos,
int length, int dummy)
+#endif
{
struct ti_ohci *ohci=&cards[0];
struct hpsb_host *host=ohci->host;
@@ -1165,15 +1369,23 @@ int ohci_get_info(char *buf, char **start, off_t fpos,
host->is_irm ? "iso_res_mgr" : "",
host->is_busmgr ? "bus_mgr" : "");
- p += sprintf(p,"\n### ohci data ###\n");
- p += sprintf(p,"AR_resp_buf : %p AR_resp_prg: %p\n",
- ohci->AR_resp_buf, ohci->AR_resp_prg);
-
+ p += sprintf(p,"\n---Iso Receive DMA---\n");
for (i= 0; i < IR_NUM_DESC; i++) {
p += sprintf(p, "IR_recv_buf[%d] : %p IR_recv_prg[%d]: %p\n",
i, ohci->IR_recv_buf[i], i, ohci->IR_recv_prg[i]);
}
+
+ p += sprintf(p,"\n---Async Reponse Receive DMA---\n");
+ for (i= 0; i < AR_RESP_NUM_DESC; i++) {
+ p += sprintf(p, "AR_resp_buf[%d] : %p AR_resp_prg[%d]: %p\n",
+ i, ohci->AR_resp_buf[i], i, ohci->AR_resp_prg[i]);
+ }
+ p += sprintf(p, "Current AR resp buf in irq handler: %d offset: %d\n",
+ ohci->AR_resp_buf_th_ind,ohci->AR_resp_buf_th_offset);
+ p += sprintf(p, "Current AR resp buf in bottom half: %d offset: %d\n",
+ ohci->AR_resp_buf_bh_ind,ohci->AR_resp_buf_bh_offset);
+
/* ----- Register Dump ----- */
p += sprintf(p,"\n### HC Register dump ###\n");
SR("Version : %08x GUID_ROM : %08x ATRetries : %08x\n",
@@ -1242,12 +1454,27 @@ int ohci_get_info(char *buf, char **start, off_t fpos,
phyreg&0x3f);
#endif
+#if 0
p += sprintf(p,"AR_resp_prg ctrl: %08x\n",ohci->AR_resp_prg->control);
p += sprintf(p,"AR_resp_prg status: %08x\n",ohci->AR_resp_prg->status);
+#endif
return p - buf;
}
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+static int ohci1394_read_proc(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+ int len = ohci_get_status(page);
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len>count) len = count;
+ if (len<0) len = 0;
+ return len;
+}
+#else
struct proc_dir_entry ohci_proc_entry =
{
0, /* Inode number - dynamic */
@@ -1261,18 +1488,36 @@ struct proc_dir_entry ohci_proc_entry =
ohci_get_info, /* The read function for this file */
NULL
};
-#endif
+#endif /* LINUX_VERSION_CODE */
+#endif /* CONFIG_PROC_FS */
static void remove_card(struct ti_ohci *ohci)
{
if (ohci->registers)
iounmap(ohci->registers);
- if (ohci->AR_resp_buf)
- kfree(ohci->AR_resp_buf);
- if (ohci->AR_resp_prg)
- kfree(ohci->AR_resp_prg);
+
+ /* Free AR response buffers and programs */
+ if (ohci->AR_resp_buf) {
+ int i;
+ for (i= 0; i < AR_RESP_NUM_DESC; i++) {
+ kfree(ohci->AR_resp_buf[i]);
+ }
+ kfree(ohci->AR_resp_buf);
+ }
+ if (ohci->AR_resp_prg) {
+ int i;
+ for (i= 0; i < AR_RESP_NUM_DESC; i++) {
+ kfree(ohci->AR_resp_prg[i]);
+ }
+ kfree(ohci->AR_resp_prg);
+ }
+ kfree(ohci->AR_resp_spb);
+
+ /* Free AT request buffer and program */
if (ohci->AT_req_prg)
kfree(ohci->AT_req_prg);
+
+ /* Free Iso receive buffers and programs */
if (ohci->IR_recv_buf) {
int i;
for (i= 0; i < IR_NUM_DESC; i++) {
@@ -1288,11 +1533,16 @@ static void remove_card(struct ti_ohci *ohci)
kfree(ohci->IR_recv_prg);
}
kfree(ohci->IR_spb);
+
+ /* Free self-id buffer */
if (ohci->self_id_buffer)
kfree(ohci->self_id_buffer);
+
+ /* Free config rom */
if (ohci->csr_config_rom)
kfree(ohci->csr_config_rom);
+ /* Free the IRQ */
free_irq(ohci->dev->irq, ohci);
ohci->state = 0;
@@ -1327,11 +1577,15 @@ static int init_driver()
}
#ifdef CONFIG_PROC_FS
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+ create_proc_read_entry ("ohci1394", 0, NULL, ohci1394_read_proc, NULL);
+#else
if (proc_register(&proc_root, &ohci_proc_entry)) {
PRINT_G(KERN_ERR, "unable to register proc file\n");
return -EIO;
}
#endif
+#endif
return 0;
}
@@ -1384,8 +1638,12 @@ void cleanup_module(void)
{
hpsb_unregister_lowlevel(get_ohci_template());
#ifdef CONFIG_PROC_FS
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0)
+ remove_proc_entry ("ohci1394", NULL);
+#else
proc_unregister(&proc_root, ohci_proc_entry.low_ino);
#endif
+#endif
PRINT_G(KERN_INFO, "removed " OHCI1394_DRIVER_NAME " module\n");
}
diff --git a/drivers/ieee1394/ohci1394.h b/drivers/ieee1394/ohci1394.h
index c6d7f469a..35d8fa2af 100644
--- a/drivers/ieee1394/ohci1394.h
+++ b/drivers/ieee1394/ohci1394.h
@@ -20,9 +20,15 @@
#define MAX_OHCI1394_CARDS 4
-#define AR_RESP_BUF_SIZE 4096
-#define AR_RESP_PRG_SIZE 256
-#define AT_REQ_PRG_SIZE 256
+#define OHCI1394_MAX_AT_REQ_RETRIES 1
+#define OHCI1394_MAX_AT_RESP_RETRIES 1
+#define OHCI1394_MAX_PHYS_RESP_RETRIES 4
+
+#define AR_RESP_NUM_DESC 4 /* number of AR resp descriptors */
+#define AR_RESP_BUF_SIZE 4096 /* size of AR resp buffers */
+#define AR_RESP_SPLIT_PACKET_BUF_SIZE 256 /* split packet buffer */
+#define AR_RESP_TOTAL_BUF_SIZE (AR_RESP_BUF_SIZE * AR_RESP_NUM_DESC)
+#define AT_REQ_PRG_SIZE 256
#define IR_RECV_BUF_SIZE 4096 /* 4096 bytes/buffer */
#define IR_SPLIT_PACKET_BUF_SIZE 8192 /* size of buffer for split packets */
@@ -49,8 +55,18 @@ struct ti_ohci {
quadlet_t *csr_config_rom; /* buffer for csr config rom */
/* asynchronous receive */
- struct dma_cmd *AR_resp_prg;
- quadlet_t *AR_resp_buf;
+ struct dma_cmd **AR_resp_prg;
+ quadlet_t **AR_resp_buf;
+ unsigned int AR_resp_buf_bh_ind;
+ unsigned int AR_resp_buf_bh_offset;
+ unsigned int AR_resp_buf_th_ind;
+ unsigned int AR_resp_buf_th_offset;
+ int AR_resp_bytes_left;
+ quadlet_t *AR_resp_spb;
+ spinlock_t AR_resp_lock;
+
+ /* async receive task */
+ struct tq_struct AR_resp_pdl_task;
/* asynchronous transmit */
struct dma_cmd *AT_req_prg;
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c
index 596f95219..adc45896d 100644
--- a/drivers/ieee1394/raw1394.c
+++ b/drivers/ieee1394/raw1394.c
@@ -495,8 +495,8 @@ static int handle_local_request(struct file_info *fi,
if (req->req.length == 8) {
req->req.error = highlevel_lock(fi->host, req->data,
- addr, req->data[0],
- req->data[1],
+ addr, req->data[1],
+ req->data[0],
req->req.misc);
req->req.length = 4;
} else {
@@ -567,6 +567,32 @@ static int handle_remote_request(struct file_info *fi,
break;
case RAW1394_REQ_LOCK:
+ if ((req->req.misc != EXTCODE_FETCH_ADD)
+ && (req->req.misc != EXTCODE_LITTLE_ADD)) {
+ if (req->req.length != 4) {
+ req->req.error = RAW1394_ERROR_INVALID_ARG;
+ break;
+ }
+ } else {
+ if (req->req.length != 8) {
+ req->req.error = RAW1394_ERROR_INVALID_ARG;
+ break;
+ }
+ }
+
+ packet = hpsb_make_lockpacket(fi->host, node, addr,
+ req->req.misc);
+ if (!packet) return -ENOMEM;
+
+ if (copy_from_user(packet->data, req->req.sendb,
+ req->req.length)) {
+ req->req.error = RAW1394_ERROR_MEMFAULT;
+ break;
+ }
+
+ req->req.length = 4;
+ break;
+
case RAW1394_REQ_LOCK64:
default:
req->req.error = RAW1394_ERROR_STATE_ORDER;
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 03864c4ba..232075634 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -115,7 +115,7 @@ obj-$(CONFIG_NET) += Space.o setup.o net_init.o loopback.o
obj-$(CONFIG_SEEQ8005) += seeq8005.o
obj-$(CONFIG_ETHERTAP) += ethertap.o
obj-$(CONFIG_NET_SB1000) += sb1000.o
-obj-$(CONFIG_DAYNAPORT) += daynaport.o 8390.o
+obj-$(CONFIG_MAC8390) += daynaport.o 8390.o
obj-$(CONFIG_APNE) += apne.o 8390.o
obj-$(CONFIG_PCMCIA_PCNET) += 8390.o
obj-$(CONFIG_SHAPER) += shaper.o
@@ -248,6 +248,8 @@ obj-$(CONFIG_IPDDP) += ipddp.o
obj-$(CONFIG_RCPCI) += rcpci.o
obj-$(CONFIG_MACE) += mace.o
obj-$(CONFIG_MACSONIC) += macsonic.o
+obj-$(CONFIG_MACMACE) += macmace.o
+obj-$(CONFIG_MAC89x0) += mac89x0.o
obj-$(CONFIG_BMAC) += bmac.o
obj-$(CONFIG_NCR885E) += ncr885e.o
obj-$(CONFIG_ADAPTEC_STARFIRE) += starfire.o
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index dc18256ce..52c3a23d0 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -106,7 +106,13 @@ extern int dec_lance_probe(struct net_device *);
extern int mvme147lance_probe(struct net_device *dev);
extern int tc515_probe(struct net_device *dev);
extern int lance_probe(struct net_device *dev);
-extern int mac_onboard_sonic_probe(struct net_device *dev);
+extern int mace68k_probe(struct net_device *dev);
+extern int macsonic_probe(struct net_device *dev);
+extern int mac8390_probe(struct net_device *dev);
+extern int mac89x0_probe(struct net_device *dev);
+
+ /* Gigabit Ethernet adapters */
+ extern int yellowfin_probe(struct net_device *dev);
/* Detachable devices ("pocket adaptors") */
extern int atp_init(struct net_device *);
@@ -356,8 +362,17 @@ struct devprobe m68k_probes[] __initdata = {
#ifdef CONFIG_MVME147_NET /* MVME147 internal Ethernet */
{mvme147lance_probe, 0},
#endif
-#ifdef CONFIG_MACSONIC /* Mac 68k Quadra builtin Ethernet */
- {mac_onboard_sonic_probe, 0},
+#ifdef CONFIG_MACMACE /* Mac 68k Quadra AV builtin Ethernet */
+ {mace68k_probe, 0},
+#endif
+#ifdef CONFIG_MACSONIC /* Mac SONIC-based Ethernet of all sorts */
+ {macsonic_probe, 0},
+#endif
+#ifdef CONFIG_MAC8390 /* NuBus NS8390-based cards */
+ {mac8390_probe, 0},
+#endif
+#ifdef CONFIG_MAC89x0
+ {mac89x0_probe, 0},
#endif
{NULL, 0},
};
diff --git a/drivers/net/cs89x0.h b/drivers/net/cs89x0.h
index 42776088f..7e78805af 100644
--- a/drivers/net/cs89x0.h
+++ b/drivers/net/cs89x0.h
@@ -14,6 +14,8 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#include <linux/config.h>
+
#define PP_ChipID 0x0000 /* offset 0h -> Corp -ID */
/* offset 2h -> Model/Product Number */
/* offset 3h -> Chip Revision Number */
@@ -77,6 +79,12 @@
#define ADD_MASK 0x3000 /* Mask it use of the ADD_PORT register */
#define ADD_SIG 0x3000 /* Expected ID signature */
+/* On Macs, we only need use the ISA I/O stuff until we do MEMORY_ON */
+#ifdef CONFIG_MAC
+#define LCSLOTBASE 0xfee00000
+#define MMIOBASE 0x40000
+#endif
+
#define CHIP_EISA_ID_SIG 0x630E /* Product ID Code for Crystal Chip (CS8900 spec 4.3) */
#ifdef IBMEIPKT
diff --git a/drivers/net/daynaport.c b/drivers/net/daynaport.c
index 02ebff8b6..724369bb8 100644
--- a/drivers/net/daynaport.c
+++ b/drivers/net/daynaport.c
@@ -1,4 +1,4 @@
-/* mac_ns8390.c: A Macintosh 8390 based ethernet driver for linux. */
+/* daynaport.c: A Macintosh 8390 based ethernet driver for linux. */
/*
Derived from code:
@@ -15,14 +15,20 @@
The block output routines may be wrong for non Dayna
cards
- Reading MAC addresses
-*/
+ Fix this driver so that it will attempt to use the info
+ (i.e. iobase, iosize) given to it by the new and improved
+ NuBus code.
+
+ Despite its misleading filename, this driver is not Dayna-specific
+ anymore. */
+/* Cabletron E6100 card support added by Tony Mantler (eek@escape.ca) April 1999 */
static const char *version =
- "mac_ns8390.c:v0.01 7/5/97 Alan Cox (Alan.Cox@linux.org)\n";
+ "daynaport.c: v0.02 1999-05-17 Alan Cox (Alan.Cox@linux.org) and others\n";
+static int version_printed = 0;
#include <linux/module.h>
-
+#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/errno.h>
@@ -31,20 +37,26 @@ static const char *version =
#include <asm/io.h>
#include <asm/system.h>
#include <asm/hwtest.h>
+#include <asm/macints.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include "8390.h"
-int ns8390_probe1(struct net_device *dev, int word16, char *name, int id, int prom);
+extern int console_loglevel;
+
+int ns8390_probe1(struct net_device *dev, int word16, char *name, int id,
+ int prom, struct nubus_dev *ndev);
static int ns8390_open(struct net_device *dev);
static void ns8390_no_reset(struct net_device *dev);
static int ns8390_close_card(struct net_device *dev);
+/* Interlan */
static void interlan_reset(struct net_device *dev);
+/* Dayna */
static void dayna_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
int ring_page);
static void dayna_block_input(struct net_device *dev, int count,
@@ -52,6 +64,7 @@ static void dayna_block_input(struct net_device *dev, int count,
static void dayna_block_output(struct net_device *dev, int count,
const unsigned char *buf, const int start_page);
+/* Sane (32-bit chunk memory read/write) */
static void sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
int ring_page);
static void sane_block_input(struct net_device *dev, int count,
@@ -59,6 +72,7 @@ static void sane_block_input(struct net_device *dev, int count,
static void sane_block_output(struct net_device *dev, int count,
const unsigned char *buf, const int start_page);
+/* Slow Sane (16-bit chunk memory read/write) */
static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
int ring_page);
static void slow_sane_block_input(struct net_device *dev, int count,
@@ -71,6 +85,10 @@ static void slow_sane_block_output(struct net_device *dev, int count,
#define WD03_STOP_PG 0x20 /* Last page +1 of RX ring */
#define WD13_STOP_PG 0x40 /* Last page +1 of RX ring */
+#define CABLETRON_RX_START_PG 0x00 /* First page of RX buffer */
+#define CABLETRON_RX_STOP_PG 0x30 /* Last page +1 of RX ring */
+#define CABLETRON_TX_START_PG CABLETRON_RX_STOP_PG /* First page of TX buffer */
+
#define DAYNA_MAC_BASE 0xf0007
#define DAYNA_8390_BASE 0x80000 /* 3 */
@@ -81,9 +99,14 @@ static void slow_sane_block_output(struct net_device *dev, int count,
#define APPLE_8390_MEM 0xD0000
#define APPLE_MEMSIZE 8192 /* FIXME: need to dynamically check */
-#define KINETICS_8390_BASE 0x80003
-#define KINETICS_8390_MEM 0x00000
+#define KINETICS_MAC_BASE 0xf0004 /* first byte of each long */
+#define KINETICS_8390_BASE 0x80000
+#define KINETICS_8390_MEM 0x00000 /* first word of each long */
#define KINETICS_MEMSIZE 8192 /* FIXME: need to dynamically check */
+/*#define KINETICS_MEMSIZE (0x10000/2) * CSA: on the board I have, at least */
+
+#define CABLETRON_8390_BASE 0x90000
+#define CABLETRON_8390_MEM 0x00000
static int test_8390(volatile char *ptr, int scale)
{
@@ -113,34 +136,59 @@ static int test_8390(volatile char *ptr, int scale)
* Identify the species of NS8390 card/driver we need
*/
-#define NS8390_DAYNA 1
-#define NS8390_INTERLAN 2
-#define NS8390_KINETICS 3
-#define NS8390_APPLE 4
-#define NS8390_FARALLON 5
-#define NS8390_ASANTE 6
+enum mac8390_type {
+ NS8390_DAYNA,
+ NS8390_INTERLAN,
+ NS8390_KINETICS,
+ NS8390_APPLE,
+ NS8390_FARALLON,
+ NS8390_ASANTE,
+ NS8390_CABLETRON
+};
-int ns8390_ident(struct nubus_type *nb)
+int __init ns8390_ident(struct nubus_dev* ndev)
{
- /* It appears anything with a software type of 0 is an apple
- compatible - even if the hardware matches others */
-
- if(nb->DrSW==0x0001 || nb->DrSW==0x0109 || nb->DrSW==0x0000 || nb->DrSW==0x0100)
- return NS8390_APPLE;
-
+ /* This really needs to be tested and tested hard. */
+
+ /* Summary of what we know so far --
+ * SW: 0x0104 -- asante, 16 bit, back4_offsets
+ * SW: 0x010b -- daynaport, 16 bit, fwrd4_offsets
+ * SW: 0x010c -- farallon, 16 bit, back4_offsets, no long word access
+ * SW: 0x011a -- focus, [no details yet]
+ * SW: ?????? -- interlan, 16 bit, back4_offsets, funny reset
+ * SW: ?????? -- kinetics, 8 bit, back4_offsets
+ * -- so i've this hypothesis going that says DrSW&1 says whether the
+ * map is forward or backwards -- and maybe DrSW&256 says what the
+ * register spacing is -- for all cards that report a DrSW in some
+ * range.
+ * This would allow the "apple compatible" driver to drive many
+ * seemingly different types of cards. More DrSW info is needed
+ * to investigate this properly. [CSA, 21-May-1999]
+ */
/* Dayna ex Kinetics board */
- if(nb->DrHW==0x0103)
+ if(ndev->dr_sw == NUBUS_DRSW_DAYNA)
return NS8390_DAYNA;
-
- /* Asante board */
- if(nb->DrHW==0x0104)
+ if(ndev->dr_sw == NUBUS_DRSW_ASANTE)
return NS8390_ASANTE;
- if(nb->DrHW==0x0100)
- return NS8390_INTERLAN;
- if(nb->DrHW==0x0106)
- return NS8390_KINETICS;
- if(nb->DrSW==0x010C)
+ if(ndev->dr_sw == NUBUS_DRSW_FARALLON) /* farallon or sonic systems */
return NS8390_FARALLON;
+ if(ndev->dr_sw == NUBUS_DRSW_KINETICS)
+ return NS8390_KINETICS;
+ /* My ATI Engineering card with this combination crashes the */
+ /* driver trying to xmit packets. Best not touch it for now. */
+ /* - 1999-05-20 (funaho@jurai.org) */
+ if(ndev->dr_sw == NUBUS_DRSW_FOCUS)
+ return -1;
+
+ /* Check the HW on this one, because it shares the same DrSW as
+ the on-board SONIC chips */
+ if(ndev->dr_hw == NUBUS_DRHW_CABLETRON)
+ return NS8390_CABLETRON;
+ /* does anyone have one of these? */
+ if(ndev->dr_hw == NUBUS_DRHW_INTERLAN)
+ return NS8390_INTERLAN;
+
+ /* FIXME: what do genuine Apple boards look like? */
return -1;
}
@@ -148,7 +196,7 @@ int ns8390_ident(struct nubus_type *nb)
* Memory probe for 8390 cards
*/
-int apple_8390_mem_probe(volatile unsigned short *p)
+int __init apple_8390_mem_probe(volatile unsigned short *p)
{
int i, j;
/*
@@ -192,61 +240,79 @@ int apple_8390_mem_probe(volatile unsigned short *p)
/*
* Probe for 8390 cards.
* The ns8390_probe1() routine initializes the card and fills the
- * station address field. On entry base_addr is set, irq is set
- * (These come from the nubus probe code). dev->mem_start points
+ * station address field.
+ *
+ * The NuBus interface has changed! We now scan for these somewhat
+ * like how the PCI and Zorro drivers do. It's not clear whether
+ * this is actually better, but it makes things more consistent.
+ *
+ * dev->mem_start points
* at the memory ring, dev->mem_end gives the end of it.
*/
-int ns8390_probe(struct nubus_device_specifier *d, int slot, struct nubus_type *match)
+int __init mac8390_probe(struct net_device *dev)
{
- struct net_device *dev;
+ static int slots = 0;
volatile unsigned short *i;
volatile unsigned char *p;
int plen;
int id;
+ static struct nubus_dev* ndev = NULL;
+
+ /* Find the first card that hasn't already been seen */
+ while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK,
+ NUBUS_TYPE_ETHERNET, ndev)) != NULL) {
+ /* Have we seen it already? */
+ if (slots & (1<<ndev->board->slot))
+ continue;
+ slots |= 1<<ndev->board->slot;
+
+ /* Is it one of ours? */
+ if ((id = ns8390_ident(ndev)) != -1)
+ break;
+ }
- if(match->category!=NUBUS_CAT_NETWORK || match->type!=1)
- return -ENODEV;
- /* Ok so it is an ethernet network device */
- if((id=ns8390_ident(match))==-1)
- {
- printk("Ethernet but type unknown %d\n",match->DrHW);
+ /* Hm. No more cards, then */
+ if (ndev == NULL)
return -ENODEV;
+
+ dev = init_etherdev(dev, 0);
+
+ if (!version_printed) {
+ printk(KERN_INFO "%s", version);
+ version_printed = 1;
}
- dev = init_etherdev(0, 0);
- if(dev==NULL)
- return -ENOMEM;
/*
* Dayna specific init
*/
if(id==NS8390_DAYNA)
{
- dev->base_addr=(int)(nubus_slot_addr(slot)+DAYNA_8390_BASE);
- dev->mem_start=(int)(nubus_slot_addr(slot)+DAYNA_8390_MEM);
- dev->mem_end=dev->mem_start+DAYNA_MEMSIZE; /* 8K it seems */
+ dev->base_addr = (int)(ndev->board->slot_addr+DAYNA_8390_BASE);
+ dev->mem_start = (int)(ndev->board->slot_addr+DAYNA_8390_MEM);
+ dev->mem_end = dev->mem_start+DAYNA_MEMSIZE; /* 8K it seems */
- printk("daynaport: testing board: ");
-
+ printk(KERN_INFO "%s: daynaport. testing board: ", dev->name);
+
printk("memory - ");
-
- i=(void *)dev->mem_start;
+
+ i = (void *)dev->mem_start;
memset((void *)i,0xAA, DAYNA_MEMSIZE);
while(i<(volatile unsigned short *)dev->mem_end)
{
if(*i!=0xAAAA)
goto membad;
- *i=0x5555;
- if(*i!=0x5555)
+ *i=0x5678; /* make sure we catch byte smearing */
+ if(*i!=0x5678)
goto membad;
i+=2; /* Skip a word */
}
-
+
printk("controller - ");
-
+
p=(void *)dev->base_addr;
plen=0;
-
+
while(plen<0x3FF00)
{
if(test_8390(p,0)==0)
@@ -263,26 +329,71 @@ int ns8390_probe(struct nubus_device_specifier *d, int slot, struct nubus_type *
if(plen==0x3FF00)
goto membad;
printk("OK\n");
- dev->irq=slot;
- if(ns8390_probe1(dev, 0, "dayna", id, -1)==0)
- return 0;
+ dev->irq = SLOT2IRQ(ndev->board->slot);
+ if(ns8390_probe1(dev, 0, "dayna", id, -1, ndev)==0)
+ return 0;
+ }
+ /* Cabletron */
+ if (id==NS8390_CABLETRON) {
+ int memsize = 16<<10; /* fix this */
+
+ dev->base_addr=(int)(ndev->board->slot_addr+CABLETRON_8390_BASE);
+ dev->mem_start=(int)(ndev->board->slot_addr+CABLETRON_8390_MEM);
+ dev->mem_end=dev->mem_start+memsize;
+ dev->irq = SLOT2IRQ(ndev->board->slot);
+
+ /* The base address is unreadable if 0x00 has been written to the command register */
+ /* Reset the chip by writing E8390_NODMA+E8390_PAGE0+E8390_STOP just to be sure */
+ i = (void *)dev->base_addr;
+ *i = 0x21;
+
+ printk(KERN_INFO "%s: cabletron: testing board: ", dev->name);
+ printk("%dK memory - ", memsize>>10);
+ i=(void *)dev->mem_start;
+ while(i<(volatile unsigned short *)(dev->mem_start+memsize))
+ {
+ *i=0xAAAA;
+ if(*i!=0xAAAA)
+ goto membad;
+ *i=0x5555;
+ if(*i!=0x5555)
+ goto membad;
+ i+=2; /* Skip a word */
+ }
+ printk("OK\n");
+
+ if(ns8390_probe1(dev, 1, "cabletron", id, -1, ndev)==0)
+ return 0;
}
/* Apple, Farallon, Asante */
- if(id==NS8390_APPLE|| id==NS8390_FARALLON || id==NS8390_ASANTE)
+ if(id==NS8390_APPLE || id==NS8390_FARALLON || id==NS8390_ASANTE)
{
int memsize;
-
- dev->base_addr=(int)(nubus_slot_addr(slot)+APPLE_8390_BASE);
- dev->mem_start=(int)(nubus_slot_addr(slot)+APPLE_8390_MEM);
-
+
+ dev->base_addr=(int)(ndev->board->slot_addr+APPLE_8390_BASE);
+ dev->mem_start=(int)(ndev->board->slot_addr+APPLE_8390_MEM);
+
memsize = apple_8390_mem_probe((void *)dev->mem_start);
-
+
dev->mem_end=dev->mem_start+memsize;
- dev->irq=slot;
- printk("apple/clone: testing board: ");
-
+ dev->irq = SLOT2IRQ(ndev->board->slot);
+
+ switch(id)
+ {
+ case NS8390_FARALLON:
+ printk(KERN_INFO "%s: farallon: testing board: ", dev->name);
+ break;
+ case NS8390_ASANTE:
+ printk(KERN_INFO "%s: asante: testing board: ", dev->name);
+ break;
+ case NS8390_APPLE:
+ default:
+ printk(KERN_INFO "%s: apple/clone: testing board: ", dev->name);
+ break;
+ }
+
printk("%dK memory - ", memsize>>10);
-
+
i=(void *)dev->mem_start;
memset((void *)i,0xAA, memsize);
while(i<(volatile unsigned short *)dev->mem_end)
@@ -295,51 +406,75 @@ int ns8390_probe(struct nubus_device_specifier *d, int slot, struct nubus_type *
i+=2; /* Skip a word */
}
printk("OK\n");
-
- if(id==NS8390_FARALLON)
+
+ switch (id)
{
- if(ns8390_probe1(dev, 1, "farallon", id, -1)==0)
+ case NS8390_FARALLON:
+ if(ns8390_probe1(dev, 1, "farallon", id, -1, ndev)==0)
return 0;
- }
- else
- {
- if(ns8390_probe1(dev, 1, "apple/clone", id, -1)==0)
- return 0;
+ break;
+ case NS8390_ASANTE:
+ if(ns8390_probe1(dev, 1, "asante", id, -1, ndev)==0)
+ return 0;
+ break;
+ case NS8390_APPLE:
+ default:
+ if(ns8390_probe1(dev, 1, "apple/clone", id, -1, ndev)==0)
+ return 0;
+ break;
}
}
/* Interlan */
if(id==NS8390_INTERLAN)
{
/* As apple and asante */
- dev->base_addr=(int)(nubus_slot_addr(slot)+APPLE_8390_BASE);
- dev->mem_start=(int)(nubus_slot_addr(slot)+APPLE_8390_MEM);
+ dev->base_addr=(int)(ndev->board->slot_addr+APPLE_8390_BASE);
+ dev->mem_start=(int)(ndev->board->slot_addr+APPLE_8390_MEM);
dev->mem_end=dev->mem_start+APPLE_MEMSIZE; /* 8K it seems */
- dev->irq=slot;
- if(ns8390_probe1(dev, 1, "interlan", id, -1)==0)
+ dev->irq = SLOT2IRQ(ndev->board->slot);
+ if(ns8390_probe1(dev, 1, "interlan", id, -1, ndev)==0)
return 0;
}
- /* Kinetics */
+ /* Kinetics (Shiva Etherport) */
if(id==NS8390_KINETICS)
{
- dev->base_addr=(int)(nubus_slot_addr(slot)+KINETICS_8390_BASE);
- dev->mem_start=(int)(nubus_slot_addr(slot)+KINETICS_8390_MEM);
+ dev->base_addr=(int)(ndev->board->slot_addr+KINETICS_8390_BASE);
+ dev->mem_start=(int)(ndev->board->slot_addr+KINETICS_8390_MEM);
dev->mem_end=dev->mem_start+KINETICS_MEMSIZE; /* 8K it seems */
- dev->irq=slot;
- if(ns8390_probe1(dev, 0, "kinetics", id, -1)==0)
+ dev->irq = SLOT2IRQ(ndev->board->slot);
+ if(ns8390_probe1(dev, 0, "kinetics", id, -1, ndev)==0)
return 0;
}
- kfree(dev);
+
+ /* We should hopefully not get here */
+ printk(KERN_ERR "Probe unsucessful.\n");
return -ENODEV;
-membad:
- printk("failed.\n");
- kfree(dev);
+
+ membad:
+ printk(KERN_ERR "failed at %p in %p - %p.\n", i,
+ (void *)dev->mem_start, (void *)dev->mem_end);
return -ENODEV;
}
-int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type, int promoff)
+int __init mac8390_ethernet_addr(struct nubus_dev* ndev,
+ unsigned char addr[6])
{
- static unsigned version_printed = 0;
+ struct nubus_dir dir;
+ struct nubus_dirent ent;
+
+ /* Get the functional resource for this device */
+ if (nubus_get_func_dir(ndev, &dir) == -1)
+ return -1;
+ if (nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent) == -1)
+ return -1;
+
+ nubus_get_rsrc_mem(addr, &ent, 6);
+ return 0;
+}
+int __init ns8390_probe1(struct net_device *dev, int word16, char *model_name,
+ int type, int promoff, struct nubus_dev *ndev)
+{
static u32 fwrd4_offsets[16]={
0, 4, 8, 12,
16, 20, 24, 28,
@@ -352,25 +487,19 @@ int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type
28, 24, 20, 16,
12, 8, 4, 0
};
+ static u32 fwrd2_offsets[16]={
+ 0, 2, 4, 6,
+ 8, 10, 12, 14,
+ 16, 18, 20, 22,
+ 24, 26, 28, 30
+ };
- unsigned char *prom=((unsigned char *)nubus_slot_addr(dev->irq))+promoff;
+ unsigned char *prom = (unsigned char*) ndev->board->slot_addr + promoff;
- if (ei_debug && version_printed++ == 0)
- printk(version);
-
- /* Snarf the interrupt now. There's no point in waiting since we cannot
- share a slot! and the board will usually be enabled. */
- if (nubus_request_irq(dev->irq, dev, ei_interrupt))
- {
- printk (" unable to get nubus IRQ %d.\n", dev->irq);
- return EAGAIN;
- }
-
/* Allocate dev->priv and fill in 8390 specific dev fields. */
if (ethdev_init(dev))
{
- printk (" unable to get memory for dev->priv.\n");
- nubus_free_irq(dev->irq);
+ printk ("%s: unable to get memory for dev->priv.\n", dev->name);
return -ENOMEM;
}
@@ -378,16 +507,25 @@ int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type
ei_status.name = model_name;
ei_status.word16 = word16;
- ei_status.tx_start_page = WD_START_PG;
- ei_status.rx_start_page = WD_START_PG + TX_PAGES;
- dev->rmem_start = dev->mem_start + TX_PAGES*256;
- ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
- dev->rmem_end = dev->mem_end;
+ if (type==NS8390_CABLETRON) {
+ /* Cabletron card puts the RX buffer before the TX buffer */
+ ei_status.tx_start_page = CABLETRON_TX_START_PG;
+ ei_status.rx_start_page = CABLETRON_RX_START_PG;
+ ei_status.stop_page = CABLETRON_RX_STOP_PG;
+ dev->rmem_start = dev->mem_start;
+ dev->rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256;
+ } else {
+ ei_status.tx_start_page = WD_START_PG;
+ ei_status.rx_start_page = WD_START_PG + TX_PAGES;
+ ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
+ dev->rmem_start = dev->mem_start + TX_PAGES*256;
+ dev->rmem_end = dev->mem_end;
+ }
if(promoff==-1) /* Use nubus resources ? */
{
- if(nubus_ethernet_addr(dev->irq /* slot */, dev->dev_addr))
+ if(mac8390_ethernet_addr(ndev, dev->dev_addr))
{
printk("mac_ns8390: MAC address not in resources!\n");
return -ENODEV;
@@ -400,7 +538,7 @@ int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type
/* These should go in the end I hope */
if(type==NS8390_DAYNA)
x=2;
- if(type==NS8390_INTERLAN)
+ if(type==NS8390_INTERLAN || type==NS8390_KINETICS)
x=4;
while(i<6)
{
@@ -412,12 +550,24 @@ int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type
}
}
- printk(" %s, IRQ %d, shared memory at %#lx-%#lx.\n",
- model_name, dev->irq, dev->mem_start, dev->mem_end-1);
+ printk(KERN_INFO "%s: %s in slot %X (type %s)\n",
+ dev->name, ndev->board->name, ndev->board->slot, model_name);
+ printk(KERN_INFO "MAC ");
+ {
+ int i;
+ for (i = 0; i < 6; i++) {
+ printk("%2.2x", dev->dev_addr[i]);
+ if (i < 5)
+ printk(":");
+ }
+ }
+ printk(" IRQ %d, shared memory at %#lx-%#lx.\n",
+ dev->irq, dev->mem_start, dev->mem_end-1);
switch(type)
{
case NS8390_DAYNA: /* Dayna card */
+ case NS8390_KINETICS: /* Kinetics -- 8 bit config, but 16 bit mem */
/* 16 bit, 4 word offsets */
ei_status.reset_8390 = &ns8390_no_reset;
ei_status.block_input = &dayna_block_input;
@@ -425,6 +575,15 @@ int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type
ei_status.get_8390_hdr = &dayna_get_8390_hdr;
ei_status.reg_offset = fwrd4_offsets;
break;
+ case NS8390_CABLETRON: /* Cabletron */
+ /* 16 bit card, register map is short forward */
+ ei_status.reset_8390 = &ns8390_no_reset;
+ /* Ctron card won't accept 32bit values read or written to it */
+ ei_status.block_input = &slow_sane_block_input;
+ ei_status.block_output = &slow_sane_block_output;
+ ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
+ ei_status.reg_offset = fwrd2_offsets;
+ break;
case NS8390_FARALLON:
case NS8390_APPLE: /* Apple/Asante/Farallon */
/* 16 bit card, register map is reversed */
@@ -450,6 +609,8 @@ int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type
ei_status.get_8390_hdr = &sane_get_8390_hdr;
ei_status.reg_offset = back4_offsets;
break;
+#if 0 /* i think this suffered code rot. my kinetics card has much
+ * different settings. -- CSA [22-May-1999] */
case NS8390_KINETICS: /* Kinetics */
/* 8bit card, map is forward */
ei_status.reset_8390 = &ns8390_no_reset;
@@ -458,6 +619,7 @@ int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type
ei_status.get_8390_hdr = &sane_get_8390_hdr;
ei_status.reg_offset = back4_offsets;
break;
+#endif
default:
panic("Detected a card I can't drive - whoops\n");
}
@@ -472,6 +634,19 @@ int ns8390_probe1(struct net_device *dev, int word16, char *model_name, int type
static int ns8390_open(struct net_device *dev)
{
ei_open(dev);
+
+ /* At least on my card (a Focus Enhancements PDS card) I start */
+ /* getting interrupts right away, so the driver needs to be */
+ /* completely initialized before enabling the interrupt. */
+ /* - funaho@jurai.org (1999-05-17) */
+
+ /* Non-slow interrupt, works around issues with the SONIC driver */
+ if (request_irq(dev->irq, ei_interrupt, 0, "8390 Ethernet", dev))
+ {
+ printk ("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
+ return EAGAIN;
+ }
+
MOD_INC_USE_COUNT;
return 0;
}
@@ -489,24 +664,19 @@ static int ns8390_close_card(struct net_device *dev)
{
if (ei_debug > 1)
printk("%s: Shutting down ethercard.\n", dev->name);
+ free_irq(dev->irq, dev);
ei_close(dev);
MOD_DEC_USE_COUNT;
return 0;
}
-struct nubus_device_specifier nubus_8390={
- ns8390_probe,
- NULL
-};
-
-
/*
* Interlan Specific Code Starts Here
*/
static void interlan_reset(struct net_device *dev)
{
- unsigned char *target=nubus_slot_addr(dev->irq);
+ unsigned char *target=nubus_slot_addr(IRQ2SLOT(dev->irq));
if (ei_debug > 1)
printk("Need to reset the NS8390 t=%lu...", jiffies);
ei_status.txing = 0;
@@ -531,16 +701,23 @@ static void interlan_reset(struct net_device *dev)
The only complications are that the ring buffer wraps.
*/
-static void dayna_cpu_memcpy(struct net_device *dev, void *to, int from, int count)
+static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count)
{
volatile unsigned short *ptr;
unsigned short *target=to;
from<<=1; /* word, skip overhead */
ptr=(unsigned short *)(dev->mem_start+from);
+ /*
+ * Leading byte?
+ */
+ if (from&2) {
+ *((char *)target)++ = *(((char *)ptr++)-1);
+ count--;
+ }
while(count>=2)
{
*target++=*ptr++; /* Copy and */
- ptr++; /* Cruft and */
+ ptr++; /* skip cruft */
count-=2;
}
/*
@@ -554,16 +731,24 @@ static void dayna_cpu_memcpy(struct net_device *dev, void *to, int from, int cou
}
}
-static void cpu_dayna_memcpy(struct net_device *dev, int to, const void *from, int count)
+static void dayna_memcpy_tocard(struct net_device *dev, int to, const void *from, int count)
{
volatile unsigned short *ptr;
const unsigned short *src=from;
to<<=1; /* word, skip overhead */
ptr=(unsigned short *)(dev->mem_start+to);
+ /*
+ * Leading byte?
+ */
+ if (to&2) { /* avoid a byte write (stomps on other data) */
+ ptr[-1] = (ptr[-1]&0xFF00)|*((unsigned char *)src)++;
+ ptr++;
+ count--;
+ }
while(count>=2)
{
*ptr++=*src++; /* Copy and */
- ptr++; /* Cruft and */
+ ptr++; /* skip cruft */
count-=2;
}
/*
@@ -573,14 +758,15 @@ static void cpu_dayna_memcpy(struct net_device *dev, int to, const void *from, i
{
/* Big endian */
unsigned short v=*src;
- *((char *)ptr)=v>>8;
+ /* card doesn't like byte writes */
+ *ptr=(*ptr&0x00FF)|(v&0xFF00);
}
}
static void dayna_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
{
unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
- dayna_cpu_memcpy(dev, (void *)hdr, hdr_start, 4);
+ dayna_memcpy_fromcard(dev, (void *)hdr, hdr_start, 4);
/* Register endianism - fix here rather than 8390.c */
hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
}
@@ -599,14 +785,14 @@ static void dayna_block_input(struct net_device *dev, int count, struct sk_buff
{
/* We must wrap the input move. */
int semi_count = dev->rmem_end - xfer_start;
- dayna_cpu_memcpy(dev, skb->data, xfer_base, semi_count);
+ dayna_memcpy_fromcard(dev, skb->data, xfer_base, semi_count);
count -= semi_count;
- dayna_cpu_memcpy(dev, skb->data + semi_count,
+ dayna_memcpy_fromcard(dev, skb->data + semi_count,
dev->rmem_start - dev->mem_start, count);
}
else
{
- dayna_cpu_memcpy(dev, skb->data, xfer_base, count);
+ dayna_memcpy_fromcard(dev, skb->data, xfer_base, count);
}
}
@@ -615,7 +801,7 @@ static void dayna_block_output(struct net_device *dev, int count, const unsigned
{
long shmem = (start_page - WD_START_PG)<<8;
- cpu_dayna_memcpy(dev, shmem, buf, count);
+ dayna_memcpy_tocard(dev, shmem, buf, count);
}
/*
@@ -739,6 +925,7 @@ static void slow_sane_block_output(struct net_device *dev, int count, const unsi
* Local variables:
* compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c daynaport.c"
* version-control: t
+ * c-basic-offset: 4
* tab-width: 4
* kept-new-versions: 5
* End:
diff --git a/drivers/net/irda/Config.in b/drivers/net/irda/Config.in
index da1df253c..da0b5f4be 100644
--- a/drivers/net/irda/Config.in
+++ b/drivers/net/irda/Config.in
@@ -6,10 +6,12 @@ dep_tristate 'IrTTY (uses Linux serial driver)' CONFIG_IRTTY_SIR $CONFIG_IRDA
dep_tristate 'IrPORT (IrDA serial driver)' CONFIG_IRPORT_SIR $CONFIG_IRDA
comment 'FIR device drivers'
-dep_tristate 'NSC PC87108/PC97338' CONFIG_NSC_FIR $CONFIG_IRDA
+dep_tristate 'NSC PC87108/PC87338' CONFIG_NSC_FIR $CONFIG_IRDA
dep_tristate 'Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA
dep_tristate 'Toshiba Type-O IR Port' CONFIG_TOSHIBA_FIR $CONFIG_IRDA
-dep_tristate 'SMC IrCC' CONFIG_SMC_IRCC_FIR $CONFIG_IRDA
+if [ "$CONFIG_EXPERIMENTAL" != "n" ]; then
+dep_tristate 'SMC IrCC (Experimental)' CONFIG_SMC_IRCC_FIR $CONFIG_IRDA
+fi
comment 'Dongle support'
bool 'Serial dongle support' CONFIG_DONGLE
@@ -19,9 +21,7 @@ if [ "$CONFIG_DONGLE" != "n" ]; then
dep_tristate ' Tekram IrMate 210B dongle' CONFIG_TEKRAM_DONGLE $CONFIG_IRDA
dep_tristate ' Greenwich GIrBIL dongle' CONFIG_GIRBIL_DONGLE $CONFIG_IRDA
dep_tristate ' Parallax LiteLink dongle' CONFIG_LITELINK_DONGLE $CONFIG_IRDA
- dep_tristate ' Adaptec Airport 1000/2000 dongle' CONFIG_AIRPORT_DONGLE $CONFIG_IRDA
- dep_tristate ' Old Belkin dongle' CONFIG_OLD_BELKIN_DONGLE $CONFIG_IRDA
-
+ dep_tristate ' Old Belkin dongle' CONFIG_OLD_BELKIN_DONGLE $CONFIG_IRDA
fi
endmenu
diff --git a/drivers/net/irda/Makefile b/drivers/net/irda/Makefile
index bf5628ebd..291a27f05 100644
--- a/drivers/net/irda/Makefile
+++ b/drivers/net/irda/Makefile
@@ -29,10 +29,10 @@ else
endif
ifeq ($(CONFIG_NSC_FIR),y)
-L_OBJS += nsc_fir.o
+L_OBJS += nsc-ircc.o
else
ifeq ($(CONFIG_NSC_FIR),m)
- M_OBJS += nsc_fir.o
+ M_OBJS += nsc-ircc.o
endif
endif
@@ -118,14 +118,6 @@ else
endif
endif
-ifeq ($(CONFIG_AIRPORT_DONGLE),y)
-L_OBJS += airport.o
-else
- ifeq ($(CONFIG_AIRPORT_DONGLE),m)
- M_OBJS += airport.o
- endif
-endif
-
ifeq ($(CONFIG_OLD_BELKIN_DONGLE),y)
L_OBJS += old_belkin.o
else
diff --git a/drivers/net/irda/airport.c b/drivers/net/irda/airport.c
deleted file mode 100644
index b68378189..000000000
--- a/drivers/net/irda/airport.c
+++ /dev/null
@@ -1,358 +0,0 @@
-/*********************************************************************
- *
- * Filename: airport.c
- * Version: 0.2
- * Description: Implementation for the Adaptec Airport 1000 and 2000
- * dongles
- * Status: Experimental.
- * Author: Fons Botman <budely@tref.nl>
- * Created at: Wed May 19 23:14:34 CEST 1999
- * Based on: actisys.c by Dag Brattli <dagb@cs.uit.no>
- *
- * Copyright (c) 1998-1999 Fons Botman, All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * Neither Fons Botman nor anyone else admit liability nor
- * provide warranty for any of this software. This material is
- * provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/tty.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-
-#include <net/irda/irda.h>
-#include <net/irda/irmod.h>
-#include <net/irda/irda_device.h>
-
-static int airport_reset_wrapper(struct irda_task *task);
-static void airport_open(dongle_t *self, struct qos_info *qos);
-static void airport_close(dongle_t *self);
-static int airport_change_speed_wrapper(struct irda_task *task);
-
-static struct dongle_reg dongle = {
- Q_NULL,
- IRDA_AIRPORT_DONGLE,
- airport_open,
- airport_close,
- airport_reset_wrapper,
- airport_change_speed_wrapper,
-};
-
-int __init airport_init(void)
-{
- int ret;
-
- IRDA_DEBUG(2, __FUNCTION__ "()\n");
- ret = irda_device_register_dongle(&dongle);
- if (ret < 0)
- return ret;
- return 0;
-}
-
-void airport_cleanup(void)
-{
- IRDA_DEBUG(2, __FUNCTION__ "()\n");
- irda_device_unregister_dongle(&dongle);
-}
-
-static void airport_open(dongle_t *self, struct qos_info *qos)
-{
- qos->baud_rate.bits &=
- IR_2400|IR_9600|IR_19200|IR_38400|IR_57600|IR_115200;
- /* May need 1ms */
- qos->min_turn_time.bits = 0x07;
-
- MOD_INC_USE_COUNT;
-}
-
-static void airport_close(dongle_t *self)
-{
- IRDA_DEBUG(2, __FUNCTION__ "()\n");
- /* Power off dongle */
- self->set_dtr_rts(self->dev, FALSE, FALSE);
-
- MOD_DEC_USE_COUNT;
-}
-
-static void airport_set_command_mode(dongle_t *self)
-{
- IRDA_DEBUG(2, __FUNCTION__ "()\n");
- self->set_dtr_rts(self->dev, FALSE, TRUE);
-}
-
-static void airport_set_normal_mode(dongle_t *self)
-{
- IRDA_DEBUG(2, __FUNCTION__ "()\n");
- self->set_dtr_rts(self->dev, TRUE, TRUE);
-}
-
-void airport_write_char(dongle_t *self, unsigned char c)
-{
- int actual;
- IRDA_DEBUG(2, __FUNCTION__ "(,0x%x)\n", c & 0xff);
- actual = self->write(self->dev, &c, 1);
- ASSERT(actual == 1, return;);
-}
-
-#define JIFFIES_TO_MSECS(j) ((j)*1000/HZ)
-
-static int airport_waitfor_char(dongle_t *self, unsigned char c)
-{
- __u8 buf[100];
- int i, found = FALSE;
- int before;
- int len;
-
- IRDA_DEBUG(2, __FUNCTION__ "(,0x%x)\n", c);
-
- /* Sleep approx. 10 ms */
- before = jiffies;
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(20));
- IRDA_DEBUG(4, __FUNCTION__ " waited %ldms\n",
- JIFFIES_TO_MSECS(jiffies - before));
-
- len = self->read(self->dev, buf, 100);
-
- for (i = 0; !found && i < len; i++ ) {
- /* IRDA_DEBUG(6, __FUNCTION__ " 0x02x\n", idev->rx_buff.data[i]); */
- found = c == buf[i];
- }
-
- IRDA_DEBUG(2, __FUNCTION__ " returns %s\n", (found ? "true" : "false"));
- return found;
-}
-
-static int airport_check_command_mode(dongle_t *self)
-{
- int i;
- int found = FALSE;
-
- IRDA_DEBUG(2, __FUNCTION__ "()\n");
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(20));
- airport_set_command_mode(self);
-
- /* Loop until the time expires (200ms) or we get the magic char. */
-
- for ( i = 0 ; i < 25 ; i++ ) {
- airport_write_char(self, 0xff);
- if (airport_waitfor_char(self, 0xc3)) {
- found = TRUE;
- break;
- }
- }
-
- if (found) {
- IRDA_DEBUG(2, __FUNCTION__ " OK. (%d)\n", i);
- } else {
- IRDA_DEBUG(0, __FUNCTION__ " FAILED!\n");
- }
- return found;
-}
-
-static int airport_write_register(dongle_t *self, unsigned char reg)
-{
- int ok = FALSE;
- int i;
-
- IRDA_DEBUG(4, __FUNCTION__ "(,0x%x)\n", reg);
- airport_check_command_mode(self);
-
- for ( i = 0 ; i < 6 ; i++ ) {
- airport_write_char(self, reg);
- if (!airport_waitfor_char(self, reg))
- continue;
-
- /* Now read it back */
- airport_write_char(self, (reg << 4) | 0x0f);
- if (airport_waitfor_char(self, reg)) {
- ok = TRUE;
- break;
- }
- }
-
- airport_set_normal_mode(self);
- if (ok) {
- IRDA_DEBUG(4, __FUNCTION__ "(,0x%x) returns OK\n", reg);
- } else {
- IRDA_DEBUG(0, __FUNCTION__ "(,0x%x) returns False!\n", reg);
- }
- return ok;
-}
-
-
-/*
- * Function airport_change_speed (self, speed)
- *
- * Change speed of the Airport type IrDA dongles.
- */
-static void airport_change_speed(dongle_t *self, __u32 speed)
-{
- __u32 current_baudrate;
- int baudcode;
-
- IRDA_DEBUG(4, __FUNCTION__ "(,%d)\n", speed);
-
- ASSERT(self != NULL, return;);
-
- /* Find the correct baudrate code for the required baudrate */
- switch (speed) {
- case 2400: baudcode = 0x10; break;
- case 4800: baudcode = 0x20; break;
- case 9600: baudcode = 0x30; break;
- case 19200: baudcode = 0x40; break;
- case 38400: baudcode = 0x50; break;
- case 57600: baudcode = 0x60; break;
- case 115200: baudcode = 0x70; break;
- default:
- IRDA_DEBUG(0, __FUNCTION__ " bad baud rate: %d\n", speed);
- return;
- }
-
- current_baudrate = self->speed;
- IRDA_DEBUG(4, __FUNCTION__ " current baudrate: %d\n", current_baudrate);
-
- self->set_mode(self->dev, IRDA_RAW);
-
- /* Set the new speed in both registers */
- if (airport_write_register(self, baudcode)) {
- if (airport_write_register(self, baudcode|0x01)) {
- /* ok */
- } else {
- IRDA_DEBUG(0, __FUNCTION__
- " Cannot set new speed in second register\n");
- }
- } else {
- IRDA_DEBUG(0, __FUNCTION__
- " Cannot set new speed in first register\n");
- }
-
- self->set_mode(self->dev, IRDA_IRLAP);
-
- /* How do I signal an error in these functions? */
-
- IRDA_DEBUG(4, __FUNCTION__ " returning\n");
-}
-
-int airport_change_speed_wrapper(struct irda_task *task)
-{
- dongle_t *self = (dongle_t *) task->instance;
- __u32 speed = (__u32) task->param;
-
- irda_execute_as_process(self, (TODO_CALLBACK) airport_change_speed,
- speed);
-
- irda_task_next_state(task, IRDA_TASK_DONE);
-
- return 0;
-}
-
-/*
- * Function airport_reset (self)
- *
- * Reset the Airport type dongle. Warning, this function must only be
- * called with a process context!
- *
- */
-static void airport_reset(dongle_t *self)
-{
- int ok;
-
- IRDA_DEBUG(2, __FUNCTION__ "()\n");
- ASSERT(self != NULL, return;);
-
- self->set_mode(self->dev, IRDA_RAW);
-
- airport_set_normal_mode(self);
-
- /* Sleep 2000 ms */
- IRDA_DEBUG(2, __FUNCTION__ " waiting for powerup\n");
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(2000));
- IRDA_DEBUG(2, __FUNCTION__ " finished waiting for powerup\n");
-
- /* set dongle speed to 9600 */
- ok = TRUE;
-
- if (ok)
- ok = airport_write_register(self, 0x30);
- if (!ok)
- MESSAGE(__FUNCTION__ "() dongle not connected?\n");
- if (ok)
- ok = airport_write_register(self, 0x31);
-
- if (ok)
- ok = airport_write_register(self, 0x02);
- if (ok)
- ok = airport_write_register(self, 0x03);
-
- if (ok) {
- ok = airport_check_command_mode(self);
-
- if (ok) {
- airport_write_char(self, 0x04);
- ok = airport_waitfor_char(self, 0x04);
- }
- airport_set_normal_mode(self);
- }
-
- self->set_mode(self->dev, IRDA_IRLAP);
-
- current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(MSECS_TO_JIFFIES(20));
- IRDA_DEBUG(4, __FUNCTION__ " waited 20ms\n");
-
- self->speed = 9600;
- if (!ok)
- MESSAGE(__FUNCTION__ "() failed.\n");
- IRDA_DEBUG(2, __FUNCTION__ " returning.\n");
-}
-
-int airport_reset_wrapper(struct irda_task *task)
-{
- dongle_t *self = (dongle_t *) task->instance;
-
- irda_execute_as_process(self, (TODO_CALLBACK) airport_reset, 0);
-
- irda_task_next_state(task, IRDA_TASK_DONE);
-
- return 0;
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Fons Botman <budely@tref.nl>");
-MODULE_DESCRIPTION("Adaptec Airport 1000 and 2000 dongle driver");
-
-/*
- * Function init_module (void)
- *
- * Initialize Airport module
- *
- */
-int init_module(void)
-{
- return airport_init();
-}
-
-/*
- * Function cleanup_module (void)
- *
- * Cleanup Airport module
- *
- */
-void cleanup_module(void)
-{
- airport_cleanup();
-}
-
-#endif
diff --git a/drivers/net/irda/irport.c b/drivers/net/irda/irport.c
index 352dddecc..d8832292a 100644
--- a/drivers/net/irda/irport.c
+++ b/drivers/net/irda/irport.c
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 3 13:49:59 1997
- * Modified at: Wed Jan 5 13:59:38 2000
+ * Modified at: Fri Jan 28 20:22:38 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: serial.c by Linus Torvalds
*
@@ -161,20 +161,19 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
self->index = i;
/* Initialize IO */
- self->io.iobase = iobase;
+ self->io.sir_base = iobase;
+ self->io.sir_ext = IO_EXTENT;
self->io.irq = irq;
- self->io.io_ext = IO_EXTENT;
self->io.fifo_size = 16;
/* Lock the port that we need */
- ret = check_region(self->io.iobase, self->io.io_ext);
+ ret = check_region(self->io.sir_base, self->io.sir_ext);
if (ret < 0) {
IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
- self->io.iobase);
- /* irport_cleanup(self->self); */
+ self->io.sir_base);
return NULL;
}
- request_region(self->io.iobase, self->io.io_ext, driver_name);
+ request_region(self->io.sir_base, self->io.sir_ext, driver_name);
/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&self->qos);
@@ -218,7 +217,6 @@ irport_open(int i, unsigned int iobase, unsigned int irq)
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
return NULL;
}
-
self->netdev = dev;
/* May be overridden by piggyback drivers */
@@ -268,19 +266,19 @@ int irport_close(struct irport_cb *self)
/* Release the IO-port that this driver is using */
IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n",
- self->io.iobase);
- release_region(self->io.iobase, self->io.io_ext);
+ self->io.sir_base);
+ release_region(self->io.sir_base, self->io.sir_ext);
if (self->tx_buff.head)
kfree(self->tx_buff.head);
if (self->rx_buff.head)
kfree(self->rx_buff.head);
-
+
/* Remove ourselves */
dev_self[self->index] = NULL;
kfree(self);
-
+
return 0;
}
@@ -289,7 +287,7 @@ void irport_start(struct irport_cb *self)
unsigned long flags;
int iobase;
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
spin_lock_irqsave(&self->lock, flags);
@@ -310,7 +308,7 @@ void irport_stop(struct irport_cb *self)
unsigned long flags;
int iobase;
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
spin_lock_irqsave(&self->lock, flags);
@@ -355,7 +353,7 @@ void irport_change_speed(void *priv, __u32 speed)
ASSERT(self != NULL, return;);
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
/* Update accounting for new speed */
self->io.speed = speed;
@@ -431,7 +429,7 @@ int __irport_change_speed(struct irda_task *task)
break;
case IRDA_TASK_CHILD_INIT:
/* Go to default speed */
- irport_change_speed(self, 9600);
+ self->change_speed(self->priv, 9600);
/* Change speed of dongle */
if (irda_task_execute(self->dongle,
@@ -454,7 +452,7 @@ int __irport_change_speed(struct irda_task *task)
break;
case IRDA_TASK_CHILD_DONE:
/* Finally we are ready to change the speed */
- irport_change_speed(self, speed);
+ self->change_speed(self->priv, speed);
irda_task_next_state(task, IRDA_TASK_DONE);
break;
@@ -484,7 +482,7 @@ static void irport_write_wakeup(struct irport_cb *self)
IRDA_DEBUG(4, __FUNCTION__ "()\n");
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
/* Finished with frame? */
if (self->tx_buff.len > 0) {
@@ -598,7 +596,6 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct irport_cb *self;
unsigned long flags;
- int actual = 0;
int iobase;
__u32 speed;
@@ -607,7 +604,7 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self = (struct irport_cb *) dev->priv;
ASSERT(self != NULL, return 0;);
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
/* Lock transmit buffer */
if (irda_lock((void *) &dev->tbusy) == FALSE) {
@@ -617,7 +614,7 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
WARNING("%s: transmit timed out\n", dev->name);
irport_start(self);
- irport_change_speed(self, self->io.speed );
+ self->change_speed(self->priv, self->io.speed);
dev->trans_start = jiffies;
}
@@ -635,8 +632,7 @@ int irport_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
self->tx_buff.truesize);
- self->tx_buff.data += actual;
- self->tx_buff.len -= actual;
+ self->stats.tx_bytes += self->tx_buff.len;
/* Turn on transmit finished interrupt. Will fire immediately! */
outb(UART_IER_THRI, iobase+UART_IER);
@@ -661,7 +657,7 @@ static void irport_receive(struct irport_cb *self)
ASSERT(self != NULL, return;);
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
/*
* Receive all characters in Rx FIFO, unwrap and unstuff them.
@@ -702,15 +698,16 @@ void irport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
dev->interrupt = 1;
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
iir = inb(iobase+UART_IIR) & UART_IIR_ID;
while (iir) {
/* Clear interrupt */
lsr = inb(iobase+UART_LSR);
- IRDA_DEBUG(4, __FUNCTION__ "(), iir=%02x, lsr=%02x, iobase=%#x\n",
- iir, lsr, iobase);
+ IRDA_DEBUG(4, __FUNCTION__
+ "(), iir=%02x, lsr=%02x, iobase=%#x\n",
+ iir, lsr, iobase);
switch (iir) {
case UART_IIR_RLSI:
@@ -765,7 +762,7 @@ int irport_net_open(struct net_device *dev)
ASSERT(dev != NULL, return -1;);
self = (struct irport_cb *) dev->priv;
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
if (request_irq(self->io.irq, self->interrupt, 0, dev->name,
(void *) dev))
@@ -809,7 +806,7 @@ int irport_net_close(struct net_device *dev)
ASSERT(self != NULL, return -1;);
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
/* Stop device */
dev->tbusy = 1;
@@ -840,7 +837,7 @@ void irport_wait_until_sent(struct irport_cb *self)
{
int iobase;
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
/* Wait until Tx FIFO is empty */
while (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
@@ -875,7 +872,7 @@ static int irport_set_dtr_rts(struct net_device *dev, int dtr, int rts)
ASSERT(self != NULL, return -1;);
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
if (dtr)
dtr = UART_MCR_DTR;
@@ -895,7 +892,7 @@ static int irport_raw_write(struct net_device *dev, __u8 *buf, int len)
ASSERT(self != NULL, return -1;);
- iobase = self->io.iobase;
+ iobase = self->io.sir_base;
/* Tx FIFO should be empty! */
if (!(inb(iobase+UART_LSR) & UART_LSR_THRE)) {
diff --git a/drivers/net/irda/irtty.c b/drivers/net/irda/irtty.c
index 2ec4eba14..370a9c7fe 100644
--- a/drivers/net/irda/irtty.c
+++ b/drivers/net/irda/irtty.c
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Dec 9 21:18:38 1997
- * Modified at: Wed Jan 5 14:00:13 2000
+ * Modified at: Fri Jan 14 21:02:27 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
* Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
@@ -233,6 +233,8 @@ static int irtty_open(struct tty_struct *tty)
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
return -ENOMEM;
}
+ /* dev_alloc doesn't clear the struct */
+ memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*));
dev->priv = (void *) self;
self->netdev = dev;
@@ -654,6 +656,7 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
dev->trans_start = jiffies;
+ self->stats.tx_bytes += self->tx_buff.len;
if (self->tty->driver.write)
actual = self->tty->driver.write(self->tty, 0,
@@ -663,9 +666,6 @@ static int irtty_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self->tx_buff.data += actual;
self->tx_buff.len -= actual;
- self->stats.tx_packets++;
- self->stats.tx_bytes += self->tx_buff.len;
-
dev_kfree_skb(skb);
return 0;
@@ -709,6 +709,8 @@ static void irtty_write_wakeup(struct tty_struct *tty)
self->tx_buff.data += actual;
self->tx_buff.len -= actual;
+
+ self->stats.tx_packets++;
} else {
/*
* Now serial buffer is almost free & we can start
diff --git a/drivers/net/irda/nsc_fir.c b/drivers/net/irda/nsc-ircc.c
index affd1d8fa..e8aaa8459 100644
--- a/drivers/net/irda/nsc_fir.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -1,12 +1,12 @@
/*********************************************************************
*
- * Filename: nsc_fir.c
+ * Filename: nsc-ircc.c
* Version: 1.0
* Description: Driver for the NSC PC'108 and PC'338 IrDA chipsets
* Status: Stable.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Nov 7 21:43:15 1998
- * Modified at: Wed Jan 5 13:59:21 2000
+ * Modified at: Fri Jan 28 12:10:10 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
@@ -41,8 +41,9 @@
*
********************************************************************/
-#include <linux/module.h>
#include <linux/config.h>
+#include <linux/module.h>
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/skbuff.h>
@@ -67,29 +68,38 @@
#include <net/irda/irlap_frame.h>
#include <net/irda/irda_device.h>
-#include <net/irda/nsc_fir.h>
+#include <net/irda/nsc-ircc.h>
#define CHIP_IO_EXTENT 8
#define BROKEN_DONGLE_ID
-/*
- * Define if you have multiple NSC IrDA controllers in your machine. Not
- * enabled by default since some single chips detects at multiple addresses
- */
-#undef CONFIG_NSC_FIR_MULTIPLE
-
-static char *driver_name = "nsc_fir";
+static char *driver_name = "nsc-ircc";
/* Module parameters */
static int qos_mtt_bits = 0x07; /* 1 ms or more */
static int dongle_id = 0;
-static unsigned int io[] = { 0x2f8, 0x2f8, 0x2f8, 0x2f8, 0x2f8 };
-static unsigned int io2[] = { 0x150, 0x398, 0xea, 0x15c, 0x2e };
-static unsigned int irq[] = { 3, 3, 3, 3, 3 };
-static unsigned int dma[] = { 0, 0, 0, 0, 3 };
+/* Use BIOS settions by default, but user may supply module parameters */
+static unsigned int io[] = { ~0, ~0, ~0, ~0 };
+static unsigned int irq[] = { 0, 0, 0, 0, 0 };
+static unsigned int dma[] = { 0, 0, 0, 0, 0 };
+
+static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info);
+static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info);
+static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info);
+static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info);
+
+/* These are the known NSC chips */
+static nsc_chip_t chips[] = {
+ { "PC87108", { 0x150, 0x398, 0xea }, 0x05, 0x10, 0xf0,
+ nsc_ircc_probe_108, nsc_ircc_init_108 },
+ { "PC87338", { 0x398, 0x15c, 0x2e }, 0x08, 0xb0, 0xf0,
+ nsc_ircc_probe_338, nsc_ircc_init_338 },
+ { NULL }
+};
-static struct nsc_fir_cb *dev_self[] = { NULL, NULL, NULL, NULL, NULL };
+/* Max 4 instances for now */
+static struct nsc_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL };
static char *dongle_types[] = {
"Differential serial interface",
@@ -111,143 +121,182 @@ static char *dongle_types[] = {
};
/* Some prototypes */
-static int nsc_fir_open(int i, unsigned int iobase, unsigned int board_addr,
- unsigned int irq, unsigned int dma);
+static int nsc_ircc_open(int i, chipio_t *info);
#ifdef MODULE
-static int nsc_fir_close(struct nsc_fir_cb *self);
+static int nsc_ircc_close(struct nsc_ircc_cb *self);
#endif /* MODULE */
-static int nsc_fir_probe(int iobase, int board_addr, int irq, int dma);
-static void nsc_fir_pio_receive(struct nsc_fir_cb *self);
-static int nsc_fir_dma_receive(struct nsc_fir_cb *self);
-static int nsc_fir_dma_receive_complete(struct nsc_fir_cb *self, int iobase);
-static int nsc_fir_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev);
-static int nsc_fir_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev);
-static int nsc_fir_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
-static void nsc_fir_dma_xmit(struct nsc_fir_cb *self, int iobase);
-static void nsc_fir_change_speed(struct nsc_fir_cb *self, __u32 baud);
-static void nsc_fir_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int nsc_fir_is_receiving(struct nsc_fir_cb *self);
-static int nsc_fir_read_dongle_id (int iobase);
-static void nsc_fir_init_dongle_interface (int iobase, int dongle_id);
-
-static int nsc_fir_net_init(struct net_device *dev);
-static int nsc_fir_net_open(struct net_device *dev);
-static int nsc_fir_net_close(struct net_device *dev);
-static int nsc_fir_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-static struct net_device_stats *nsc_fir_net_get_stats(struct net_device *dev);
+static int nsc_ircc_setup(chipio_t *info);
+static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self);
+static int nsc_ircc_dma_receive(struct nsc_ircc_cb *self);
+static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase);
+static int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev);
+static int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev);
+static int nsc_ircc_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
+static void nsc_ircc_dma_xmit(struct nsc_ircc_cb *self, int iobase);
+static void nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 baud);
+static void nsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static int nsc_ircc_is_receiving(struct nsc_ircc_cb *self);
+static int nsc_ircc_read_dongle_id (int iobase);
+static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id);
+
+static int nsc_ircc_net_init(struct net_device *dev);
+static int nsc_ircc_net_open(struct net_device *dev);
+static int nsc_ircc_net_close(struct net_device *dev);
+static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev);
#ifdef CONFIG_APM
-static int nsc_fir_apmproc(apm_event_t event);
+static int nsc_ircc_apmproc(apm_event_t event);
#endif /* CONFIG_APM */
+
/*
- * Function nsc_fir_init ()
+ * Function nsc_ircc_init ()
*
* Initialize chip. Just try to find out how many chips we are dealing with
* and where they are
*/
-int __init nsc_fir_init(void)
+int __init nsc_ircc_init(void)
{
+ chipio_t info;
+ nsc_chip_t *chip;
int ret = -ENODEV;
- int ioaddr;
- int i;
+ int cfg_base;
+ int cfg, id;
+ int reg;
+ int i = 0;
+
+ /* Probe for all the NSC chipsets we know about */
+ for (chip=chips; chip->name ; chip++,i++) {
+ IRDA_DEBUG(2, __FUNCTION__"(), Probing for %s ...\n",
+ chip->name);
+
+ /* Try all config registers for this chip */
+ for (cfg=0; cfg<3; cfg++) {
+ cfg_base = chip->cfg[cfg];
+ if (!cfg_base)
+ continue;
+
+ memset(&info, 0, sizeof(chipio_t));
+ info.cfg_base = cfg_base;
+ info.fir_base = io[i];
+ info.dma = dma[i];
+ info.irq = irq[i];
+
+ /* Read index register */
+ reg = inb(cfg_base);
+ if (reg == 0xff) {
+ IRDA_DEBUG(2, __FUNCTION__
+ "() no chip at 0x%03x\n", cfg_base);
+ continue;
+ }
+
+ /* Read chip identification register */
+ outb(chip->cid_index, cfg_base);
+ id = inb(cfg_base+1);
+ if ((id & chip->cid_mask) == chip->cid_value) {
+ IRDA_DEBUG(2, __FUNCTION__
+ "() Found %s chip, revision=%d\n",
+ chip->name, id & ~chip->cid_mask);
+ /*
+ * If the user supplies the base address, then
+ * we init the chip, if not we probe the values
+ * set by the BIOS
+ */
+ if (io[i] < 2000) {
+ chip->init(chip, &info);
+ } else
+ chip->probe(chip, &info);
+ if (nsc_ircc_open(i, &info) == 0)
+ ret = 0;
+ i++;
+ } else {
+ IRDA_DEBUG(2, __FUNCTION__
+ "(), Wrong chip id=0x%02x\n", id);
+ }
+ }
+
+ }
#ifdef CONFIG_APM
- apm_register_callback(nsc_fir_apmproc);
+ /* Make sure at least one chip was found before enabling APM */
+ if (ret == 0)
+ apm_register_callback(nsc_ircc_apmproc);
#endif /* CONFIG_APM */
- for (i=0; (io[i] < 2000) && (i < 5); i++) {
- ioaddr = io[i];
- if (check_region(ioaddr, CHIP_IO_EXTENT) < 0)
- continue;
- if (nsc_fir_open(i, io[i], io2[i], irq[i], dma[i]) == 0)
- {
-#ifdef CONFIG_NSC_FIR_MULTIPLE
- ret = 0;
-#else
- return 0;
-#endif
- }
- }
-
return ret;
}
/*
- * Function nsc_fir_cleanup ()
+ * Function nsc_ircc_cleanup ()
*
* Close all configured chips
*
*/
#ifdef MODULE
-static void nsc_fir_cleanup(void)
+static void nsc_ircc_cleanup(void)
{
int i;
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
#ifdef CONFIG_APM
- apm_unregister_callback(nsc_fir_apmproc);
+ apm_unregister_callback(nsc_ircc_apmproc);
#endif /* CONFIG_APM */
-
- for (i=0; i < 5; i++) {
+ for (i=0; i < 4; i++) {
if (dev_self[i])
- nsc_fir_close(dev_self[i]);
+ nsc_ircc_close(dev_self[i]);
}
}
#endif /* MODULE */
/*
- * Function nsc_fir_open (iobase, irq)
+ * Function nsc_ircc_open (iobase, irq)
*
* Open driver instance
*
*/
-static int
-nsc_fir_open(int i, unsigned int iobase, unsigned int board_addr,
- unsigned int irq, unsigned int dma)
+static int nsc_ircc_open(int i, chipio_t *info)
{
struct net_device *dev;
- struct nsc_fir_cb *self;
- int dongle_id;
+ struct nsc_ircc_cb *self;
int ret;
int err;
IRDA_DEBUG(2, __FUNCTION__ "()\n");
- if ((dongle_id = nsc_fir_probe(iobase, board_addr, irq, dma)) == -1)
+ if ((nsc_ircc_setup(info)) == -1)
return -1;
- /*
- * Allocate new instance of the driver
- */
- self = kmalloc(sizeof(struct nsc_fir_cb), GFP_KERNEL);
+ /* Allocate new instance of the driver */
+ self = kmalloc(sizeof(struct nsc_ircc_cb), GFP_KERNEL);
if (self == NULL) {
ERROR(__FUNCTION__ "(), can't allocate memory for "
"control block!\n");
return -ENOMEM;
}
- memset(self, 0, sizeof(struct nsc_fir_cb));
+ memset(self, 0, sizeof(struct nsc_ircc_cb));
spin_lock_init(&self->lock);
/* Need to store self somewhere */
dev_self[i] = self;
+ self->index = i;
/* Initialize IO */
- self->io.iobase = iobase;
- self->io.irq = irq;
- self->io.io_ext = CHIP_IO_EXTENT;
- self->io.dma = dma;
+ self->io.cfg_base = info->cfg_base;
+ self->io.fir_base = info->fir_base;
+ self->io.irq = info->irq;
+ self->io.fir_ext = CHIP_IO_EXTENT;
+ self->io.dma = info->dma;
self->io.fifo_size = 32;
-
- /* Lock the port that we need */
- ret = check_region(self->io.iobase, self->io.io_ext);
+
+ /* Reserve the ioports that we need */
+ ret = check_region(self->io.fir_base, self->io.fir_ext);
if (ret < 0) {
- IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
- self->io.iobase);
- /* nsc_fir_cleanup(self->self); */
+ WARNING(__FUNCTION__ "(), can't get iobase of 0x%03x\n",
+ self->io.fir_base);
+ dev_self[i] = NULL;
+ kfree(self);
return -ENODEV;
}
- request_region(self->io.iobase, self->io.io_ext, driver_name);
+ request_region(self->io.fir_base, self->io.fir_ext, driver_name);
/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&self->qos);
@@ -268,13 +317,16 @@ nsc_fir_open(int i, unsigned int iobase, unsigned int board_addr,
/* Allocate memory if needed */
self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
GFP_KERNEL|GFP_DMA);
- if (self->rx_buff.head == NULL)
+ if (self->rx_buff.head == NULL) {
+ kfree(self);
return -ENOMEM;
+ }
memset(self->rx_buff.head, 0, self->rx_buff.truesize);
self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
GFP_KERNEL|GFP_DMA);
if (self->tx_buff.head == NULL) {
+ kfree(self);
kfree(self->rx_buff.head);
return -ENOMEM;
}
@@ -298,12 +350,12 @@ nsc_fir_open(int i, unsigned int iobase, unsigned int board_addr,
self->netdev = dev;
/* Override the network functions we need to use */
- dev->init = nsc_fir_net_init;
- dev->hard_start_xmit = nsc_fir_hard_xmit_sir;
- dev->open = nsc_fir_net_open;
- dev->stop = nsc_fir_net_close;
- dev->do_ioctl = nsc_fir_net_ioctl;
- dev->get_stats = nsc_fir_net_get_stats;
+ dev->init = nsc_ircc_net_init;
+ dev->hard_start_xmit = nsc_ircc_hard_xmit_sir;
+ dev->open = nsc_ircc_net_open;
+ dev->stop = nsc_ircc_net_close;
+ dev->do_ioctl = nsc_ircc_net_ioctl;
+ dev->get_stats = nsc_ircc_net_get_stats;
rtnl_lock();
err = register_netdevice(dev);
@@ -312,23 +364,33 @@ nsc_fir_open(int i, unsigned int iobase, unsigned int board_addr,
ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
return -1;
}
-
MESSAGE("IrDA: Registered device %s\n", dev->name);
+
+ /* Check if user has supplied the dongle id or not */
+ if (!dongle_id) {
+ dongle_id = nsc_ircc_read_dongle_id(self->io.fir_base);
+
+ MESSAGE("%s, Found dongle: %s\n", driver_name,
+ dongle_types[dongle_id]);
+ } else {
+ MESSAGE("%s, Using dongle: %s\n", driver_name,
+ dongle_types[dongle_id]);
+ }
self->io.dongle_id = dongle_id;
- nsc_fir_init_dongle_interface(iobase, dongle_id);
+ nsc_ircc_init_dongle_interface(self->io.fir_base, dongle_id);
return 0;
}
#ifdef MODULE
/*
- * Function nsc_fir_close (self)
+ * Function nsc_ircc_close (self)
*
* Close driver instance
*
*/
-static int nsc_fir_close(struct nsc_fir_cb *self)
+static int nsc_ircc_close(struct nsc_ircc_cb *self)
{
int iobase;
@@ -336,7 +398,7 @@ static int nsc_fir_close(struct nsc_fir_cb *self)
ASSERT(self != NULL, return -1;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Remove netdevice */
if (self->netdev) {
@@ -347,8 +409,8 @@ static int nsc_fir_close(struct nsc_fir_cb *self)
/* Release the PORT that this driver is using */
IRDA_DEBUG(4, __FUNCTION__ "(), Releasing Region %03x\n",
- self->io.iobase);
- release_region(self->io.iobase, self->io.io_ext);
+ self->io.fir_base);
+ release_region(self->io.fir_base, self->io.fir_ext);
if (self->tx_buff.head)
kfree(self->tx_buff.head);
@@ -356,37 +418,39 @@ static int nsc_fir_close(struct nsc_fir_cb *self)
if (self->rx_buff.head)
kfree(self->rx_buff.head);
+ dev_self[self->index] = NULL;
kfree(self);
-
+
return 0;
}
#endif /* MODULE */
/*
- * Function nsc_fir_init_807 (iobase, board_addr, irq, dma)
+ * Function nsc_ircc_init_108 (iobase, cfg_base, irq, dma)
*
* Initialize the NSC '108 chip
*
*/
-static void nsc_fir_init_807(int iobase, int board_addr, int irq, int dma)
+static int nsc_ircc_init_108(nsc_chip_t *chip, chipio_t *info)
{
+ int cfg_base = info->cfg_base;
__u8 temp=0;
- outb(2, board_addr); /* Mode Control Register (MCTL) */
- outb(0x00, board_addr+1); /* Disable device */
+ outb(2, cfg_base); /* Mode Control Register (MCTL) */
+ outb(0x00, cfg_base+1); /* Disable device */
/* Base Address and Interrupt Control Register (BAIC) */
- outb(0, board_addr);
- switch (iobase) {
- case 0x3e8: outb(0x14, board_addr+1); break;
- case 0x2e8: outb(0x15, board_addr+1); break;
- case 0x3f8: outb(0x16, board_addr+1); break;
- case 0x2f8: outb(0x17, board_addr+1); break;
+ outb(0, cfg_base);
+ switch (info->fir_base) {
+ case 0x3e8: outb(0x14, cfg_base+1); break;
+ case 0x2e8: outb(0x15, cfg_base+1); break;
+ case 0x3f8: outb(0x16, cfg_base+1); break;
+ case 0x2f8: outb(0x17, cfg_base+1); break;
default: ERROR(__FUNCTION__ "(), invalid base_address");
}
/* Control Signal Routing Register (CSRT) */
- switch (irq) {
+ switch (info->irq) {
case 3: temp = 0x01; break;
case 4: temp = 0x02; break;
case 5: temp = 0x03; break;
@@ -396,90 +460,242 @@ static void nsc_fir_init_807(int iobase, int board_addr, int irq, int dma)
case 15: temp = 0x07; break;
default: ERROR(__FUNCTION__ "(), invalid irq");
}
- outb(1, board_addr);
+ outb(1, cfg_base);
- switch (dma) {
- case 0: outb(0x08+temp, board_addr+1); break;
- case 1: outb(0x10+temp, board_addr+1); break;
- case 3: outb(0x18+temp, board_addr+1); break;
+ switch (info->dma) {
+ case 0: outb(0x08+temp, cfg_base+1); break;
+ case 1: outb(0x10+temp, cfg_base+1); break;
+ case 3: outb(0x18+temp, cfg_base+1); break;
default: ERROR(__FUNCTION__ "(), invalid dma");
}
- outb(2, board_addr); /* Mode Control Register (MCTL) */
- outb(0x03, board_addr+1); /* Enable device */
+ outb(2, cfg_base); /* Mode Control Register (MCTL) */
+ outb(0x03, cfg_base+1); /* Enable device */
+
+ return 0;
+}
+
+/*
+ * Function nsc_ircc_probe_108 (chip, info)
+ *
+ *
+ *
+ */
+static int nsc_ircc_probe_108(nsc_chip_t *chip, chipio_t *info)
+{
+ int cfg_base = info->cfg_base;
+ int reg;
+
+ /* Read address and interrupt control register (BAIC) */
+ outb(CFG_BAIC, cfg_base);
+ reg = inb(cfg_base+1);
+
+ switch (reg & 0x03) {
+ case 0:
+ info->fir_base = 0x3e8;
+ break;
+ case 1:
+ info->fir_base = 0x2e8;
+ break;
+ case 2:
+ info->fir_base = 0x3f8;
+ break;
+ case 3:
+ info->fir_base = 0x2f8;
+ break;
+ }
+ info->sir_base = info->fir_base;
+ IRDA_DEBUG(2, __FUNCTION__ "(), probing fir_base=0x%03x\n",
+ info->fir_base);
+
+ /* Read control signals routing register (CSRT) */
+ outb(CFG_CSRT, cfg_base);
+ reg = inb(cfg_base+1);
+
+ switch (reg & 0x07) {
+ case 0:
+ info->irq = -1;
+ break;
+ case 1:
+ info->irq = 3;
+ break;
+ case 2:
+ info->irq = 4;
+ break;
+ case 3:
+ info->irq = 5;
+ break;
+ case 4:
+ info->irq = 7;
+ break;
+ case 5:
+ info->irq = 9;
+ break;
+ case 6:
+ info->irq = 11;
+ break;
+ case 7:
+ info->irq = 15;
+ break;
+ }
+ IRDA_DEBUG(2, __FUNCTION__ "(), probing irq=%d\n", info->irq);
+
+ /* Currently we only read Rx DMA but it will also be used for Tx */
+ switch ((reg >> 3) & 0x03) {
+ case 0:
+ info->dma = -1;
+ break;
+ case 1:
+ info->dma = 0;
+ break;
+ case 2:
+ info->dma = 1;
+ break;
+ case 3:
+ info->dma = 3;
+ break;
+ }
+ IRDA_DEBUG(2, __FUNCTION__ "(), probing dma=%d\n", info->dma);
+
+ /* Read mode control register (MCTL) */
+ outb(CFG_MCTL, cfg_base);
+ reg = inb(cfg_base+1);
+
+ info->enabled = reg & 0x01;
+ info->suspended = !((reg >> 1) & 0x01);
+
+ return 0;
}
/*
- * Function nsc_fir_init_338 (iobase, board_addr, irq, dma)
+ * Function nsc_ircc_init_338 (chip, info)
*
* Initialize the NSC '338 chip. Remember that the 87338 needs two
* consecutive writes to the data registers while CPU interrupts are
* disabled. The 97338 does not require this, but shouldn't be any
* harm if we do it anyway.
*/
-static void nsc_fir_init_338(int iobase, int board_addr, int irq, int dma)
+static int nsc_ircc_init_338(nsc_chip_t *chip, chipio_t *info)
{
/* No init yet */
+
+ return 0;
}
-static int nsc_fir_find_chip(int board_addr)
+/*
+ * Function nsc_ircc_probe_338 (chip, info)
+ *
+ *
+ *
+ */
+static int nsc_ircc_probe_338(nsc_chip_t *chip, chipio_t *info)
{
- __u8 index, id;
+ int cfg_base = info->cfg_base;
+ int reg, com = 0;
+ int pnp;
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
+ /* Read funtion enable register (FER) */
+ outb(CFG_FER, cfg_base);
+ reg = inb(cfg_base+1);
- /* Read index register */
- index = inb(board_addr);
- if (index == 0xff) {
- IRDA_DEBUG(0, __FUNCTION__ "(), no chip at 0x%03x\n",
- board_addr);
- return -1;
- }
+ info->enabled = (reg >> 2) & 0x01;
+
+ /* Check if we are in Legacy or PnP mode */
+ outb(CFG_PNP0, cfg_base);
+ reg = inb(cfg_base+1);
+
+ pnp = (reg >> 4) & 0x01;
+ if (pnp) {
+ IRDA_DEBUG(2, "(), Chip is in PnP mode\n");
+ outb(0x46, cfg_base);
+ reg = (inb(cfg_base+1) & 0xfe) << 2;
+
+ outb(0x47, cfg_base);
+ reg |= ((inb(cfg_base+1) & 0xfc) << 8);
- /* Read chip identification register (SID) for the PC97338 */
- outb(8, board_addr);
- id = inb(board_addr+1);
- if ((id & 0xf0) == PC97338) {
- MESSAGE("%s, Found NSC PC97338 chip, revision=%d\n",
- driver_name, id & 0x0f);
- return PC97338;
- }
-
- /* Read device identification (DID) for the PC87108 */
- outb(5, board_addr);
- id = inb(board_addr+1);
- if ((id & 0xf0) == PC87108) {
- MESSAGE("%s, Found NSC PC87108 chip, revision=%d\n",
- driver_name, id & 0x0f);
- return PC87108;
+ info->fir_base = reg;
+ } else {
+ /* Read function address register (FAR) */
+ outb(CFG_FAR, cfg_base);
+ reg = inb(cfg_base+1);
+
+ switch ((reg >> 4) & 0x03) {
+ case 0:
+ info->fir_base = 0x3f8;
+ break;
+ case 1:
+ info->fir_base = 0x2f8;
+ break;
+ case 2:
+ com = 3;
+ break;
+ case 3:
+ com = 4;
+ break;
+ }
+
+ if (com) {
+ switch ((reg >> 6) & 0x03) {
+ case 0:
+ if (com == 3)
+ info->fir_base = 0x3e8;
+ else
+ info->fir_base = 0x2e8;
+ break;
+ case 1:
+ if (com == 3)
+ info->fir_base = 0x338;
+ else
+ info->fir_base = 0x238;
+ break;
+ case 2:
+ if (com == 3)
+ info->fir_base = 0x2e8;
+ else
+ info->fir_base = 0x2e0;
+ break;
+ case 3:
+ if (com == 3)
+ info->fir_base = 0x220;
+ else
+ info->fir_base = 0x228;
+ break;
+ }
+ }
}
+ info->sir_base = info->fir_base;
+
+ /* Read PnP register 1 (PNP1) */
+ outb(CFG_PNP1, cfg_base);
+ reg = inb(cfg_base+1);
+
+ info->irq = reg >> 4;
+
+ /* Read PnP register 3 (PNP3) */
+ outb(CFG_PNP3, cfg_base);
+ reg = inb(cfg_base+1);
+
+ info->dma = (reg & 0x07) - 1;
- return -1;
+ /* Read power and test register (PTR) */
+ outb(CFG_PTR, cfg_base);
+ reg = inb(cfg_base+1);
+
+ info->suspended = reg & 0x01;
+
+ return 0;
}
/*
- * Function nsc_fir_probe (iobase, board_addr, irq, dma)
+ * Function nsc_ircc_setup (info)
*
* Returns non-negative on success.
*
*/
-static int nsc_fir_probe(int iobase, int board_addr, int irq, int dma)
+static int nsc_ircc_setup(chipio_t *info)
{
int version;
- __u8 chip;
-
- chip = nsc_fir_find_chip(board_addr);
- switch (chip) {
- case PC87108:
- nsc_fir_init_807(iobase, board_addr, irq, dma);
- break;
- case PC97338:
- nsc_fir_init_338(iobase, board_addr, irq, dma);
- break;
- default:
- /* Found no chip */
- return -1;
- }
+ int iobase = info->fir_base;
/* Read the Module ID */
switch_bank(iobase, BANK3);
@@ -490,23 +706,13 @@ static int nsc_fir_probe(int iobase, int board_addr, int irq, int dma)
ERROR("%s, Wrong chip version %02x\n", driver_name, version);
return -1;
}
- MESSAGE("%s, Found chip at base=0x%04x\n", driver_name, board_addr);
+ MESSAGE("%s, Found chip at base=0x%03x\n", driver_name,
+ info->cfg_base);
/* Switch to advanced mode */
switch_bank(iobase, BANK2);
outb(ECR1_EXT_SL, iobase+ECR1);
switch_bank(iobase, BANK0);
-
- /* Check if user has supplied the dongle id or not */
- if (!dongle_id) {
- dongle_id = nsc_fir_read_dongle_id(iobase);
-
- MESSAGE("%s, Found dongle: %s\n", driver_name,
- dongle_types[dongle_id]);
- } else {
- MESSAGE("%s, Using dongle: %s\n", driver_name,
- dongle_types[dongle_id]);
- }
/* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */
switch_bank(iobase, BANK0);
@@ -533,24 +739,21 @@ static int nsc_fir_probe(int iobase, int board_addr, int irq, int dma)
switch_bank(iobase, BANK0);
outb(IER_RXHDL_IE, iobase+IER);
- return dongle_id;
+ return 0;
}
/*
- * Function nsc_fir_read_dongle_id (void)
+ * Function nsc_ircc_read_dongle_id (void)
*
* Try to read dongle indentification. This procedure needs to be executed
* once after power-on/reset. It also needs to be used whenever you suspect
* that the user may have plugged/unplugged the IrDA Dongle.
- *
*/
-static int nsc_fir_read_dongle_id (int iobase)
+static int nsc_ircc_read_dongle_id (int iobase)
{
int dongle_id;
__u8 bank;
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
bank = inb(iobase+BSR);
/* Select Bank 7 */
@@ -568,8 +771,7 @@ static int nsc_fir_read_dongle_id (int iobase)
#ifdef BROKEN_DONGLE_ID
if (dongle_id == 0x0a)
dongle_id = 0x09;
-#endif
-
+#endif
/* Go back to bank 0 before returning */
switch_bank(iobase, BANK0);
@@ -579,14 +781,14 @@ static int nsc_fir_read_dongle_id (int iobase)
}
/*
- * Function nsc_fir_init_dongle_interface (iobase, dongle_id)
+ * Function nsc_ircc_init_dongle_interface (iobase, dongle_id)
*
* This function initializes the dongle for the transceiver that is
* used. This procedure needs to be executed once after
* power-on/reset. It also needs to be used whenever you suspect that
* the dongle is changed.
*/
-static void nsc_fir_init_dongle_interface (int iobase, int dongle_id)
+static void nsc_ircc_init_dongle_interface (int iobase, int dongle_id)
{
int bank;
@@ -625,11 +827,11 @@ static void nsc_fir_init_dongle_interface (int iobase, int dongle_id)
dongle_types[dongle_id]);
break;
case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
- dongle_types[dongle_id]);
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s\n",
+ dongle_types[dongle_id]);
break;
case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
- outb_p(0x28, iobase+7); /* Set irsl[0-2] as output */
+ outb(0x28, iobase+7); /* Set irsl[0-2] as output */
break;
case 0x0A: /* same as */
case 0x0B: /* Reserved */
@@ -668,18 +870,16 @@ static void nsc_fir_init_dongle_interface (int iobase, int dongle_id)
} /* set_up_dongle_interface */
/*
- * Function nsc_fir_change_dongle_speed (iobase, speed, dongle_id)
+ * Function nsc_ircc_change_dongle_speed (iobase, speed, dongle_id)
*
* Change speed of the attach dongle
*
*/
-static void nsc_fir_change_dongle_speed(int iobase, int speed, int dongle_id)
+static void nsc_ircc_change_dongle_speed(int iobase, int speed, int dongle_id)
{
unsigned long flags;
__u8 bank;
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
/* Save current bank */
bank = inb(iobase+BSR);
@@ -714,11 +914,14 @@ static void nsc_fir_change_dongle_speed(int iobase, int speed, int dongle_id)
dongle_types[dongle_id]);
break;
case 0x08: /* HP HSDL-2300, HP HSDL-3600/HSDL-3610 */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s\n",
dongle_types[dongle_id]);
+ outb(0x00, iobase+4);
+ if (speed > 115200)
+ outb(0x01, iobase+4);
+ break;
case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
- switch_bank(iobase, BANK7);
- outb_p(0x01, iobase+4);
+ outb(0x01, iobase+4);
if (speed == 4000000) {
save_flags(flags);
@@ -727,7 +930,7 @@ static void nsc_fir_change_dongle_speed(int iobase, int speed, int dongle_id)
outb(0x80, iobase+4);
restore_flags(flags);
} else
- outb_p(0x00, iobase+4);
+ outb(0x00, iobase+4);
break;
case 0x0A: /* same as */
case 0x0B: /* Reserved */
@@ -754,12 +957,12 @@ static void nsc_fir_change_dongle_speed(int iobase, int speed, int dongle_id)
}
/*
- * Function nsc_fir_change_speed (self, baud)
+ * Function nsc_ircc_change_speed (self, baud)
*
* Change the speed of the device
*
*/
-static void nsc_fir_change_speed(struct nsc_fir_cb *self, __u32 speed)
+static void nsc_ircc_change_speed(struct nsc_ircc_cb *self, __u32 speed)
{
struct net_device *dev = self->netdev;
__u8 mcr = MCR_SIR;
@@ -770,7 +973,7 @@ static void nsc_fir_change_speed(struct nsc_fir_cb *self, __u32 speed)
ASSERT(self != NULL, return;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Update accounting for new speed */
self->io.speed = speed;
@@ -821,7 +1024,7 @@ static void nsc_fir_change_speed(struct nsc_fir_cb *self, __u32 speed)
outb(mcr | MCR_TX_DFR, iobase+MCR);
/* Give some hits to the transceiver */
- nsc_fir_change_dongle_speed(iobase, speed, self->io.dongle_id);
+ nsc_ircc_change_dongle_speed(iobase, speed, self->io.dongle_id);
/* Set FIFO threshold to TX17, RX16 */
switch_bank(iobase, BANK0);
@@ -844,12 +1047,12 @@ static void nsc_fir_change_speed(struct nsc_fir_cb *self, __u32 speed)
switch_bank(iobase, BANK0);
if (speed > 115200) {
/* Install FIR xmit handler */
- dev->hard_start_xmit = nsc_fir_hard_xmit_fir;
+ dev->hard_start_xmit = nsc_ircc_hard_xmit_fir;
outb(IER_SFIF_IE, iobase+IER);
- nsc_fir_dma_receive(self);
+ nsc_ircc_dma_receive(self);
} else {
/* Install SIR xmit handler */
- dev->hard_start_xmit = nsc_fir_hard_xmit_sir;
+ dev->hard_start_xmit = nsc_ircc_hard_xmit_sir;
outb(IER_RXHDL_IE, iobase+IER);
}
@@ -858,24 +1061,24 @@ static void nsc_fir_change_speed(struct nsc_fir_cb *self, __u32 speed)
}
/*
- * Function nsc_fir_hard_xmit (skb, dev)
+ * Function nsc_ircc_hard_xmit (skb, dev)
*
* Transmit the frame!
*
*/
-static int nsc_fir_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
+static int nsc_ircc_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
{
- struct nsc_fir_cb *self;
+ struct nsc_ircc_cb *self;
unsigned long flags;
int iobase;
__u32 speed;
__u8 bank;
- self = (struct nsc_fir_cb *) dev->priv;
+ self = (struct nsc_ircc_cb *) dev->priv;
ASSERT(self != NULL, return 0;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Lock transmit buffer */
if (irda_lock((void *) &dev->tbusy) == FALSE)
@@ -894,6 +1097,8 @@ static int nsc_fir_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
self->tx_buff.truesize);
+
+ self->stats.tx_bytes += self->tx_buff.len;
/* Add interrupt on tx low level (will fire immediately) */
switch_bank(iobase, BANK0);
@@ -909,20 +1114,17 @@ static int nsc_fir_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
return 0;
}
-static int nsc_fir_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
+static int nsc_ircc_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
{
- struct nsc_fir_cb *self;
+ struct nsc_ircc_cb *self;
unsigned long flags;
int iobase;
__u32 speed;
__u8 bank;
int mtt, diff;
- self = (struct nsc_fir_cb *) dev->priv;
-
- ASSERT(self != NULL, return 0;);
-
- iobase = self->io.iobase;
+ self = (struct nsc_ircc_cb *) dev->priv;
+ iobase = self->io.fir_base;
/* Lock transmit buffer */
if (irda_lock((void *) &dev->tbusy) == FALSE)
@@ -942,6 +1144,8 @@ static int nsc_fir_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
self->tx_fifo.queue[self->tx_fifo.free].len = skb->len;
self->tx_fifo.tail += skb->len;
+ self->stats.tx_bytes += skb->len;
+
memcpy(self->tx_fifo.queue[self->tx_fifo.free].start, skb->data,
skb->len);
@@ -950,10 +1154,11 @@ static int nsc_fir_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
/* Start transmit only if there is currently no transmit going on */
if (self->tx_fifo.len == 1) {
+ /* Check if we must wait the min turn time or not */
mtt = irda_get_mtt(skb);
if (mtt) {
/* Check how much time we have used already */
- do_gettimeofday(&self->now);
+ get_fast_time(&self->now);
diff = self->now.tv_usec - self->stamp.tv_usec;
if (diff < 0)
diff += 1000000;
@@ -963,9 +1168,15 @@ static int nsc_fir_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
*/
if (mtt > diff) {
mtt -= diff;
+
+ /*
+ * Use timer if delay larger than 125 us, and
+ * use udelay for smaller values which should
+ * be acceptable
+ */
if (mtt > 125) {
/* Adjust for timer resolution */
- mtt = mtt / 125 + 1;
+ mtt = mtt / 125;
/* Setup timer */
switch_bank(iobase, BANK4);
@@ -985,34 +1196,35 @@ static int nsc_fir_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
} else
udelay(mtt);
}
- }
-
+ }
/* Enable DMA interrupt */
switch_bank(iobase, BANK0);
outb(IER_DMA_IE, iobase+IER);
- nsc_fir_dma_xmit(self, iobase);
+
+ /* Transmit frame */
+ nsc_ircc_dma_xmit(self, iobase);
}
+ out:
/* Not busy transmitting anymore if window is not full */
- if (self->tx_fifo.len < MAX_WINDOW)
+ if (self->tx_fifo.free < MAX_TX_WINDOW)
dev->tbusy = 0;
- out:
+
/* Restore bank register */
outb(bank, iobase+BSR);
spin_unlock_irqrestore(&self->lock, flags);
-
dev_kfree_skb(skb);
return 0;
}
/*
- * Function nsc_fir_dma_xmit (self, iobase)
+ * Function nsc_ircc_dma_xmit (self, iobase)
*
* Transmit data using DMA
*
*/
-static void nsc_fir_dma_xmit(struct nsc_fir_cb *self, int iobase)
+static void nsc_ircc_dma_xmit(struct nsc_ircc_cb *self, int iobase)
{
int bsr;
@@ -1043,13 +1255,13 @@ static void nsc_fir_dma_xmit(struct nsc_fir_cb *self, int iobase)
}
/*
- * Function nsc_fir_pio_xmit (self, iobase)
+ * Function nsc_ircc_pio_xmit (self, iobase)
*
* Transmit data using PIO. Returns the number of bytes that actually
* got transfered
*
*/
-static int nsc_fir_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
+static int nsc_ircc_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
{
int actual = 0;
__u8 bank;
@@ -1064,6 +1276,7 @@ static int nsc_fir_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
IRDA_DEBUG(4, __FUNCTION__
"(), warning, FIFO not empty yet!\n");
+ /* FIFO may still be filled to the Tx interrupt threshold */
fifo_size -= 17;
}
@@ -1083,13 +1296,13 @@ static int nsc_fir_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
}
/*
- * Function nsc_fir_dma_xmit_complete (self)
+ * Function nsc_ircc_dma_xmit_complete (self)
*
* The transfer of a frame in finished. This function will only be called
* by the interrupt handler
*
*/
-static int nsc_fir_dma_xmit_complete(struct nsc_fir_cb *self)
+static int nsc_ircc_dma_xmit_complete(struct nsc_ircc_cb *self)
{
int iobase;
__u8 bank;
@@ -1097,7 +1310,7 @@ static int nsc_fir_dma_xmit_complete(struct nsc_fir_cb *self)
IRDA_DEBUG(2, __FUNCTION__ "()\n");
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Save current bank */
bank = inb(iobase+BSR);
@@ -1115,11 +1328,11 @@ static int nsc_fir_dma_xmit_complete(struct nsc_fir_cb *self)
outb(ASCR_TXUR, iobase+ASCR);
} else {
self->stats.tx_packets++;
- self->stats.tx_bytes += self->tx_buff.len;
}
-
+
+ /* Check if we need to change the speed */
if (self->new_speed) {
- nsc_fir_change_speed(self, self->new_speed);
+ nsc_ircc_change_speed(self, self->new_speed);
self->new_speed = 0;
}
@@ -1129,17 +1342,24 @@ static int nsc_fir_dma_xmit_complete(struct nsc_fir_cb *self)
/* Any frames to be sent back-to-back? */
if (self->tx_fifo.len) {
- nsc_fir_dma_xmit(self, iobase);
+ nsc_ircc_dma_xmit(self, iobase);
/* Not finished yet! */
ret = FALSE;
+ } else {
+ /* Reset Tx FIFO info */
+ self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
+ self->tx_fifo.tail = self->tx_buff.head;
}
- /* Not busy transmitting anymore */
- self->netdev->tbusy = 0;
+ /* Make sure we have room for more frames */
+ if (self->tx_fifo.free < MAX_TX_WINDOW) {
+ /* Not busy transmitting anymore */
+ self->netdev->tbusy = 0;
- /* Tell the network layer, that we can accept more frames */
- mark_bh(NET_BH);
+ /* Tell the network layer, that we can accept more frames */
+ mark_bh(NET_BH);
+ }
/* Restore bank */
outb(bank, iobase+BSR);
@@ -1148,20 +1368,18 @@ static int nsc_fir_dma_xmit_complete(struct nsc_fir_cb *self)
}
/*
- * Function nsc_fir_dma_receive (self)
+ * Function nsc_ircc_dma_receive (self)
*
* Get ready for receiving a frame. The device will initiate a DMA
* if it starts to receive a frame.
*
*/
-static int nsc_fir_dma_receive(struct nsc_fir_cb *self)
+static int nsc_ircc_dma_receive(struct nsc_ircc_cb *self)
{
int iobase;
__u8 bsr;
- ASSERT(self != NULL, return -1;);
-
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Reset Tx FIFO info */
self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
@@ -1184,7 +1402,9 @@ static int nsc_fir_dma_receive(struct nsc_fir_cb *self)
/* Reset Rx FIFO. This will also flush the ST_FIFO */
switch_bank(iobase, BANK0);
outb(FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
- self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0;
+
+ self->st_fifo.len = self->st_fifo.pending_bytes = 0;
+ self->st_fifo.tail = self->st_fifo.head = 0;
setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize,
DMA_RX_MODE);
@@ -1200,18 +1420,18 @@ static int nsc_fir_dma_receive(struct nsc_fir_cb *self)
}
/*
- * Function nsc_fir_dma_receive_complete (self)
+ * Function nsc_ircc_dma_receive_complete (self)
*
* Finished with receiving frames
*
*
*/
-static int nsc_fir_dma_receive_complete(struct nsc_fir_cb *self, int iobase)
+static int nsc_ircc_dma_receive_complete(struct nsc_ircc_cb *self, int iobase)
{
- struct sk_buff *skb;
struct st_fifo *st_fifo;
- __u8 bank;
+ struct sk_buff *skb;
__u8 status;
+ __u8 bank;
int len;
st_fifo = &self->st_fifo;
@@ -1219,22 +1439,27 @@ static int nsc_fir_dma_receive_complete(struct nsc_fir_cb *self, int iobase)
/* Save current bank */
bank = inb(iobase+BSR);
- /* Read status FIFO */
+ /* Read all entries in status FIFO */
switch_bank(iobase, BANK5);
while ((status = inb(iobase+FRM_ST)) & FRM_ST_VLD) {
- st_fifo->entries[st_fifo->tail].status = status;
+ /* We must empty the status FIFO no matter what */
+ len = inb(iobase+RFLFL) | ((inb(iobase+RFLFH) & 0x1f) << 8);
- st_fifo->entries[st_fifo->tail].len = inb(iobase+RFLFL);
- st_fifo->entries[st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
-
+ if (st_fifo->tail >= MAX_RX_WINDOW)
+ continue;
+
+ st_fifo->entries[st_fifo->tail].status = status;
+ st_fifo->entries[st_fifo->tail].len = len;
+ st_fifo->pending_bytes += len;
st_fifo->tail++;
st_fifo->len++;
}
/* Try to process all entries in status FIFO */
- while (st_fifo->len) {
+ while (st_fifo->len > 0) {
/* Get first entry */
status = st_fifo->entries[st_fifo->head].status;
len = st_fifo->entries[st_fifo->head].len;
+ st_fifo->pending_bytes -= len;
st_fifo->head++;
st_fifo->len--;
@@ -1265,36 +1490,46 @@ static int nsc_fir_dma_receive_complete(struct nsc_fir_cb *self, int iobase)
if (status & FRM_ST_OVR2)
self->stats.rx_fifo_errors++;
} else {
- /* Check if we have transfered all data to memory */
- switch_bank(iobase, BANK0);
- if (inb(iobase+LSR) & LSR_RXDA) {
- /* Put this entry back in fifo */
- st_fifo->head--;
- st_fifo->len++;
- st_fifo->entries[st_fifo->head].status = status;
- st_fifo->entries[st_fifo->head].len = len;
-
- /* Restore bank register */
- outb(bank, iobase+BSR);
+ /*
+ * First we must make sure that the frame we
+ * want to deliver is all in main memory. If we
+ * cannot tell, then we check if the Rx FIFO is
+ * empty. If not then we will have to take a nap
+ * and try again later.
+ */
+ if (st_fifo->pending_bytes < self->io.fifo_size) {
+ switch_bank(iobase, BANK0);
+ if (inb(iobase+LSR) & LSR_RXDA) {
+ /* Put this entry back in fifo */
+ st_fifo->head--;
+ st_fifo->len++;
+ st_fifo->pending_bytes += len;
+ st_fifo->entries[st_fifo->head].status = status;
+ st_fifo->entries[st_fifo->head].len = len;
- return FALSE; /* I'll be back! */
+ /* Restore bank register */
+ outb(bank, iobase+BSR);
+
+ return FALSE; /* I'll be back! */
+ }
}
/*
- * Remember when we received this frame, so we can
+ * Remember the time we received this frame, so we can
* reduce the min turn time a bit since we will know
* how much time we have used for protocol processing
*/
- do_gettimeofday(&self->stamp);
+ get_fast_time(&self->stamp);
skb = dev_alloc_skb(len+1);
if (skb == NULL) {
WARNING(__FUNCTION__ "(), memory squeeze, "
"dropping frame.\n");
-
+ self->stats.rx_dropped++;
+
/* Restore bank register */
outb(bank, iobase+BSR);
-
+
return FALSE;
}
@@ -1312,6 +1547,7 @@ static int nsc_fir_dma_receive_complete(struct nsc_fir_cb *self, int iobase)
/* Move to next frame */
self->rx_buff.data += len;
+ self->stats.rx_bytes += len;
self->stats.rx_packets++;
skb->dev = self->netdev;
@@ -1327,21 +1563,17 @@ static int nsc_fir_dma_receive_complete(struct nsc_fir_cb *self, int iobase)
}
/*
- * Function nsc_fir_pio_receive (self)
+ * Function nsc_ircc_pio_receive (self)
*
* Receive all data in receiver FIFO
*
*/
-static void nsc_fir_pio_receive(struct nsc_fir_cb *self)
+static void nsc_ircc_pio_receive(struct nsc_ircc_cb *self)
{
- __u8 byte = 0x00;
+ __u8 byte;
int iobase;
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
- ASSERT(self != NULL, return;);
-
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Receive all characters in Rx FIFO */
do {
@@ -1352,20 +1584,19 @@ static void nsc_fir_pio_receive(struct nsc_fir_cb *self)
}
/*
- * Function nsc_fir_sir_interrupt (self, eir)
+ * Function nsc_ircc_sir_interrupt (self, eir)
*
* Handle SIR interrupt
*
*/
-static __u8 nsc_fir_sir_interrupt(struct nsc_fir_cb *self, int eir)
+static void nsc_ircc_sir_interrupt(struct nsc_ircc_cb *self, int eir)
{
int actual;
- __u8 new_ier = 0;
/* Check if transmit FIFO is low on data */
if (eir & EIR_TXLDL_EV) {
/* Write data left in transmit buffer */
- actual = nsc_fir_pio_write(self->io.iobase,
+ actual = nsc_ircc_pio_write(self->io.fir_base,
self->tx_buff.data,
self->tx_buff.len,
self->io.fifo_size);
@@ -1376,14 +1607,14 @@ static __u8 nsc_fir_sir_interrupt(struct nsc_fir_cb *self, int eir)
/* Check if finished */
if (self->tx_buff.len > 0)
- new_ier |= IER_TXLDL_IE;
+ self->ier = IER_TXLDL_IE;
else {
self->netdev->tbusy = 0; /* Unlock */
self->stats.tx_packets++;
mark_bh(NET_BH);
- new_ier |= IER_TXEMP_IE;
+ self->ier = IER_TXEMP_IE;
}
}
@@ -1392,56 +1623,62 @@ static __u8 nsc_fir_sir_interrupt(struct nsc_fir_cb *self, int eir)
/* Check if we need to change the speed? */
if (self->new_speed) {
IRDA_DEBUG(2, __FUNCTION__ "(), Changing speed!\n");
- nsc_fir_change_speed(self, self->new_speed);
+ nsc_ircc_change_speed(self, self->new_speed);
self->new_speed = 0;
- }
+ /* Check if we are going to FIR */
+ if (self->io.speed > 115200) {
+ /* Should wait for status FIFO interrupt */
+ self->ier = IER_SFIF_IE;
+
+ /* No need to do anymore SIR stuff */
+ return;
+ }
+ }
/* Turn around and get ready to receive some data */
self->io.direction = IO_RECV;
- new_ier |= IER_RXHDL_IE;
+ self->ier = IER_RXHDL_IE;
}
/* Rx FIFO threshold or timeout */
if (eir & EIR_RXHDL_EV) {
- nsc_fir_pio_receive(self);
+ nsc_ircc_pio_receive(self);
/* Keep receiving */
- new_ier |= IER_RXHDL_IE;
+ self->ier = IER_RXHDL_IE;
}
- return new_ier;
}
/*
- * Function nsc_fir_fir_interrupt (self, eir)
+ * Function nsc_ircc_fir_interrupt (self, eir)
*
* Handle MIR/FIR interrupt
*
*/
-static __u8 nsc_fir_fir_interrupt(struct nsc_fir_cb *self, int iobase, int eir)
+static void nsc_ircc_fir_interrupt(struct nsc_ircc_cb *self, int iobase,
+ int eir)
{
- __u8 new_ier = 0;
__u8 bank;
bank = inb(iobase+BSR);
- /* Status event, or end of frame detected in FIFO */
- if (eir & (EIR_SFIF_EV|EIR_LS_EV)) {
- if (nsc_fir_dma_receive_complete(self, iobase)) {
-
+ /* Status FIFO event*/
+ if (eir & EIR_SFIF_EV) {
+ if (nsc_ircc_dma_receive_complete(self, iobase)) {
/* Wait for next status FIFO interrupt */
- new_ier |= IER_SFIF_IE;
+ self->ier = IER_SFIF_IE;
} else {
- /* DMA not finished yet */
-
- /* Set timer value, resolution 125 us */
+ /*
+ * DMA not finished yet, so try again later, set
+ * timer value, resolution 125 us
+ */
switch_bank(iobase, BANK4);
- outb(0x0f, iobase+TMRL); /* 125 us * 15 */
+ outb(0x02, iobase+TMRL); /* 2 * 125 us */
outb(0x00, iobase+TMRH);
/* Start timer */
outb(IRCR1_TMR_EN, iobase+IRCR1);
-
- new_ier |= IER_TMR_IE;
+ self->ier = IER_TMR_IE | IER_SFIF_IE;
}
} else if (eir & EIR_TMR_EV) { /* Timer finished */
/* Disable timer */
@@ -1452,101 +1689,102 @@ static __u8 nsc_fir_fir_interrupt(struct nsc_fir_cb *self, int iobase, int eir)
switch_bank(iobase, BANK0);
outb(ASCR_CTE, iobase+ASCR);
- /* Check if this is a TX timer interrupt */
+ /* Check if this is a Tx timer interrupt */
if (self->io.direction == IO_XMIT) {
- nsc_fir_dma_xmit(self, iobase);
+ nsc_ircc_dma_xmit(self, iobase);
/* Interrupt on DMA */
- new_ier |= IER_DMA_IE;
+ self->ier = IER_DMA_IE;
} else {
/* Check if DMA has now finished */
- nsc_fir_dma_receive_complete(self, iobase);
+ nsc_ircc_dma_receive_complete(self, iobase);
- new_ier |= IER_SFIF_IE;
+ self->ier = IER_SFIF_IE;
}
- } else if (eir & EIR_DMA_EV) { /* Finished with transmission */
- if (nsc_fir_dma_xmit_complete(self)) {
+ } else if (eir & EIR_DMA_EV) {
+ /* Finished with all transmissions? */
+ if (nsc_ircc_dma_xmit_complete(self)) {
/* Check if there are more frames to be transmitted */
if (irda_device_txqueue_empty(self->netdev)) {
/* Prepare for receive */
- nsc_fir_dma_receive(self);
+ nsc_ircc_dma_receive(self);
- new_ier = IER_LS_IE|IER_SFIF_IE;
+ self->ier = IER_SFIF_IE;
}
} else {
/* Not finished yet, so interrupt on DMA again */
- new_ier |= IER_DMA_IE;
+ self->ier = IER_DMA_IE;
}
}
outb(bank, iobase+BSR);
-
- return new_ier;
}
/*
- * Function nsc_fir_interrupt (irq, dev_id, regs)
+ * Function nsc_ircc_interrupt (irq, dev_id, regs)
*
* An interrupt from the chip has arrived. Time to do some work
*
*/
-static void nsc_fir_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static void nsc_ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = (struct net_device *) dev_id;
- struct nsc_fir_cb *self;
- __u8 bsr, eir, ier;
+ struct nsc_ircc_cb *self;
+ __u8 bsr, eir;
int iobase;
if (!dev) {
- printk(KERN_WARNING "%s: irq %d for unknown device.\n",
- driver_name, irq);
+ WARNING("%s: irq %d for unknown device.\n", driver_name, irq);
return;
}
- self = (struct nsc_fir_cb *) dev->priv;
+ self = (struct nsc_ircc_cb *) dev->priv;
spin_lock(&self->lock);
dev->interrupt = 1;
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
bsr = inb(iobase+BSR); /* Save current bank */
switch_bank(iobase, BANK0);
- ier = inb(iobase+IER);
- eir = inb(iobase+EIR) & ier; /* Mask out the interesting ones */
+ self->ier = inb(iobase+IER);
+ eir = inb(iobase+EIR) & self->ier; /* Mask out the interesting ones */
outb(0, iobase+IER); /* Disable interrupts */
if (eir) {
/* Dispatch interrupt handler for the current speed */
if (self->io.speed > 115200)
- ier = nsc_fir_fir_interrupt(self, iobase, eir);
+ nsc_ircc_fir_interrupt(self, iobase, eir);
else
- ier = nsc_fir_sir_interrupt(self, eir);
+ nsc_ircc_sir_interrupt(self, eir);
}
-
- outb(ier, iobase+IER); /* Restore interrupts */
- outb(bsr, iobase+BSR); /* Restore bank register */
+
+ outb(self->ier, iobase+IER); /* Restore interrupts */
+ outb(bsr, iobase+BSR); /* Restore bank register */
dev->interrupt = 0;
spin_unlock(&self->lock);
}
/*
- * Function nsc_fir_is_receiving (self)
+ * Function nsc_ircc_is_receiving (self)
*
* Return TRUE is we are currently receiving a frame
*
*/
-static int nsc_fir_is_receiving(struct nsc_fir_cb *self)
+static int nsc_ircc_is_receiving(struct nsc_ircc_cb *self)
{
+ unsigned long flags;
int status = FALSE;
int iobase;
__u8 bank;
ASSERT(self != NULL, return FALSE;);
+ spin_lock_irqsave(&self->lock, flags);
+
if (self->io.speed > 115200) {
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Check if rx FIFO is not empty */
bank = inb(iobase+BSR);
@@ -1559,16 +1797,18 @@ static int nsc_fir_is_receiving(struct nsc_fir_cb *self)
} else
status = (self->rx_buff.state != OUTSIDE_FRAME);
+ spin_unlock_irqrestore(&self->lock, flags);
+
return status;
}
/*
- * Function nsc_fir_net_init (dev)
+ * Function nsc_ircc_net_init (dev)
*
* Initialize network device
*
*/
-static int nsc_fir_net_init(struct net_device *dev)
+static int nsc_ircc_net_init(struct net_device *dev)
{
IRDA_DEBUG(4, __FUNCTION__ "()\n");
@@ -1581,29 +1821,29 @@ static int nsc_fir_net_init(struct net_device *dev)
}
/*
- * Function nsc_fir_net_open (dev)
+ * Function nsc_ircc_net_open (dev)
*
* Start the device
*
*/
-static int nsc_fir_net_open(struct net_device *dev)
+static int nsc_ircc_net_open(struct net_device *dev)
{
- struct nsc_fir_cb *self;
+ struct nsc_ircc_cb *self;
int iobase;
__u8 bank;
IRDA_DEBUG(4, __FUNCTION__ "()\n");
ASSERT(dev != NULL, return -1;);
- self = (struct nsc_fir_cb *) dev->priv;
+ self = (struct nsc_ircc_cb *) dev->priv;
ASSERT(self != NULL, return 0;);
- iobase = self->io.iobase;
-
- if (request_irq(self->io.irq, nsc_fir_interrupt, 0, dev->name,
- (void *) dev))
- {
+ iobase = self->io.fir_base;
+
+ if (request_irq(self->io.irq, nsc_ircc_interrupt, 0, dev->name, dev)) {
+ WARNING("%s, unable to allocate irq=%d\n", driver_name,
+ self->io.irq);
return -EAGAIN;
}
/*
@@ -1611,6 +1851,8 @@ static int nsc_fir_net_open(struct net_device *dev)
* failure.
*/
if (request_dma(self->io.dma, dev->name)) {
+ WARNING("%s, unable to allocate dma=%d\n", driver_name,
+ self->io.dma);
free_irq(self->io.irq, self);
return -EAGAIN;
}
@@ -1642,22 +1884,22 @@ static int nsc_fir_net_open(struct net_device *dev)
}
/*
- * Function nsc_fir_net_close (dev)
+ * Function nsc_ircc_net_close (dev)
*
* Stop the device
*
*/
-static int nsc_fir_net_close(struct net_device *dev)
+static int nsc_ircc_net_close(struct net_device *dev)
{
- struct nsc_fir_cb *self;
+ struct nsc_ircc_cb *self;
int iobase;
__u8 bank;
IRDA_DEBUG(4, __FUNCTION__ "()\n");
ASSERT(dev != NULL, return -1;);
- self = (struct nsc_fir_cb *) dev->priv;
-
+
+ self = (struct nsc_ircc_cb *) dev->priv;
ASSERT(self != NULL, return 0;);
/* Stop device */
@@ -1669,7 +1911,7 @@ static int nsc_fir_net_close(struct net_device *dev)
irlap_close(self->irlap);
self->irlap = NULL;
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
disable_dma(self->io.dma);
@@ -1692,15 +1934,15 @@ static int nsc_fir_net_close(struct net_device *dev)
}
/*
- * Function nsc_fir_net_ioctl (dev, rq, cmd)
+ * Function nsc_ircc_net_ioctl (dev, rq, cmd)
*
* Process IOCTL commands for this device
*
*/
-static int nsc_fir_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int nsc_ircc_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct if_irda_req *irq = (struct if_irda_req *) rq;
- struct nsc_fir_cb *self;
+ struct nsc_ircc_cb *self;
unsigned long flags;
int ret = 0;
@@ -1718,13 +1960,13 @@ static int nsc_fir_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
switch (cmd) {
case SIOCSBANDWIDTH: /* Set bandwidth */
- nsc_fir_change_speed(self, irq->ifr_baudrate);
+ nsc_ircc_change_speed(self, irq->ifr_baudrate);
break;
case SIOCSMEDIABUSY: /* Set media busy */
irda_device_set_media_busy(self->netdev, TRUE);
break;
case SIOCGRECEIVING: /* Check if we are receiving right now */
- irq->ifr_receiving = nsc_fir_is_receiving(self);
+ irq->ifr_receiving = nsc_ircc_is_receiving(self);
break;
default:
ret = -EOPNOTSUPP;
@@ -1735,54 +1977,60 @@ static int nsc_fir_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return ret;
}
-static struct net_device_stats *nsc_fir_net_get_stats(struct net_device *dev)
+static struct net_device_stats *nsc_ircc_net_get_stats(struct net_device *dev)
{
- struct nsc_fir_cb *self = (struct nsc_fir_cb *) dev->priv;
+ struct nsc_ircc_cb *self = (struct nsc_ircc_cb *) dev->priv;
return &self->stats;
}
#ifdef CONFIG_APM
-static void nsc_fir_suspend(struct nsc_fir_cb *self)
+static void nsc_ircc_suspend(struct nsc_ircc_cb *self)
{
- int i = 10;
-
MESSAGE("%s, Suspending\n", driver_name);
- if (self->suspend)
+ if (self->io.suspended)
return;
- self->suspend = 1;
-}
+ nsc_ircc_net_close(self->netdev);
+ self->io.suspended = 1;
+}
-static void nsc_fir_wakeup(struct nsc_fir_cb *self)
+static void nsc_ircc_wakeup(struct nsc_ircc_cb *self)
{
struct net_device *dev = self->netdev;
- unsigned long flags;
+ int iobase;
- if (!self->suspend)
+ if (!self->io.suspended)
return;
- save_flags(flags);
- cli();
+ iobase = self->io.fir_base;
- restore_flags(flags);
+ /* Switch to advanced mode */
+ switch_bank(iobase, BANK2);
+ outb(ECR1_EXT_SL, iobase+ECR1);
+ switch_bank(iobase, BANK0);
+
+ nsc_ircc_net_open(self->netdev);
+
MESSAGE("%s, Waking up\n", driver_name);
+
+ self->io.suspended = 0;
}
-static int nsc_fir_apmproc(apm_event_t event)
+static int nsc_ircc_apmproc(apm_event_t event)
{
- static int down = 0; /* Filter out double events */
+ static int down = 0; /* Filter out double events */
int i;
switch (event) {
case APM_SYS_SUSPEND:
case APM_USER_SUSPEND:
if (!down) {
- for (i = 0; i < 4; i++) {
+ for (i=0; i<4; i++) {
if (dev_self[i])
- nsc_fir_suspend(dev_self[i]);
+ nsc_ircc_suspend(dev_self[i]);
}
}
down = 1;
@@ -1790,9 +2038,9 @@ static int nsc_fir_apmproc(apm_event_t event)
case APM_NORMAL_RESUME:
case APM_CRITICAL_RESUME:
if (down) {
- for (i = 0; i < 4; i++) {
+ for (i=0; i<4; i++) {
if (dev_self[i])
- nsc_fir_wakeup(dev_self[i]);
+ nsc_ircc_wakeup(dev_self[i]);
}
}
down = 0;
@@ -1804,22 +2052,22 @@ static int nsc_fir_apmproc(apm_event_t event)
#ifdef MODULE
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
-MODULE_DESCRIPTION("NSC FIR IrDA Device Driver");
+MODULE_DESCRIPTION("NSC IrDA Device Driver");
MODULE_PARM(qos_mtt_bits, "i");
-MODULE_PARM(io, "1-4i");
-MODULE_PARM(io2, "1-4i");
+MODULE_PARM(io, "1-4i");
MODULE_PARM(irq, "1-4i");
+MODULE_PARM(dma, "1-4i");
MODULE_PARM(dongle_id, "i");
int init_module(void)
{
- return nsc_fir_init();
+ return nsc_ircc_init();
}
void cleanup_module(void)
{
- nsc_fir_cleanup();
+ nsc_ircc_cleanup();
}
#endif /* MODULE */
diff --git a/drivers/net/irda/smc-ircc.c b/drivers/net/irda/smc-ircc.c
index 1d857c2b0..48b38227e 100644
--- a/drivers/net/irda/smc-ircc.c
+++ b/drivers/net/irda/smc-ircc.c
@@ -1,12 +1,12 @@
/*********************************************************************
*
* Filename: smc-ircc.c
- * Version: 0.3
+ * Version: 0.4
* Description: Driver for the SMC Infrared Communications Controller
* Status: Experimental.
* Author: Thomas Davis (tadavis@jps.net)
* Created at:
- * Modified at: Wed Jan 5 12:38:06 2000
+ * Modified at: Fri Jan 21 09:41:08 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999-2000 Dag Brattli
@@ -28,11 +28,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
- * SIO's: SMC FDC37N869, FDC37C669
+ * SIO's: SMC FDC37N869, FDC37C669, FDC37N958
* Applicable Models : Fujitsu Lifebook 635t, Sony PCG-505TX
*
********************************************************************/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -44,11 +45,16 @@
#include <linux/malloc.h>
#include <linux/init.h>
#include <linux/rtnetlink.h>
+#include <linux/serial_reg.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/byteorder.h>
+#ifdef CONFIG_APM
+#include <linux/apm_bios.h>
+#endif
+
#include <net/irda/wrapper.h>
#include <net/irda/irda.h>
#include <net/irda/irmod.h>
@@ -62,10 +68,10 @@ static char *driver_name = "smc-ircc";
#define CHIP_IO_EXTENT 8
-static unsigned int io[] = { 0x2e8, 0x140, 0x118, 0x240 };
-static unsigned int io2[] = { 0x2f8, 0x3e8, 0x2e8, 0x3e8 };
+static unsigned int io[] = { ~0, ~0 };
+static unsigned int io2[] = { 0, 0 };
-static struct ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL};
+static struct ircc_cb *dev_self[] = { NULL, NULL};
/* Some prototypes */
static int ircc_open(int i, unsigned int iobase, unsigned int board_addr);
@@ -73,17 +79,30 @@ static int ircc_open(int i, unsigned int iobase, unsigned int board_addr);
static int ircc_close(struct ircc_cb *self);
#endif /* MODULE */
static int ircc_probe(int iobase, int board_addr);
-static int ircc_probe_smc(int *ioaddr, int *ioaddr2);
-static int ircc_dma_receive(struct ircc_cb *self);
-static int ircc_dma_receive_complete(struct ircc_cb *self, int iobase);
+static int ircc_probe_58(smc_chip_t *chip, chipio_t *info);
+static int ircc_probe_69(smc_chip_t *chip, chipio_t *info);
+static int ircc_dma_receive(struct ircc_cb *self, int iobase);
+static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase);
static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev);
-static void ircc_dma_xmit(struct ircc_cb *self, int iobase);
+static void ircc_dma_xmit(struct ircc_cb *self, int iobase, int bofs);
static void ircc_change_speed(void *priv, __u32 speed);
static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int ircc_is_receiving(struct ircc_cb *self);
static int ircc_net_open(struct net_device *dev);
static int ircc_net_close(struct net_device *dev);
+#ifdef CONFIG_APM
+static int ircc_apmproc(apm_event_t event);
+#endif /* CONFIG_APM */
+
+/* These are the currently known SMC chipsets */
+static smc_chip_t chips[] =
+{
+ { "FDC37C669", 0x55, 0x55, 0x0d, 0x04, ircc_probe_69 },
+ { "FDC37N869", 0x55, 0x00, 0x0d, 0x29, ircc_probe_69 },
+ { "FDC37N958", 0x55, 0x55, 0x20, 0x09, ircc_probe_58 },
+ { NULL }
+};
static int ircc_irq=255;
static int ircc_dma=255;
@@ -102,26 +121,38 @@ static inline void register_bank(int iobase, int bank)
*/
int __init ircc_init(void)
{
- int ioaddr, ioaddr2;
+ static int smcreg[] = { 0x3f0, 0x370 };
+ smc_chip_t *chip;
+ chipio_t info;
+ int ret = -ENODEV;
int i;
IRDA_DEBUG(0, __FUNCTION__ "\n");
- for (i=0; (io[i] < 2000) && (i < 4); i++) {
- int ioaddr = io[i];
- if (check_region(ioaddr, CHIP_IO_EXTENT))
- continue;
- if (ircc_open(i, io[i], io2[i]) == 0)
- return 0;
- }
- /* last chance saloon, see what the controller says */
- if (ircc_probe_smc(&ioaddr, &ioaddr2) == 0) {
- if (check_region(ioaddr, CHIP_IO_EXTENT) == 0)
- if (ircc_open(0, ioaddr, ioaddr2) == 0)
- return 0;
+ /* Probe for all the NSC chipsets we know about */
+ for (chip=chips; chip->name ; chip++,i++) {
+ for (i=0; i<2; i++) {
+ info.cfg_base = smcreg[i];
+
+ /*
+ * First we check if the user has supplied any
+ * parameters which we should use instead of probed
+ * values
+ */
+ if (io[i] < 2000) {
+ info.fir_base = io[i];
+ info.sir_base = io2[i];
+ } else if (chip->probe(chip, &info) < 0)
+ continue;
+ if (check_region(info.fir_base, CHIP_IO_EXTENT) < 0)
+ continue;
+ if (check_region(info.sir_base, CHIP_IO_EXTENT) < 0)
+ continue;
+ if (ircc_open(i, info.fir_base, info.sir_base) == 0)
+ ret = 0;
+ }
}
-
- return -ENODEV;
+ return ret;
}
/*
@@ -137,7 +168,7 @@ static void ircc_cleanup(void)
IRDA_DEBUG(0, __FUNCTION__ "\n");
- for (i=0; i < 4; i++) {
+ for (i=0; i < 2; i++) {
if (dev_self[i])
ircc_close(dev_self[i]);
}
@@ -150,7 +181,7 @@ static void ircc_cleanup(void)
* Open driver instance
*
*/
-static int ircc_open(int i, unsigned int iobase, unsigned int iobase2)
+static int ircc_open(int i, unsigned int fir_base, unsigned int sir_base)
{
struct ircc_cb *self;
struct irport_cb *irport;
@@ -159,9 +190,9 @@ static int ircc_open(int i, unsigned int iobase, unsigned int iobase2)
IRDA_DEBUG(0, __FUNCTION__ "\n");
- if ((config = ircc_probe(iobase, iobase2)) == -1) {
+ if ((config = ircc_probe(fir_base, sir_base)) == -1) {
IRDA_DEBUG(0, __FUNCTION__
- "(), addr 0x%04x - no device found!\n", iobase);
+ "(), addr 0x%04x - no device found!\n", fir_base);
return -1;
}
@@ -180,7 +211,7 @@ static int ircc_open(int i, unsigned int iobase, unsigned int iobase2)
/* Need to store self somewhere */
dev_self[i] = self;
- irport = irport_open(0, iobase2, config >> 4 & 0x0f);
+ irport = irport_open(i, sir_base, config >> 4 & 0x0f);
if (!irport)
return -ENODEV;
@@ -190,34 +221,32 @@ static int ircc_open(int i, unsigned int iobase, unsigned int iobase2)
irport->priv = self;
/* Initialize IO */
- self->io.iobase = iobase;
- self->io.iobase2 = iobase2; /* Used by irport */
+ self->io.fir_base = fir_base;
+ self->io.sir_base = sir_base; /* Used by irport */
self->io.irq = config >> 4 & 0x0f;
if (ircc_irq < 255) {
MESSAGE("%s, Overriding IRQ - chip says %d, using %d\n",
driver_name, self->io.irq, ircc_irq);
self->io.irq = ircc_irq;
}
- self->io.io_ext = CHIP_IO_EXTENT;
- self->io.io_ext2 = 8; /* Used by irport */
+ self->io.fir_ext = CHIP_IO_EXTENT;
+ self->io.sir_ext = 8; /* Used by irport */
self->io.dma = config & 0x0f;
if (ircc_dma < 255) {
MESSAGE("%s, Overriding DMA - chip says %d, using %d\n",
driver_name, self->io.dma, ircc_dma);
self->io.dma = ircc_dma;
}
- self->io.fifo_size = 16;
/* Lock the port that we need */
- ret = check_region(self->io.iobase, self->io.io_ext);
+ ret = check_region(self->io.fir_base, self->io.fir_ext);
if (ret < 0) {
- IRDA_DEBUG(0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
- self->io.iobase);
- /* ircc_cleanup(self->self); */
+ IRDA_DEBUG(0, __FUNCTION__ ": can't get fir_base of 0x%03x\n",
+ self->io.fir_base);
+ kfree(self);
return -ENODEV;
}
-
- request_region(self->io.iobase, self->io.io_ext, driver_name);
+ request_region(self->io.fir_base, self->io.fir_ext, driver_name);
/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&irport->qos);
@@ -229,7 +258,7 @@ static int ircc_open(int i, unsigned int iobase, unsigned int iobase2)
irport->qos.min_turn_time.bits = 0x07;
irda_qos_bits_to_value(&irport->qos);
- irport->flags = IFF_FIR|IFF_SIR|IFF_DMA|IFF_PIO;
+ irport->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO;
/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
self->rx_buff.truesize = 4000;
@@ -256,6 +285,7 @@ static int ircc_open(int i, unsigned int iobase, unsigned int iobase2)
/* Override the speed change function, since we must control it now */
irport->change_speed = &ircc_change_speed;
+ irport->interrupt = &ircc_interrupt;
self->netdev->open = &ircc_net_open;
self->netdev->stop = &ircc_net_close;
@@ -279,23 +309,26 @@ static int ircc_close(struct ircc_cb *self)
ASSERT(self != NULL, return -1;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
irport_close(self->irport);
+ /* Stop interrupts */
register_bank(iobase, 0);
outb(0, iobase+IRCC_IER);
outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
-
+ outb(0x00, iobase+IRCC_MASTER);
+#if 0
+ /* Reset to SIR mode */
register_bank(iobase, 1);
-
outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase+IRCC_SCE_CFGA);
outb(IRCC_CFGB_IR, iobase+IRCC_SCE_CFGB);
-
+#endif
/* Release the PORT that this driver is using */
- IRDA_DEBUG(0, __FUNCTION__ "(), releasing 0x%03x\n", self->io.iobase);
+ IRDA_DEBUG(0, __FUNCTION__ "(), releasing 0x%03x\n",
+ self->io.fir_base);
- release_region(self->io.iobase, self->io.io_ext);
+ release_region(self->io.fir_base, self->io.fir_ext);
if (self->tx_buff.head)
kfree(self->tx_buff.head);
@@ -310,58 +343,106 @@ static int ircc_close(struct ircc_cb *self)
#endif /* MODULE */
/*
- * Function ircc_probe_smc (ioaddr, ioaddr2)
+ * Function ircc_probe_69 (chip, info)
*
- * Probe the SMC Chip for an IrDA port
+ * Probes for the SMC FDC37C669 and FDC37N869
*
*/
-static int ircc_probe_smc(int *ioaddr, int *ioaddr2)
+static int ircc_probe_69(smc_chip_t *chip, chipio_t *info)
{
- static int smcreg[] = { 0x3f0, 0x370 };
+ int cfg_base = info->cfg_base;
__u8 devid, mode;
- __u8 conf_reg;
- int ret = -1;
+ int ret = -ENODEV;
int fir_io;
- int i;
IRDA_DEBUG(0, __FUNCTION__ "()\n");
- for (i = 0; i < 2 && ret == -1; i++) {
- conf_reg = smcreg[i];
-
- /* Enter configuration */
- outb(0x55, conf_reg);
- outb(0x55, conf_reg);
-
- outb(0x0d, conf_reg);
- devid = inb(conf_reg+1);
- IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
+ /* Enter configuration */
+ outb(chip->entr1, cfg_base);
+ outb(chip->entr2, cfg_base);
+
+ outb(chip->cid_index, cfg_base);
+ devid = inb(cfg_base+1);
+ IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
+
+ /* Check for expected device ID; are there others? */
+ if (devid == chip->cid_value) {
+ outb(0x0c, cfg_base);
+ mode = inb(cfg_base+1);
+ mode = (mode & 0x38) >> 3;
- /* Check for expected device ID; are there others? */
- if (devid == 0x29) {
- outb(0x0c, conf_reg);
- mode = inb(conf_reg+1);
- mode = (mode & 0x38) >> 3;
-
- /* Value for IR port */
- if (mode && mode < 4) {
- /* SIR iobase */
- outb(0x25, conf_reg);
- *ioaddr2 = inb(conf_reg+1) << 2;
-
- /* FIR iobase */
- outb(0x2b, conf_reg);
- fir_io = inb(conf_reg+1) << 3;
- if (fir_io) {
- ret = 0;
- *ioaddr = fir_io;
- }
+ /* Value for IR port */
+ if (mode && mode < 4) {
+ /* SIR iobase */
+ outb(0x25, cfg_base);
+ info->sir_base = inb(cfg_base+1) << 2;
+
+ /* FIR iobase */
+ outb(0x2b, cfg_base);
+ fir_io = inb(cfg_base+1) << 3;
+ if (fir_io) {
+ ret = 0;
+ info->fir_base = fir_io;
}
}
+ }
+
+ /* Exit configuration */
+ outb(0xaa, cfg_base);
+
+ return ret;
+}
+
+/*
+ * Function ircc_probe_58 (chip, info)
+ *
+ * Probes for the SMC FDC37N958
+ *
+ */
+static int ircc_probe_58(smc_chip_t *chip, chipio_t *info)
+{
+ int cfg_base = info->cfg_base;
+ __u8 devid;
+ int ret = -ENODEV;
+ int fir_io;
+
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
+
+ /* Enter configuration */
+ outb(chip->entr1, cfg_base);
+ outb(chip->entr2, cfg_base);
+
+ outb(chip->cid_index, cfg_base);
+ devid = inb(cfg_base+1);
+ IRDA_DEBUG(0, __FUNCTION__ "(), devid=0x%02x\n",devid);
+
+ /* Check for expected device ID; are there others? */
+ if (devid == chip->cid_value) {
+ /* Select logical device (UART2) */
+ outb(0x07, cfg_base);
+ outb(0x05, cfg_base + 1);
+
+ /* SIR iobase */
+ outb(0x60, cfg_base);
+ info->sir_base = inb(cfg_base + 1) << 8;
+ outb(0x61, cfg_base);
+ info->sir_base |= inb(cfg_base + 1);
+
+ /* Read FIR base */
+ outb(0x62, cfg_base);
+ fir_io = inb(cfg_base + 1) << 8;
+ outb(0x63, cfg_base);
+ fir_io |= inb(cfg_base + 1);
+ outb(0x2b, cfg_base);
+ if (fir_io) {
+ ret = 0;
+ info->fir_base = fir_io;
+ }
+ }
+
+ /* Exit configuration */
+ outb(0xaa, cfg_base);
- /* Exit configuration */
- outb(0xaa, conf_reg);
- }
return ret;
}
@@ -371,34 +452,32 @@ static int ircc_probe_smc(int *ioaddr, int *ioaddr2)
* Returns non-negative on success.
*
*/
-static int ircc_probe(int iobase, int iobase2)
+static int ircc_probe(int fir_base, int sir_base)
{
- int version = 1;
int low, high, chip, config, dma, irq;
-
- IRDA_DEBUG(0, __FUNCTION__ "\n");
+ int iobase = fir_base;
+ int version = 1;
- /* Power on device */
- outb(inb(iobase+IRCC_MASTER) & ~IRCC_MASTER_POWERDOWN,
- iobase+IRCC_MASTER);
+ IRDA_DEBUG(0, __FUNCTION__ "\n");
register_bank(iobase, 3);
- high = inb(iobase+IRCC_ID_HIGH);
- low = inb(iobase+IRCC_ID_LOW);
- chip = inb(iobase+IRCC_CHIP_ID);
+ high = inb(iobase+IRCC_ID_HIGH);
+ low = inb(iobase+IRCC_ID_LOW);
+ chip = inb(iobase+IRCC_CHIP_ID);
version = inb(iobase+IRCC_VERSION);
- config = inb(iobase+IRCC_INTERFACE);
- irq = config >> 4 & 0x0f;
- dma = config & 0x0f;
+ config = inb(iobase+IRCC_INTERFACE);
+ irq = config >> 4 & 0x0f;
+ dma = config & 0x0f;
if (high == 0x10 && low == 0xb8 && (chip == 0xf1 || chip == 0xf2)) {
- IRDA_DEBUG(0, "SMC IrDA Controller found; IrCC version %d.%d, "
- "port 0x%04x, dma %d, interrupt %d\n",
- chip & 0x0f, version, iobase, dma, irq);
+ MESSAGE("SMC IrDA Controller found; IrCC version %d.%d, "
+ "port 0x%03x, dma=%d, irq=%d\n",
+ chip & 0x0f, version, iobase, dma, irq);
} else
- return -1;
+ return -ENODEV;
- outb(0, iobase+IRCC_MASTER);
+ /* Power on device */
+ outb(0x00, iobase+IRCC_MASTER);
return config;
}
@@ -411,7 +490,7 @@ static int ircc_probe(int iobase, int iobase2)
*/
static void ircc_change_speed(void *priv, __u32 speed)
{
- int iobase, ir_mode, select, fast;
+ int iobase, ir_mode, ctrl, fast;
struct ircc_cb *self = (struct ircc_cb *) priv;
struct net_device *dev;
@@ -420,49 +499,39 @@ static void ircc_change_speed(void *priv, __u32 speed)
ASSERT(self != NULL, return;);
dev = self->netdev;
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Update accounting for new speed */
self->io.speed = speed;
+ outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
+ outb(0x00, iobase+IRCC_MASTER);
+
switch (speed) {
case 9600:
case 19200:
case 38400:
case 57600:
- case 115200:
- IRDA_DEBUG(0, __FUNCTION__
- "(), using irport to change speed to %d\n", speed);
-
- register_bank(iobase, 0);
- outb(0, iobase+IRCC_IER);
- outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
- outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
-
- dev->hard_start_xmit = &irport_hard_xmit;
-
- /* We must give the interrupt back to irport */
- self->irport->interrupt = irport_interrupt;
-
- irport_start(self->irport);
- irport_change_speed(self->irport, speed);
- return;
+ case 115200:
+ ir_mode = IRCC_CFGA_IRDA_SIR_A;
+ ctrl = 0;
+ fast = 0;
break;
case 576000:
ir_mode = IRCC_CFGA_IRDA_HDLC;
- select = 0;
+ ctrl = IRCC_CRC;
fast = 0;
IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
break;
case 1152000:
ir_mode = IRCC_CFGA_IRDA_HDLC;
- select = IRCC_1152;
+ ctrl = IRCC_1152 | IRCC_CRC;
fast = 0;
IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
break;
case 4000000:
ir_mode = IRCC_CFGA_IRDA_4PPM;
- select = 0;
+ ctrl = IRCC_CRC;
fast = IRCC_LCR_A_FAST;
IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
break;
@@ -471,39 +540,55 @@ static void ircc_change_speed(void *priv, __u32 speed)
speed);
return;
}
-
- outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
-
+
register_bank(iobase, 0);
outb(0, iobase+IRCC_IER);
-
- irport_stop(self->irport);
+ outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
+
+ /* Make special FIR init if necessary */
+ if (speed > 115200) {
+ irport_stop(self->irport);
- /* Install FIR transmit handler */
- dev->hard_start_xmit = &ircc_hard_xmit;
+ /* Install FIR transmit handler */
+ dev->hard_start_xmit = &ircc_hard_xmit;
- /* Need to steal the interrupt as well */
- self->irport->interrupt = &ircc_interrupt;
+ /*
+ * Don't know why we have to do this, but FIR interrupts
+ * stops working if we remove it.
+ */
+ /* outb(UART_MCR_OUT2, self->io.sir_base + UART_MCR); */
+ /* Be ready for incomming frames */
+ ircc_dma_receive(self, iobase);
+ } else {
+ /* Install SIR transmit handler */
+ dev->hard_start_xmit = &irport_hard_xmit;
+ irport_start(self->irport);
+
+ IRDA_DEBUG(0, __FUNCTION__
+ "(), using irport to change speed to %d\n", speed);
+ irport_change_speed(self->irport, speed);
+ }
dev->tbusy = 0;
-
+
register_bank(iobase, 1);
outb(((inb(iobase+IRCC_SCE_CFGA) & 0x87) | ir_mode),
iobase+IRCC_SCE_CFGA);
-
- outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_IR),
- iobase+IRCC_SCE_CFGB);
+#ifdef SMC_669 /* Uses pin 88/89 for Rx/Tx */
+ outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_COM),
+ iobase+IRCC_SCE_CFGB);
+#else
+ outb(((inb(iobase+IRCC_SCE_CFGB) & 0x3f) | IRCC_CFGB_MUX_IR),
+ iobase+IRCC_SCE_CFGB);
+#endif
(void) inb(iobase+IRCC_FIFO_THRESHOLD);
outb(64, iobase+IRCC_FIFO_THRESHOLD);
-
+
register_bank(iobase, 4);
-
- outb((inb(iobase+IRCC_CONTROL) & 0x30) | select | IRCC_CRC,
- iobase+IRCC_CONTROL);
-
+ outb((inb(iobase+IRCC_CONTROL) & 0x30) | ctrl, iobase+IRCC_CONTROL);
+
register_bank(iobase, 0);
-
outb(fast, iobase+IRCC_LCR_A);
}
@@ -517,21 +602,20 @@ static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct irport_cb *irport;
struct ircc_cb *self;
+ unsigned long flags;
+ __u32 speed;
int iobase;
int mtt;
- __u32 speed;
irport = (struct irport_cb *) dev->priv;
self = (struct ircc_cb *) irport->priv;
-
ASSERT(self != NULL, return 0;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
- IRDA_DEBUG(2, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies,
- (int) skb->len);
+ spin_lock_irqsave(&self->lock, flags);
- /* Check if we need to change the speed */
+ /* Check if we need to change the speed after this frame */
if ((speed = irda_get_speed(skb)) != self->io.speed)
self->new_speed = speed;
@@ -541,19 +625,28 @@ static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev)
memcpy(self->tx_buff.head, skb->data, skb->len);
- /* Make sure that the length is a multiple of 16 bits */
- if (skb->len & 0x01)
- skb->len++;
-
self->tx_buff.len = skb->len;
self->tx_buff.data = self->tx_buff.head;
mtt = irda_get_mtt(skb);
- if (mtt)
- udelay(mtt);
-
- ircc_dma_xmit(self, iobase);
+ if (mtt) {
+ int bofs;
+
+ /*
+ * Compute who many BOFS (STA or PA's) we need to waste the
+ * min turn time given the speed of the link.
+ */
+ bofs = mtt * (self->io.speed / 1000) / 8000;
+ if (bofs > 4095)
+ bofs = 4095;
+
+ ircc_dma_xmit(self, iobase, bofs);
+ } else {
+ /* Transmit frame */
+ ircc_dma_xmit(self, iobase, 0);
+ }
+ spin_unlock_irqrestore(&self->lock, flags);
dev_kfree_skb(skb);
return 0;
@@ -565,44 +658,49 @@ static int ircc_hard_xmit(struct sk_buff *skb, struct net_device *dev)
* Transmit data using DMA
*
*/
-static void ircc_dma_xmit(struct ircc_cb *self, int iobase)
+static void ircc_dma_xmit(struct ircc_cb *self, int iobase, int bofs)
{
- IRDA_DEBUG(2, __FUNCTION__ "\n");
+ __u8 ctrl;
- ASSERT(self != NULL, return;);
-
- iobase = self->io.iobase;
+ IRDA_DEBUG(2, __FUNCTION__ "\n");
+#if 0
+ /* Disable Rx */
+ register_bank(iobase, 0);
+ outb(0x00, iobase+IRCC_LCR_B);
+#endif
+ register_bank(iobase, 1);
+ outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+ iobase+IRCC_SCE_CFGB);
- setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len,
- DMA_TX_MODE);
-
self->io.direction = IO_XMIT;
- outb(0x08, self->io.iobase2+4);
-
+ /* Set BOF additional count for generating the min turn time */
register_bank(iobase, 4);
- outb((inb(iobase+IRCC_CONTROL) & 0xf0), iobase+IRCC_CONTROL);
-
- outb(2, iobase+IRCC_BOF_COUNT_LO);
- outb(0, iobase+IRCC_BRICKWALL_CNT_LO);
-#if 1
- outb(self->tx_buff.len >> 8, iobase+IRCC_BRICKWALL_TX_CNT_HI);
+ outb(bofs & 0xff, iobase+IRCC_BOF_COUNT_LO);
+ ctrl = inb(iobase+IRCC_CONTROL) & 0xf0;
+ outb(ctrl | ((bofs >> 8) & 0x0f), iobase+IRCC_BOF_COUNT_HI);
+
+ /* Set max Tx frame size */
+ outb(self->tx_buff.len >> 8, iobase+IRCC_TX_SIZE_HI);
outb(self->tx_buff.len & 0xff, iobase+IRCC_TX_SIZE_LO);
-#else
- outb(0, iobase+IRCC_BRICKWALL_TX_CNT_HI);
- outb(0, iobase+IRCC_TX_SIZE_LO);
-#endif
+ /* Setup DMA controller (must be done after enabling chip DMA) */
+ setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len,
+ DMA_TX_MODE);
+
+ outb(UART_MCR_OUT2, self->io.sir_base + UART_MCR);
+ /* Enable burst mode chip Tx DMA */
register_bank(iobase, 1);
- outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE,
- iobase+IRCC_SCE_CFGB);
+ outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
+ IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
+ /* Enable interrupt */
+ outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
register_bank(iobase, 0);
-
outb(IRCC_IER_ACTIVE_FRAME | IRCC_IER_EOM, iobase+IRCC_IER);
- outb(IRCC_LCR_B_SCE_TRANSMIT|IRCC_LCR_B_SIP_ENABLE, iobase+IRCC_LCR_B);
- outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
+ /* Enable transmit */
+ outb(IRCC_LCR_B_SCE_TRANSMIT|IRCC_LCR_B_SIP_ENABLE, iobase+IRCC_LCR_B);
}
/*
@@ -612,39 +710,36 @@ static void ircc_dma_xmit(struct ircc_cb *self, int iobase)
* by the interrupt handler
*
*/
-static void ircc_dma_xmit_complete(struct ircc_cb *self, int underrun)
+static void ircc_dma_xmit_complete(struct ircc_cb *self, int iobase)
{
- int iobase, d;
-
IRDA_DEBUG(2, __FUNCTION__ "\n");
-
- ASSERT(self != NULL, return;);
-
- register_bank(self->io.iobase, 1);
-
- outb(inb(self->io.iobase+IRCC_SCE_CFGB) & IRCC_CFGB_DMA_ENABLE,
- self->io.iobase+IRCC_SCE_CFGB);
-
- d = get_dma_residue(self->io.dma);
-
- IRDA_DEBUG(0, __FUNCTION__
- ": dma residue = %d, len=%d, sent=%d\n",
- d, self->tx_buff.len, self->tx_buff.len - d);
-
- iobase = self->io.iobase;
+#if 0
+ /* Disable Tx */
+ register_bank(iobase, 0);
+ outb(0x00, iobase+IRCC_LCR_B);
+#endif
+ register_bank(self->io.fir_base, 1);
+ outb(inb(self->io.fir_base+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+ self->io.fir_base+IRCC_SCE_CFGB);
/* Check for underrrun! */
- if (underrun) {
+ register_bank(iobase, 0);
+ if (inb(iobase+IRCC_LSR) & IRCC_LSR_UNDERRUN) {
self->irport->stats.tx_errors++;
- self->irport->stats.tx_fifo_errors++;
+ self->irport->stats.tx_fifo_errors++;
+
+ /* Reset error condition */
+ register_bank(iobase, 0);
+ outb(IRCC_MASTER_ERROR_RESET, iobase+IRCC_MASTER);
+ outb(0x00, iobase+IRCC_MASTER);
} else {
self->irport->stats.tx_packets++;
self->irport->stats.tx_bytes += self->tx_buff.len;
}
+ /* Check if it's time to change the speed */
if (self->new_speed) {
- ircc_change_speed(self, self->new_speed);
-
+ ircc_change_speed(self, self->new_speed);
self->new_speed = 0;
}
@@ -662,39 +757,31 @@ static void ircc_dma_xmit_complete(struct ircc_cb *self, int underrun)
* if it starts to receive a frame.
*
*/
-static int ircc_dma_receive(struct ircc_cb *self)
-{
- int iobase;
-
- IRDA_DEBUG(2, __FUNCTION__ "\n");
-
- ASSERT(self != NULL, return -1;);
-
- iobase= self->io.iobase;
+static int ircc_dma_receive(struct ircc_cb *self, int iobase)
+{
+ /* Turn off chip DMA */
+ //register_bank(iobase, 1);
+ //outb(inb(iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+ // iobase+IRCC_SCE_CFGB);
setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize,
- DMA_RX_MODE);
-
- /* driver->media_busy = FALSE; */
+ DMA_RX_MODE);
+ /* Set max Rx frame size */
+ register_bank(iobase, 4);
+ outb((2050 >> 8) & 0x0f, iobase+IRCC_RX_SIZE_HI);
+ outb(2050 & 0xff, iobase+IRCC_RX_SIZE_LO);
+
self->io.direction = IO_RECV;
self->rx_buff.data = self->rx_buff.head;
-#if 0
- self->rx_buff.offset = 0;
-#endif
-
- register_bank(iobase, 4);
- outb(inb(iobase+IRCC_CONTROL) & 0xf0, iobase+IRCC_CONTROL);
- outb(2, iobase+IRCC_BOF_COUNT_LO);
- outb(0, iobase+IRCC_BRICKWALL_CNT_LO);
- outb(0, iobase+IRCC_BRICKWALL_TX_CNT_HI);
- outb(0, iobase+IRCC_TX_SIZE_LO);
- outb(0, iobase+IRCC_RX_SIZE_HI);
- outb(0, iobase+IRCC_RX_SIZE_LO);
+ /* Setup DMA controller */
+
+ /* Enable receiver */
register_bank(iobase, 0);
outb(IRCC_LCR_B_SCE_RECEIVE | IRCC_LCR_B_SIP_ENABLE,
iobase+IRCC_LCR_B);
+ /* Enable burst mode chip Rx DMA */
register_bank(iobase, 1);
outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
@@ -709,45 +796,54 @@ static int ircc_dma_receive(struct ircc_cb *self)
*
*
*/
-static int ircc_dma_receive_complete(struct ircc_cb *self, int iobase)
+static void ircc_dma_receive_complete(struct ircc_cb *self, int iobase)
{
+ unsigned long flags;
struct sk_buff *skb;
int len, msgcnt;
IRDA_DEBUG(2, __FUNCTION__ "\n");
+#if 0
+ /* Disable Rx */
+ register_bank(iobase, 0);
+ outb(0x00, iobase+IRCC_LCR_B);
+#endif
+ register_bank(iobase, 0);
+ msgcnt = inb(iobase+IRCC_LCR_B) & 0x08;
- msgcnt = inb(self->io.iobase+IRCC_LCR_B) & 0x08;
-
- IRDA_DEBUG(0, __FUNCTION__ ": dma count = %d\n",
+ IRDA_DEBUG(2, __FUNCTION__ ": dma count = %d\n",
get_dma_residue(self->io.dma));
- len = self->rx_buff.truesize - get_dma_residue(self->io.dma) - 4;
-
- IRDA_DEBUG(0, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
+ len = self->rx_buff.truesize - get_dma_residue(self->io.dma);
+
+ /* Remove CRC */
+ if (self->io.speed < 4000000)
+ len -= 2;
+ else
+ len -= 4;
+
+ if ((len < 2) && (len > 2050)) {
+ WARNING(__FUNCTION__ "(), bogus len=%d\n", len);
+ return;
+ }
+ IRDA_DEBUG(2, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
skb = dev_alloc_skb(len+1);
if (!skb) {
WARNING(__FUNCTION__ "(), memory squeeze, dropping frame.\n");
- return FALSE;
- }
-
+ return;
+ }
/* Make sure IP header gets aligned */
skb_reserve(skb, 1);
- skb_put(skb, len);
- memcpy(skb->data, self->rx_buff.data, len);
+ memcpy(skb_put(skb, len), self->rx_buff.data, len);
self->irport->stats.rx_packets++;
+ self->irport->stats.rx_bytes += len;
skb->dev = self->netdev;
skb->mac.raw = skb->data;
skb->protocol = htons(ETH_P_IRDA);
netif_rx(skb);
-
- register_bank(self->io.iobase, 1);
- outb(inb(self->io.iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
- self->io.iobase+IRCC_SCE_CFGB);
-
- return TRUE;
}
/*
@@ -758,58 +854,54 @@ static int ircc_dma_receive_complete(struct ircc_cb *self, int iobase)
*/
static void ircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- int iobase, iir;
struct net_device *dev = (struct net_device *) dev_id;
+ struct irport_cb *irport;
struct ircc_cb *self;
+ int iobase, iir;
if (dev == NULL) {
printk(KERN_WARNING "%s: irq %d for unknown device.\n",
driver_name, irq);
return;
}
-
- self = (struct ircc_cb *) dev->priv;
+ irport = (struct irport_cb *) dev->priv;
+ ASSERT(irport != NULL, return;);
+ self = (struct ircc_cb *) irport->priv;
+ ASSERT(self != NULL, return;);
- iobase = self->io.iobase;
+ /* Check if we should use the SIR interrupt handler */
+ if (self->io.speed < 576000) {
+ irport_interrupt(irq, dev_id, regs);
+ return;
+ }
+ iobase = self->io.fir_base;
+ spin_lock(&self->lock);
dev->interrupt = 1;
- outb(0, iobase+IRCC_MASTER);
-
register_bank(iobase, 0);
iir = inb(iobase+IRCC_IIR);
/* Disable interrupts */
outb(0, iobase+IRCC_IER);
- IRDA_DEBUG(0, __FUNCTION__ "(), iir = 0x%02x\n", iir);
+ IRDA_DEBUG(2, __FUNCTION__ "(), iir = 0x%02x\n", iir);
if (iir & IRCC_IIR_EOM) {
- IRDA_DEBUG(0, __FUNCTION__ "(), IRCC_IIR_EOM\n");
-
if (self->io.direction == IO_RECV)
ircc_dma_receive_complete(self, iobase);
else
ircc_dma_xmit_complete(self, iobase);
- ircc_dma_receive(self);
- }
- if (iir & IRCC_IIR_ACTIVE_FRAME) {
- IRDA_DEBUG(0, __FUNCTION__ "(), IRCC_IIR_ACTIVE_FRAME\n");
- self->rx_buff.state = INSIDE_FRAME;
-#if 0
- ircc_dma_receive(self);
-#endif
- }
- if (iir & IRCC_IIR_RAW_MODE) {
- IRDA_DEBUG(0, __FUNCTION__ "(), IIR RAW mode interrupt.\n");
+ ircc_dma_receive(self, iobase);
}
+ /* Enable interrupts again */
register_bank(iobase, 0);
outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, iobase+IRCC_IER);
- outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
dev->interrupt = 0;
+ spin_unlock(&self->lock);
}
/*
@@ -855,7 +947,7 @@ static int ircc_net_open(struct net_device *dev)
ASSERT(self != NULL, return 0;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
irport_net_open(dev); /* irport allocates the irq */
@@ -894,7 +986,7 @@ static int ircc_net_close(struct net_device *dev)
ASSERT(self != NULL, return 0;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
irport_net_close(dev);
@@ -907,6 +999,69 @@ static int ircc_net_close(struct net_device *dev)
return 0;
}
+#ifdef CONFIG_APM
+static void ircc_suspend(struct ircc_cb *self)
+{
+ int i = 10;
+
+ MESSAGE("%s, Suspending\n", driver_name);
+
+ if (self->io.suspended)
+ return;
+
+ ircc_net_close(self->netdev);
+
+ self->io.suspended = 1;
+}
+
+static void ircc_wakeup(struct ircc_cb *self)
+{
+ struct net_device *dev = self->netdev;
+ unsigned long flags;
+
+ if (!self->io.suspended)
+ return;
+
+ save_flags(flags);
+ cli();
+
+ ircc_net_open(self->netdev);
+
+ restore_flags(flags);
+ MESSAGE("%s, Waking up\n", driver_name);
+}
+
+static int ircc_apmproc(apm_event_t event)
+{
+ static int down = 0; /* Filter out double events */
+ int i;
+
+ switch (event) {
+ case APM_SYS_SUSPEND:
+ case APM_USER_SUSPEND:
+ if (!down) {
+ for (i=0; i<4; i++) {
+ if (dev_self[i])
+ ircc_suspend(dev_self[i]);
+ }
+ }
+ down = 1;
+ break;
+ case APM_NORMAL_RESUME:
+ case APM_CRITICAL_RESUME:
+ if (down) {
+ for (i=0; i<4; i++) {
+ if (dev_self[i])
+ ircc_wakeup(dev_self[i]);
+ }
+ }
+ down = 0;
+ break;
+ }
+ return 0;
+}
+#endif /* CONFIG_APM */
+
#ifdef MODULE
MODULE_AUTHOR("Thomas Davis <tadavis@jps.net>");
MODULE_DESCRIPTION("SMC IrCC controller driver");
diff --git a/drivers/net/irda/toshoboe.c b/drivers/net/irda/toshoboe.c
index cbf06af5f..a7b97af37 100644
--- a/drivers/net/irda/toshoboe.c
+++ b/drivers/net/irda/toshoboe.c
@@ -32,37 +32,6 @@
static char *rcsid = "$Id: toshoboe.c,v 1.91 1999/06/29 14:21:06 root Exp $";
-/*
- * $Log: toshoboe.c,v $
- * Revision 1.9 1999/06/29 14:21:06 root
- * *** empty log message ***
- *
- * Revision 1.8 1999/06/29 14:15:08 root
- * *** empty log message ***
- *
- * Revision 1.7 1999/06/29 13:46:42 root
- * *** empty log message ***
- *
- * Revision 1.6 1999/06/29 12:31:03 root
- * *** empty log message ***
- *
- * Revision 1.5 1999/05/12 12:24:39 root
- * *** empty log message ***
- *
- * Revision 1.4 1999/05/12 11:55:08 root
- * *** empty log message ***
- *
- * Revision 1.3 1999/05/09 01:33:12 root
- * *** empty log message ***
- *
- * Revision 1.2 1999/05/09 01:30:38 root
- * *** empty log message ***
- *
- * Revision 1.1 1999/05/09 01:25:04 root
- * Initial revision
- *
- */
-
/* Define this to have only one frame in the XMIT or RECV queue */
/* Toshiba's drivers do this, but it disables back to back tansfers */
/* I think that the chip may have some problems certainly, I have */
@@ -682,7 +651,7 @@ toshoboe_close (struct toshoboe_cb *self)
toshoboe_disablebm (self);
}
- release_region (self->io.iobase, self->io.io_ext);
+ release_region (self->io.sir_base, self->io.sir_ext);
for (i = 0; i < TX_SLOTS; ++i)
@@ -754,17 +723,17 @@ toshoboe_open (struct pci_dev *pci_dev)
self->pdev = pci_dev;
self->base = pci_dev->resource[0].start;
- self->io.iobase = self->base;
+ self->io.sir_base = self->base;
self->io.irq = pci_dev->irq;
- self->io.io_ext = CHIP_IO_EXTENT;
+ self->io.sir_ext = CHIP_IO_EXTENT;
self->io.speed = 9600;
/* Lock the port that we need */
- i = check_region (self->io.iobase, self->io.io_ext);
+ i = check_region (self->io.sir_base, self->io.sir_ext);
if (i < 0)
{
IRDA_DEBUG (0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
- self->io.iobase);
+ self->io.sir_base);
dev_self[i] = NULL;
kfree (self);
@@ -864,13 +833,12 @@ toshoboe_open (struct pci_dev *pci_dev)
}
- request_region (self->io.iobase, self->io.io_ext, driver_name);
+ request_region (self->io.sir_base, self->io.sir_ext, driver_name);
if (!(dev = dev_alloc("irda%d", &err))) {
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
return -ENOMEM;
}
-
dev->priv = (void *) self;
self->netdev = dev;
@@ -1025,7 +993,7 @@ int __init toshoboe_init (void)
if (pci_dev)
{
printk (KERN_WARNING "ToshOboe: Found 701 chip at 0x%0lx irq %d\n",
- pci_dev->resource[0].start,
+ pci_dev->resource[0].start,
pci_dev->irq);
if (!toshoboe_open (pci_dev))
diff --git a/drivers/net/irda/w83977af_ir.c b/drivers/net/irda/w83977af_ir.c
index 1bc2d9fa9..7f781719c 100644
--- a/drivers/net/irda/w83977af_ir.c
+++ b/drivers/net/irda/w83977af_ir.c
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Paul VanderSpek
* Created at: Wed Nov 4 11:46:16 1998
- * Modified at: Wed Jan 5 15:11:21 2000
+ * Modified at: Fri Jan 28 12:10:59 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
@@ -183,21 +183,21 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq,
dev_self[i] = self;
/* Initialize IO */
- self->io.iobase = iobase;
+ self->io.fir_base = iobase;
self->io.irq = irq;
- self->io.io_ext = CHIP_IO_EXTENT;
+ self->io.fir_ext = CHIP_IO_EXTENT;
self->io.dma = dma;
self->io.fifo_size = 32;
/* Lock the port that we need */
- ret = check_region(self->io.iobase, self->io.io_ext);
+ ret = check_region(self->io.fir_base, self->io.fir_ext);
if (ret < 0) {
IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
- self->io.iobase);
+ self->io.fir_base);
/* w83977af_cleanup( self); */
return -ENODEV;
}
- request_region(self->io.iobase, self->io.io_ext, driver_name);
+ request_region(self->io.fir_base, self->io.fir_ext, driver_name);
/* Initialize QoS for this device */
irda_init_max_qos_capabilies(&self->qos);
@@ -243,9 +243,6 @@ int w83977af_open(int i, unsigned int iobase, unsigned int irq,
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
return -ENOMEM;
}
- /* dev_alloc doesn't clear the struct, so lets do a little hack */
- memset(((__u8*)dev)+sizeof(char*),0,sizeof(struct net_device)-sizeof(char*));
-
dev->priv = (void *) self;
self->netdev = dev;
@@ -282,7 +279,7 @@ static int w83977af_close(struct w83977af_ir *self)
IRDA_DEBUG(0, __FUNCTION__ "()\n");
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
#ifdef CONFIG_USE_W977_PNP
/* enter PnP configuration mode */
@@ -301,14 +298,12 @@ static int w83977af_close(struct w83977af_ir *self)
rtnl_lock();
unregister_netdevice(self->netdev);
rtnl_unlock();
- /* Must free the old-style 2.2.x device */
- kfree(self->netdev);
}
/* Release the PORT that this driver is using */
IRDA_DEBUG(0 , __FUNCTION__ "(), Releasing Region %03x\n",
- self->io.iobase);
- release_region(self->io.iobase, self->io.io_ext);
+ self->io.fir_base);
+ release_region(self->io.fir_base, self->io.fir_ext);
if (self->tx_buff.head)
kfree(self->tx_buff.head);
@@ -426,7 +421,7 @@ void w83977af_change_speed(struct w83977af_ir *self, __u32 speed)
int iobase;
__u8 set;
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Update accounting for new speed */
self->io.speed = speed;
@@ -510,7 +505,7 @@ int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev)
self = (struct w83977af_ir *) dev->priv;
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies,
(int) skb->len);
@@ -692,7 +687,7 @@ void w83977af_dma_xmit_complete(struct w83977af_ir *self)
ASSERT(self != NULL, return;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Save current set */
set = inb(iobase+SSR);
@@ -748,7 +743,7 @@ int w83977af_dma_receive(struct w83977af_ir *self)
IRDA_DEBUG(4, __FUNCTION__ "\n");
- iobase= self->io.iobase;
+ iobase= self->io.fir_base;
/* Save current set */
set = inb(iobase+SSR);
@@ -822,12 +817,12 @@ int w83977af_dma_receive_complete(struct w83977af_ir *self)
st_fifo = &self->st_fifo;
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Save current set */
set = inb(iobase+SSR);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Read status FIFO */
switch_bank(iobase, SET5);
@@ -948,7 +943,7 @@ static void w83977af_pio_receive(struct w83977af_ir *self)
ASSERT(self != NULL, return;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Receive all characters in Rx FIFO */
do {
@@ -973,11 +968,11 @@ static __u8 w83977af_sir_interrupt(struct w83977af_ir *self, int isr)
IRDA_DEBUG(4, __FUNCTION__ "(), isr=%#x\n", isr);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Transmit FIFO low on data */
if (isr & ISR_TXTH_I) {
/* Write data left in transmit buffer */
- actual = w83977af_pio_write(self->io.iobase,
+ actual = w83977af_pio_write(self->io.fir_base,
self->tx_buff.data,
self->tx_buff.len,
self->io.fifo_size);
@@ -1042,7 +1037,7 @@ static __u8 w83977af_fir_interrupt(struct w83977af_ir *self, int isr)
__u8 set;
int iobase;
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
set = inb(iobase+SSR);
/* End of frame detected in FIFO */
@@ -1131,7 +1126,7 @@ static void w83977af_interrupt(int irq, void *dev_id, struct pt_regs *regs)
dev->interrupt = 1;
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Save current bank */
set = inb(iobase+SSR);
@@ -1171,7 +1166,7 @@ static int w83977af_is_receiving(struct w83977af_ir *self)
ASSERT(self != NULL, return FALSE;);
if (self->io.speed > 115200) {
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Check if rx FIFO is not empty */
set = inb(iobase+SSR);
@@ -1225,7 +1220,7 @@ static int w83977af_net_open(struct net_device *dev)
ASSERT(self != NULL, return 0;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
if (request_irq(self->io.irq, w83977af_interrupt, 0, dev->name,
(void *) dev)) {
@@ -1290,7 +1285,7 @@ static int w83977af_net_close(struct net_device *dev)
ASSERT(self != NULL, return 0;);
- iobase = self->io.iobase;
+ iobase = self->io.fir_base;
/* Stop device */
dev->tbusy = 1;
diff --git a/drivers/net/mac89x0.c b/drivers/net/mac89x0.c
new file mode 100644
index 000000000..ce43ad752
--- /dev/null
+++ b/drivers/net/mac89x0.c
@@ -0,0 +1,678 @@
+/* cs89x0.c: A Crystal Semiconductor CS89[02]0 driver for linux. */
+/*
+ Written 1996 by Russell Nelson, with reference to skeleton.c
+ written 1993-1994 by Donald Becker.
+
+ This software may be used and distributed according to the terms
+ of the GNU Public License, incorporated herein by reference.
+
+ The author may be reached at nelson@crynwr.com, Crynwr
+ Software, 11 Grant St., Potsdam, NY 13676
+
+ Changelog:
+
+ Mike Cruse : mcruse@cti-ltd.com
+ : Changes for Linux 2.0 compatibility.
+ : Added dev_id parameter in net_interrupt(),
+ : request_irq() and free_irq(). Just NULL for now.
+
+ Mike Cruse : Added MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT macros
+ : in net_open() and net_close() so kerneld would know
+ : that the module is in use and wouldn't eject the
+ : driver prematurely.
+
+ Mike Cruse : Rewrote init_module() and cleanup_module using 8390.c
+ : as an example. Disabled autoprobing in init_module(),
+ : not a good thing to do to other devices while Linux
+ : is running from all accounts.
+
+ Alan Cox : Removed 1.2 support, added 2.1 extra counters.
+
+ David Huggins-Daines <dhd@debian.org>
+
+ Split this off into mac89x0.c, and gutted it of all parts which are
+ not relevant to the existing CS8900 cards on the Macintosh
+ (i.e. basically the Daynaport CS and LC cards). To be precise:
+
+ * Removed all the media-detection stuff, because these cards are
+ TP-only.
+
+ * Lobotomized the ISA interrupt bogosity, because these cards use
+ a hardwired NuBus interrupt and a magic ISAIRQ value in the card.
+
+ * Basically eliminated everything not relevant to getting the
+ cards minimally functioning on the Macintosh.
+
+ I might add that these cards are badly designed even from the Mac
+ standpoint, in that Dayna, in their infinite wisdom, used NuBus slot
+ I/O space and NuBus interrupts for these cards, but neglected to
+ provide anything even remotely resembling a NuBus ROM. Therefore we
+ have to probe for them in a brain-damaged ISA-like fashion.
+*/
+
+static char *version =
+"cs89x0.c:v1.02 11/26/96 Russell Nelson <nelson@crynwr.com>\n";
+
+/* ======================= configure the driver here ======================= */
+
+/* use 0 for production, 1 for verification, >2 for debug */
+#ifndef NET_DEBUG
+#define NET_DEBUG 0
+#endif
+
+/* ======================= end of configuration ======================= */
+
+
+/* Always include 'config.h' first in case the user wants to turn on
+ or override something. */
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#define PRINTK(x) printk x
+
+/*
+ Sources:
+
+ Crynwr packet driver epktisa.
+
+ Crystal Semiconductor data sheets.
+
+*/
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/nubus.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/hwtest.h>
+#include <asm/macints.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include "cs89x0.h"
+
+static unsigned int net_debug = NET_DEBUG;
+
+/* Information that need to be kept for each board. */
+struct net_local {
+ struct net_device_stats stats;
+ int chip_type; /* one of: CS8900, CS8920, CS8920M */
+ char chip_revision; /* revision letter of the chip ('A'...) */
+ int send_cmd; /* the propercommand used to send a packet. */
+ int rx_mode;
+ int curr_rx_cfg;
+ int send_underrun; /* keep track of how many underruns in a row we get */
+ struct sk_buff *skb;
+};
+
+/* Index to functions, as function prototypes. */
+
+extern int mac89x0_probe(struct net_device *dev);
+extern void reset_chip(struct net_device *dev);
+static int net_open(struct net_device *dev);
+static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
+static void net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void set_multicast_list(struct net_device *dev);
+static void net_rx(struct net_device *dev);
+static int net_close(struct net_device *dev);
+static struct net_device_stats *net_get_stats(struct net_device *dev);
+static int set_mac_address(struct net_device *dev, void *addr);
+
+
+/* Example routines you must write ;->. */
+#define tx_done(dev) 1
+
+/* For reading/writing registers ISA-style */
+static int inline
+readreg_io(struct net_device *dev, int portno)
+{
+ writew(swab16(portno), dev->base_addr + ADD_PORT);
+ return swab16(readw(dev->base_addr + DATA_PORT));
+}
+
+static void inline
+writereg_io(struct net_device *dev, int portno, int value)
+{
+ writew(swab16(portno), dev->base_addr + ADD_PORT);
+ writew(swab16(value), dev->base_addr + DATA_PORT);
+}
+
+/* These are for reading/writing registers in shared memory */
+static int inline
+readreg(struct net_device *dev, int portno)
+{
+ return swab16(readw(dev->mem_start + portno));
+}
+
+static void inline
+writereg(struct net_device *dev, int portno, int value)
+{
+ writew(swab16(value), dev->mem_start + portno);
+}
+
+/* Probe for the CS8900 card in slot E. We won't bother looking
+ anywhere else until we have a really good reason to do so. */
+int __init mac89x0_probe(struct net_device *dev)
+{
+ static int once_is_enough = 0;
+ struct net_local *lp;
+ static unsigned version_printed = 0;
+ int i, slot;
+ unsigned rev_type = 0;
+ unsigned long ioaddr;
+ unsigned short sig;
+
+ if (once_is_enough)
+ return ENODEV;
+ once_is_enough = 1;
+
+ /* We might have to parameterize this later */
+ slot = 0xE;
+ /* Get out now if there's a real NuBus card in slot E */
+ if (nubus_find_slot(slot, NULL) != NULL)
+ return ENODEV;
+
+ /* The pseudo-ISA bits always live at offset 0x300 (gee,
+ wonder why...) */
+ ioaddr = (unsigned long)
+ nubus_slot_addr(slot) | (((slot&0xf) << 20) + DEFAULTIOBASE);
+ {
+ unsigned long flags;
+ int card_present;
+
+ save_flags(flags);
+ cli();
+ card_present = hwreg_present((void*) ioaddr+4)
+ && hwreg_present((void*) ioaddr + DATA_PORT);
+ restore_flags(flags);
+
+ if (!card_present)
+ return ENODEV;
+ }
+
+ writew(0, ioaddr + ADD_PORT);
+ sig = readw(ioaddr + DATA_PORT);
+ if (sig != swab16(CHIP_EISA_ID_SIG))
+ return ENODEV;
+
+ /* Initialize the net_device structure. */
+ if (dev->priv == NULL) {
+ dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+ memset(dev->priv, 0, sizeof(struct net_local));
+ }
+ lp = (struct net_local *)dev->priv;
+
+ /* Fill in the 'dev' fields. */
+ dev->base_addr = ioaddr;
+ dev->mem_start = (unsigned long)
+ nubus_slot_addr(slot) | (((slot&0xf) << 20) + MMIOBASE);
+ dev->mem_end = dev->mem_start + 0x1000;
+
+ /* Turn on shared memory */
+ writereg_io(dev, PP_BusCTL, MEMORY_ON);
+
+ /* get the chip type */
+ rev_type = readreg(dev, PRODUCT_ID_ADD);
+ lp->chip_type = rev_type &~ REVISON_BITS;
+ lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
+
+ /* Check the chip type and revision in order to set the correct send command
+ CS8920 revision C and CS8900 revision F can use the faster send. */
+ lp->send_cmd = TX_AFTER_381;
+ if (lp->chip_type == CS8900 && lp->chip_revision >= 'F')
+ lp->send_cmd = TX_NOW;
+ if (lp->chip_type != CS8900 && lp->chip_revision >= 'C')
+ lp->send_cmd = TX_NOW;
+
+ if (net_debug && version_printed++ == 0)
+ printk(version);
+
+ printk(KERN_INFO "%s: cs89%c0%s rev %c found at %#8lx",
+ dev->name,
+ lp->chip_type==CS8900?'0':'2',
+ lp->chip_type==CS8920M?"M":"",
+ lp->chip_revision,
+ dev->base_addr);
+
+ /* Try to read the MAC address */
+ if ((readreg(dev, PP_SelfST) & (EEPROM_PRESENT | EEPROM_OK)) == 0) {
+ printk("\nmac89x0: No EEPROM, giving up now.\n");
+ return ENODEV;
+ } else {
+ for (i = 0; i < ETH_ALEN; i += 2) {
+ /* Big-endian (why??!) */
+ unsigned short s = readreg(dev, PP_IA + i);
+ dev->dev_addr[i] = s >> 8;
+ dev->dev_addr[i+1] = s & 0xff;
+ }
+ }
+
+ dev->irq = SLOT2IRQ(slot);
+ printk(" IRQ %d ADDR ", dev->irq);
+
+ /* print the ethernet address. */
+ for (i = 0; i < ETH_ALEN; i++)
+ printk("%2.2x%s", dev->dev_addr[i],
+ ((i < ETH_ALEN-1) ? ":" : ""));
+
+ dev->open = net_open;
+ dev->stop = net_close;
+ dev->hard_start_xmit = net_send_packet;
+ dev->get_stats = net_get_stats;
+ dev->set_multicast_list = &set_multicast_list;
+ dev->set_mac_address = &set_mac_address;
+
+ /* Fill in the fields of the net_device structure with ethernet values. */
+ ether_setup(dev);
+
+ printk("\n");
+ return 0;
+}
+
+/* This is useful for something, but I don't know what yet. */
+void __init reset_chip(struct net_device *dev)
+{
+ int reset_start_time;
+
+ writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
+
+ /* wait 30 ms */
+ current->state = TASK_INTERRUPTIBLE;
+ schedule_timeout(30*HZ/1000);
+
+ /* Wait until the chip is reset */
+ reset_start_time = jiffies;
+ while( (readreg(dev, PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 2)
+ ;
+}
+
+/* Open/initialize the board. This is called (in the current kernel)
+ sometime after booting when the 'ifconfig' program is run.
+
+ This routine should set everything up anew at each open, even
+ registers that "should" only need to be set once at boot, so that
+ there is non-reboot way to recover if something goes wrong.
+ */
+static int
+net_open(struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+ int i;
+
+ /* Disable the interrupt for now */
+ writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) & ~ENABLE_IRQ);
+
+ /* Grab the interrupt */
+ if (request_irq(dev->irq, &net_interrupt, 0, "cs89x0", dev))
+ return -EAGAIN;
+
+ /* Set up the IRQ - Apparently magic */
+ if (lp->chip_type == CS8900)
+ writereg(dev, PP_CS8900_ISAINT, 0);
+ else
+ writereg(dev, PP_CS8920_ISAINT, 0);
+
+ /* set the Ethernet address */
+ for (i=0; i < ETH_ALEN/2; i++)
+ writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
+
+ /* Turn on both receive and transmit operations */
+ writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);
+
+ /* Receive only error free packets addressed to this card */
+ lp->rx_mode = 0;
+ writereg(dev, PP_RxCTL, DEF_RX_ACCEPT);
+
+ lp->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL;
+
+ writereg(dev, PP_RxCFG, lp->curr_rx_cfg);
+
+ writereg(dev, PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL |
+ TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);
+
+ writereg(dev, PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL |
+ TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL);
+
+ /* now that we've got our act together, enable everything */
+ writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) | ENABLE_IRQ);
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+ MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int
+net_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+ if (dev->tbusy) {
+ /* If we get here, some higher level has decided we are broken.
+ There should really be a "kick me" function call instead. */
+ int tickssofar = jiffies - dev->trans_start;
+ if (tickssofar < 5)
+ return 1;
+ if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
+ tx_done(dev) ? "IRQ conflict" : "network cable problem");
+ /* Try to restart the adaptor. */
+ dev->tbusy=0;
+ dev->trans_start = jiffies;
+ }
+
+ /* Block a timer-based transmit from overlapping. This could better be
+ done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
+ if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
+ printk("%s: Transmitter access conflict.\n", dev->name);
+ else {
+ struct net_local *lp = (struct net_local *)dev->priv;
+ unsigned long flags;
+
+ if (net_debug > 3)
+ printk("%s: sent %d byte packet of type %x\n",
+ dev->name, skb->len,
+ (skb->data[ETH_ALEN+ETH_ALEN] << 8)
+ | skb->data[ETH_ALEN+ETH_ALEN+1]);
+
+ /* keep the upload from being interrupted, since we
+ ask the chip to start transmitting before the
+ whole packet has been completely uploaded. */
+ save_flags(flags);
+ cli();
+
+ /* initiate a transmit sequence */
+ writereg(dev, PP_TxCMD, lp->send_cmd);
+ writereg(dev, PP_TxLength, skb->len);
+
+ /* Test to see if the chip has allocated memory for the packet */
+ if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
+ /* Gasp! It hasn't. But that shouldn't happen since
+ we're waiting for TxOk, so return 1 and requeue this packet. */
+ restore_flags(flags);
+ return 1;
+ }
+
+ /* Write the contents of the packet */
+ memcpy_toio(dev->mem_start + PP_TxFrame, skb->data, skb->len+1);
+
+ restore_flags(flags);
+ dev->trans_start = jiffies;
+ }
+ dev_kfree_skb (skb);
+
+ return 0;
+}
+
+/* The typical workload of the driver:
+ Handle the network interface interrupts. */
+static void net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+ struct net_device *dev = dev_id;
+ struct net_local *lp;
+ int ioaddr, status;
+
+ if (dev == NULL) {
+ printk ("net_interrupt(): irq %d for unknown device.\n", irq);
+ return;
+ }
+ if (dev->interrupt)
+ printk("%s: Re-entering the interrupt handler.\n", dev->name);
+ dev->interrupt = 1;
+
+ ioaddr = dev->base_addr;
+ lp = (struct net_local *)dev->priv;
+
+ /* we MUST read all the events out of the ISQ, otherwise we'll never
+ get interrupted again. As a consequence, we can't have any limit
+ on the number of times we loop in the interrupt handler. The
+ hardware guarantees that eventually we'll run out of events. Of
+ course, if you're on a slow machine, and packets are arriving
+ faster than you can read them off, you're screwed. Hasta la
+ vista, baby! */
+ while ((status = swab16(readw(dev->base_addr + ISQ_PORT)))) {
+ if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status);
+ switch(status & ISQ_EVENT_MASK) {
+ case ISQ_RECEIVER_EVENT:
+ /* Got a packet(s). */
+ net_rx(dev);
+ break;
+ case ISQ_TRANSMITTER_EVENT:
+ lp->stats.tx_packets++;
+ dev->tbusy = 0;
+ mark_bh(NET_BH); /* Inform upper layers. */
+ if ((status & TX_OK) == 0) lp->stats.tx_errors++;
+ if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++;
+ if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++;
+ if (status & TX_LATE_COL) lp->stats.tx_window_errors++;
+ if (status & TX_16_COL) lp->stats.tx_aborted_errors++;
+ break;
+ case ISQ_BUFFER_EVENT:
+ if (status & READY_FOR_TX) {
+ /* we tried to transmit a packet earlier,
+ but inexplicably ran out of buffers.
+ That shouldn't happen since we only ever
+ load one packet. Shrug. Do the right
+ thing anyway. */
+ dev->tbusy = 0;
+ mark_bh(NET_BH); /* Inform upper layers. */
+ }
+ if (status & TX_UNDERRUN) {
+ if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);
+ lp->send_underrun++;
+ if (lp->send_underrun == 3) lp->send_cmd = TX_AFTER_381;
+ else if (lp->send_underrun == 6) lp->send_cmd = TX_AFTER_ALL;
+ }
+ break;
+ case ISQ_RX_MISS_EVENT:
+ lp->stats.rx_missed_errors += (status >>6);
+ break;
+ case ISQ_TX_COL_EVENT:
+ lp->stats.collisions += (status >>6);
+ break;
+ }
+ }
+ dev->interrupt = 0;
+ return;
+}
+
+/* We have a good packet(s), get it/them out of the buffers. */
+static void
+net_rx(struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+ struct sk_buff *skb;
+ int status, length;
+
+ status = readreg(dev, PP_RxStatus);
+ if ((status & RX_OK) == 0) {
+ lp->stats.rx_errors++;
+ if (status & RX_RUNT) lp->stats.rx_length_errors++;
+ if (status & RX_EXTRA_DATA) lp->stats.rx_length_errors++;
+ if (status & RX_CRC_ERROR) if (!(status & (RX_EXTRA_DATA|RX_RUNT)))
+ /* per str 172 */
+ lp->stats.rx_crc_errors++;
+ if (status & RX_DRIBBLE) lp->stats.rx_frame_errors++;
+ return;
+ }
+
+ length = readreg(dev, PP_RxLength);
+ /* Malloc up new buffer. */
+ skb = alloc_skb(length, GFP_ATOMIC);
+ if (skb == NULL) {
+ printk("%s: Memory squeeze, dropping packet.\n", dev->name);
+ lp->stats.rx_dropped++;
+ return;
+ }
+ skb->len = length;
+ skb->dev = dev;
+
+ memcpy_fromio(skb->data, dev->mem_start + PP_RxFrame, length);
+
+ if (net_debug > 3)printk("%s: received %d byte packet of type %x\n",
+ dev->name, length,
+ (skb->data[ETH_ALEN+ETH_ALEN] << 8)
+ | skb->data[ETH_ALEN+ETH_ALEN+1]);
+
+ skb->protocol=eth_type_trans(skb,dev);
+ netif_rx(skb);
+ lp->stats.rx_packets++;
+ lp->stats.rx_bytes+=skb->len;
+ return;
+}
+
+/* The inverse routine to net_open(). */
+static int
+net_close(struct net_device *dev)
+{
+
+ writereg(dev, PP_RxCFG, 0);
+ writereg(dev, PP_TxCFG, 0);
+ writereg(dev, PP_BufCFG, 0);
+ writereg(dev, PP_BusCTL, 0);
+
+ dev->start = 0;
+
+ free_irq(dev->irq, dev);
+
+ /* Update the statistics here. */
+
+ MOD_DEC_USE_COUNT;
+ return 0;
+
+}
+
+/* Get the current statistics. This may be called with the card open or
+ closed. */
+static struct net_device_stats *
+net_get_stats(struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+
+ cli();
+ /* Update the statistics from the device registers. */
+ lp->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
+ lp->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
+ sti();
+
+ return &lp->stats;
+}
+
+static void set_multicast_list(struct net_device *dev)
+{
+ struct net_local *lp = (struct net_local *)dev->priv;
+
+ if(dev->flags&IFF_PROMISC)
+ {
+ lp->rx_mode = RX_ALL_ACCEPT;
+ }
+ else if((dev->flags&IFF_ALLMULTI)||dev->mc_list)
+ {
+ /* The multicast-accept list is initialized to accept-all, and we
+ rely on higher-level filtering for now. */
+ lp->rx_mode = RX_MULTCAST_ACCEPT;
+ }
+ else
+ lp->rx_mode = 0;
+
+ writereg(dev, PP_RxCTL, DEF_RX_ACCEPT | lp->rx_mode);
+
+ /* in promiscuous mode, we accept errored packets, so we have to enable interrupts on them also */
+ writereg(dev, PP_RxCFG, lp->curr_rx_cfg |
+ (lp->rx_mode == RX_ALL_ACCEPT? (RX_CRC_ERROR_ENBL|RX_RUNT_ENBL|RX_EXTRA_DATA_ENBL) : 0));
+}
+
+
+static int set_mac_address(struct net_device *dev, void *addr)
+{
+ int i;
+ if (dev->start)
+ return -EBUSY;
+ printk("%s: Setting MAC address to ", dev->name);
+ for (i = 0; i < 6; i++)
+ printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]);
+ printk(".\n");
+ /* set the Ethernet address */
+ for (i=0; i < ETH_ALEN/2; i++)
+ writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
+
+ return 0;
+}
+
+#ifdef MODULE
+
+static char namespace[16] = "";
+static struct net_device dev_cs89x0 = {
+ NULL,
+ 0, 0, 0, 0,
+ 0, 0,
+ 0, 0, 0, NULL, NULL };
+
+static int debug=0;
+
+MODULE_PARM(debug, "i");
+
+EXPORT_NO_SYMBOLS;
+
+int
+init_module(void)
+{
+ struct net_local *lp;
+
+ net_debug = debug;
+ dev_cs89x0.name = namespace;
+ dev_cs89x0.init = mac89x0_probe;
+ dev_cs89x0.priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+ memset(dev_cs89x0.priv, 0, sizeof(struct net_local));
+ lp = (struct net_local *)dev_cs89x0.priv;
+
+ if (register_netdev(&dev_cs89x0) != 0) {
+ printk(KERN_WARNING "mac89x0.c: No card found\n");
+ return -ENXIO;
+ }
+ return 0;
+}
+
+void
+cleanup_module(void)
+{
+
+#endif
+#ifdef MODULE
+ writew(0, dev_cs89x0.base_addr + ADD_PORT);
+#endif
+#ifdef MODULE
+
+ if (dev_cs89x0.priv != NULL) {
+ /* Free up the private structure, or leak memory :-) */
+ unregister_netdev(&dev_cs89x0);
+ kfree(dev_cs89x0.priv);
+ dev_cs89x0.priv = NULL; /* gets re-allocated by cs89x0_probe1 */
+ }
+}
+#endif /* MODULE */
+
+/*
+ * Local variables:
+ * compile-command: "m68k-linux-gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -c -o mac89x0.o mac89x0.c"
+ * version-control: t
+ * kept-new-versions: 5
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ *
+ */
diff --git a/drivers/net/macmace.c b/drivers/net/macmace.c
new file mode 100644
index 000000000..a7c347a7d
--- /dev/null
+++ b/drivers/net/macmace.c
@@ -0,0 +1,825 @@
+/*
+ * Driver for the Macintosh 68K onboard MACE controller with PSC
+ * driven DMA. The MACE driver code is derived from mace.c. The
+ * Mac68k theory of operation is courtesy of the MacBSD wizards.
+ *
+ * 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.
+ *
+ * Copyright (C) 1996 Paul Mackerras.
+ * Copyright (C) 1998 Alan Cox <alan@redhat.com>
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+#include <asm/irq.h>
+#include <asm/macintosh.h>
+#include <asm/macints.h>
+#include <asm/mac_psc.h>
+#include "mace.h"
+
+#define N_RX_RING 8
+#define N_TX_RING 2
+#define MAX_TX_ACTIVE 1
+#define NCMDS_TX 1 /* dma commands per element in tx ring */
+#define RX_BUFLEN (ETH_FRAME_LEN + 8)
+#define TX_TIMEOUT HZ /* 1 second */
+
+/* Bits in transmit DMA status */
+#define TX_DMA_ERR 0x80
+
+/* The MACE is simply wired down on a Mac68K box */
+
+#define MACE_BASE (void *)(0x50F1C000)
+#define MACE_PROM (void *)(0x50F08001)
+
+struct mace68k_data
+{
+ volatile struct mace *mace;
+ volatile unsigned char *tx_ring;
+ volatile unsigned char *rx_ring;
+ int dma_intr;
+ unsigned char maccc;
+ struct net_device_stats stats;
+ struct timer_list tx_timeout;
+ int timeout_active;
+ int rx_slot, rx_done;
+ int tx_slot, tx_count;
+};
+
+struct mace_frame
+{
+ u16 len;
+ u16 status;
+ u16 rntpc;
+ u16 rcvcc;
+ u32 pad1;
+ u32 pad2;
+ u8 data[1];
+ /* And frame continues.. */
+};
+
+#define PRIV_BYTES sizeof(struct mace68k_data)
+
+extern void psc_debug_dump(void);
+
+static int mace68k_open(struct net_device *dev);
+static int mace68k_close(struct net_device *dev);
+static int mace68k_xmit_start(struct sk_buff *skb, struct net_device *dev);
+static struct net_device_stats *mace68k_stats(struct net_device *dev);
+static void mace68k_set_multicast(struct net_device *dev);
+static void mace68k_reset(struct net_device *dev);
+static int mace68k_set_address(struct net_device *dev, void *addr);
+static void mace68k_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void mace68k_dma_intr(int irq, void *dev_id, struct pt_regs *regs);
+static void mace68k_set_timeout(struct net_device *dev);
+static void mace68k_tx_timeout(unsigned long data);
+
+/*
+ * PSC DMA engine control. As you'd expect on a macintosh its
+ * more like a lawnmower engine supplied without instructions
+ *
+ * The basic theory of operation appears to be as follows.
+ *
+ * There are two sets of receive DMA registers and two sets
+ * of transmit DMA registers. Instead of the more traditional
+ * "ring buffer" approach the Mac68K DMA engine expects you
+ * to be loading one chain while the other runs, and then
+ * to flip register set. Each entry in the chain is a fixed
+ * length.
+ */
+
+/*
+ * Load a receive DMA channel with a base address and ring length
+ */
+
+static void psc_load_rxdma_base(int set, void *base)
+{
+ psc_write_word(PSC_ENETRD_CMD + set, 0x0100);
+ psc_write_long(PSC_ENETRD_ADDR + set, (u32)base);
+ psc_write_long(PSC_ENETRD_LEN + set, N_RX_RING);
+ psc_write_word(PSC_ENETRD_CMD + set, 0x9800);
+}
+
+/*
+ * Reset the receive DMA subsystem
+ */
+
+static void mace68k_rxdma_reset(struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mace = mp->mace;
+ u8 mcc = mace->maccc;
+
+ /*
+ * Turn off receive
+ */
+
+ mcc&=~ENRCV;
+ mace->maccc=mcc;
+
+ /*
+ * Program the DMA
+ */
+
+ psc_write_word(PSC_ENETRD_CTL, 0x8800);
+ psc_load_rxdma_base(0x0, (void *)virt_to_bus(mp->rx_ring));
+ psc_write_word(PSC_ENETRD_CTL, 0x0400);
+
+ psc_write_word(PSC_ENETRD_CTL, 0x8800);
+ psc_load_rxdma_base(0x10, (void *)virt_to_bus(mp->rx_ring));
+ psc_write_word(PSC_ENETRD_CTL, 0x0400);
+
+ mace->maccc=mcc|ENRCV;
+
+#if 0
+ psc_write_word(PSC_ENETRD_CTL, 0x9800);
+ psc_write_word(PSC_ENETRD_CTL+0x10, 0x9800);
+#endif
+}
+
+/*
+ * Reset the transmit DMA subsystem
+ */
+
+static void mace68k_txdma_reset(struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mace = mp->mace;
+ u8 mcc = mace->maccc;
+
+ psc_write_word(PSC_ENETWR_CTL,0x8800);
+
+ mace->maccc = mcc&~ENXMT;
+ psc_write_word(PSC_ENETWR_CTL,0x0400);
+ mace->maccc = mcc;
+}
+
+/*
+ * Disable DMA
+ */
+
+static void mace68k_dma_off(struct net_device *dev)
+{
+ psc_write_word(PSC_ENETRD_CTL, 0x8800);
+ psc_write_word(PSC_ENETRD_CTL, 0x1000);
+ psc_write_word(PSC_ENETRD_CMD, 0x1100);
+ psc_write_word(PSC_ENETRD_CMD+0x10, 0x1100);
+
+ psc_write_word(PSC_ENETWR_CTL, 0x8800);
+ psc_write_word(PSC_ENETWR_CTL, 0x1000);
+ psc_write_word(PSC_ENETWR_CMD, 0x1100);
+ psc_write_word(PSC_ENETWR_CMD+0x10, 0x1100);
+}
+
+/* Bit-reverse one byte of an ethernet hardware address. */
+
+static int bitrev(int b)
+{
+ int d = 0, i;
+
+ for (i = 0; i < 8; ++i, b >>= 1)
+ d = (d << 1) | (b & 1);
+ return d;
+}
+
+/*
+ * Not really much of a probe. The hardware table tells us if this
+ * model of Macintrash has a MACE (AV macintoshes)
+ */
+
+int mace68k_probe(struct net_device *unused)
+{
+ int j;
+ static int once=0;
+ struct mace68k_data *mp;
+ unsigned char *addr;
+ struct net_device *dev;
+ unsigned char checksum = 0;
+
+ /*
+ * There can be only one...
+ */
+
+ if (once) return -ENODEV;
+
+ once = 1;
+
+ if (macintosh_config->ether_type != MAC_ETHER_MACE) return -ENODEV;
+
+ printk("MACE ethernet should be present ");
+
+ dev = init_etherdev(0, PRIV_BYTES);
+ if(dev==NULL)
+ {
+ printk("no free memory.\n");
+ return -ENOMEM;
+ }
+ mp = (struct mace68k_data *) dev->priv;
+ dev->base_addr = (u32)MACE_BASE;
+ mp->mace = (volatile struct mace *) MACE_BASE;
+
+ printk("at 0x%p", mp->mace);
+
+ /*
+ * 16K RX ring and 4K TX ring should do nicely
+ */
+
+ mp->rx_ring=(void *)__get_free_pages(GFP_KERNEL, 2);
+ mp->tx_ring=(void *)__get_free_page(GFP_KERNEL);
+
+ printk(".");
+
+ if(mp->tx_ring==NULL || mp->rx_ring==NULL)
+ {
+ if(mp->tx_ring)
+ free_page((u32)mp->tx_ring);
+// if(mp->rx_ring)
+// __free_pages(mp->rx_ring,2);
+ printk("\nNo memory for ring buffers.\n");
+ return -ENOMEM;
+ }
+
+ /* We want the receive data to be uncached. We dont care about the
+ byte reading order */
+
+ printk(".");
+ kernel_set_cachemode((void *)mp->rx_ring, 16384, IOMAP_NOCACHE_NONSER);
+
+ printk(".");
+ /* The transmit buffer needs to be write through */
+ kernel_set_cachemode((void *)mp->tx_ring, 4096, IOMAP_WRITETHROUGH);
+
+ printk(" Ok\n");
+ dev->irq = IRQ_MAC_MACE;
+ printk(KERN_INFO "%s: MACE at", dev->name);
+
+ /*
+ * The PROM contains 8 bytes which total 0xFF when XOR'd
+ * together. Due to the usual peculiar apple brain damage
+ * the bytes are spaced out in a strange boundary and the
+ * bits are reversed.
+ */
+
+ addr = (void *)MACE_PROM;
+
+ for (j = 0; j < 6; ++j)
+ {
+ u8 v=bitrev(addr[j<<4]);
+ checksum^=v;
+ dev->dev_addr[j] = v;
+ printk("%c%.2x", (j ? ':' : ' '), dev->dev_addr[j]);
+ }
+ for (; j < 8; ++j)
+ {
+ checksum^=bitrev(addr[j<<4]);
+ }
+
+ if(checksum!=0xFF)
+ {
+ printk(" (invalid checksum)\n");
+ return -ENODEV;
+ }
+ printk("\n");
+
+ memset(&mp->stats, 0, sizeof(mp->stats));
+ init_timer(&mp->tx_timeout);
+ mp->timeout_active = 0;
+
+ dev->open = mace68k_open;
+ dev->stop = mace68k_close;
+ dev->hard_start_xmit = mace68k_xmit_start;
+ dev->get_stats = mace68k_stats;
+ dev->set_multicast_list = mace68k_set_multicast;
+ dev->set_mac_address = mace68k_set_address;
+
+ ether_setup(dev);
+
+ mp = (struct mace68k_data *) dev->priv;
+ mp->maccc = ENXMT | ENRCV;
+ mp->dma_intr = IRQ_MAC_MACE_DMA;
+
+ psc_write_word(PSC_ENETWR_CTL, 0x9000);
+ psc_write_word(PSC_ENETRD_CTL, 0x9000);
+ psc_write_word(PSC_ENETWR_CTL, 0x0400);
+ psc_write_word(PSC_ENETRD_CTL, 0x0400);
+
+ /* apple's driver doesn't seem to do this */
+ /* except at driver shutdown time... */
+#if 0
+ mace68k_dma_off(dev);
+#endif
+
+ return 0;
+}
+
+/*
+ * Reset a MACE controller
+ */
+
+static void mace68k_reset(struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
+ int i;
+
+ /* soft-reset the chip */
+ i = 200;
+ while (--i) {
+ mb->biucc = SWRST;
+ if (mb->biucc & SWRST) {
+ udelay(10);
+ continue;
+ }
+ break;
+ }
+ if (!i) {
+ printk(KERN_ERR "mace: cannot reset chip!\n");
+ return;
+ }
+
+ mb->biucc = XMTSP_64;
+ mb->imr = 0xff; /* disable all intrs for now */
+ i = mb->ir;
+ mb->maccc = 0; /* turn off tx, rx */
+ mb->utr = RTRD;
+ mb->fifocc = RCVFW_64;
+ mb->xmtfc = AUTO_PAD_XMIT; /* auto-pad short frames */
+
+ /* load up the hardware address */
+
+ mb->iac = ADDRCHG | PHYADDR;
+
+ while ((mb->iac & ADDRCHG) != 0);
+
+ for (i = 0; i < 6; ++i)
+ mb->padr = dev->dev_addr[i];
+
+ /* clear the multicast filter */
+ mb->iac = ADDRCHG | LOGADDR;
+
+ while ((mb->iac & ADDRCHG) != 0);
+
+ for (i = 0; i < 8; ++i)
+ mb->ladrf = 0;
+
+ mb->plscc = PORTSEL_GPSI + ENPLSIO;
+}
+
+/*
+ * Load the address on a mace controller.
+ */
+
+static int mace68k_set_address(struct net_device *dev, void *addr)
+{
+ unsigned char *p = addr;
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
+ int i;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ /* load up the hardware address */
+ mb->iac = ADDRCHG | PHYADDR;
+ while ((mb->iac & ADDRCHG) != 0);
+
+ for (i = 0; i < 6; ++i)
+ mb->padr = dev->dev_addr[i] = p[i];
+ /* note: setting ADDRCHG clears ENRCV */
+ mb->maccc = mp->maccc;
+ restore_flags(flags);
+ return 0;
+}
+
+/*
+ * Open the Macintosh MACE. Most of this is playing with the DMA
+ * engine. The ethernet chip is quite friendly.
+ */
+
+static int mace68k_open(struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
+
+ /* reset the chip */
+ mace68k_reset(dev);
+
+ mp->rx_done = 0;
+ mace68k_rxdma_reset(dev);
+
+ /*
+ * The interrupt is fixed and comes off the PSC.
+ */
+
+ if (request_irq(dev->irq, mace68k_interrupt, 0, "68K MACE", dev))
+ {
+ printk(KERN_ERR "MACE: can't get irq %d\n", dev->irq);
+ return -EAGAIN;
+ }
+
+ /*
+ * Ditto the DMA interrupt.
+ */
+
+ if (request_irq(IRQ_MAC_MACE_DMA, mace68k_dma_intr, 0, "68K MACE DMA",
+ dev))
+ {
+ printk(KERN_ERR "MACE: can't get irq %d\n", IRQ_MAC_MACE_DMA);
+ return -EAGAIN;
+ }
+
+ /* Activate the Mac DMA engine */
+
+ mp->tx_slot = 0; /* Using register set 0 */
+ mp->tx_count = 1; /* 1 Buffer ready for use */
+ mace68k_txdma_reset(dev);
+
+ /* turn it on! */
+ mb->maccc = mp->maccc;
+ /* enable all interrupts except receive interrupts */
+ mb->imr = RCVINT;
+ return 0;
+}
+
+/*
+ * Shut down the mace and its interrupt channel
+ */
+
+static int mace68k_close(struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
+
+ /* disable rx and tx */
+ mb->maccc = 0;
+ mb->imr = 0xff; /* disable all intrs */
+
+ /* disable rx and tx dma */
+
+ mace68k_dma_off(dev);
+
+ free_irq(dev->irq, dev);
+ free_irq(IRQ_MAC_MACE_DMA, dev);
+ return 0;
+}
+
+static inline void mace68k_set_timeout(struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+ if (mp->timeout_active)
+ del_timer(&mp->tx_timeout);
+ mp->tx_timeout.expires = jiffies + TX_TIMEOUT;
+ mp->tx_timeout.function = mace68k_tx_timeout;
+ mp->tx_timeout.data = (unsigned long) dev;
+ add_timer(&mp->tx_timeout);
+ mp->timeout_active = 1;
+ restore_flags(flags);
+}
+
+/*
+ * Transmit a frame
+ */
+
+static int mace68k_xmit_start(struct sk_buff *skb, struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ /*
+ * This may need atomic types ???
+ */
+
+ printk("mace68k_xmit_start: mp->tx_count = %d, dev->tbusy = %d, mp->tx_ring = %p (%p)\n",
+ mp->tx_count, dev->tbusy,
+ mp->tx_ring, virt_to_bus(mp->tx_ring));
+ psc_debug_dump();
+
+ if(mp->tx_count == 0)
+ {
+ dev->tbusy=1;
+ mace68k_dma_intr(IRQ_MAC_MACE_DMA, dev, NULL);
+ return 1;
+ }
+ mp->tx_count--;
+
+ /*
+ * FIXME:
+ * This is hackish. The memcpy probably isnt needed but
+ * the rules for alignment are not known. Ideally we'd like
+ * to just blast the skb directly to ethernet. We also don't
+ * use the ring properly - just a one frame buffer. That
+ * also requires cache pushes ;).
+ */
+ memcpy((void *)mp->tx_ring, skb, skb->len);
+ psc_write_long(PSC_ENETWR_ADDR + mp->tx_slot, virt_to_bus(mp->tx_ring));
+ psc_write_long(PSC_ENETWR_LEN + mp->tx_slot, skb->len);
+ psc_write_word(PSC_ENETWR_CMD + mp->tx_slot, 0x9800);
+ mp->stats.tx_packets++;
+ mp->stats.tx_bytes+=skb->len;
+ dev_kfree_skb(skb);
+ return 0;
+}
+
+static struct net_device_stats *mace68k_stats(struct net_device *dev)
+{
+ struct mace68k_data *p = (struct mace68k_data *) dev->priv;
+ return &p->stats;
+}
+
+/*
+ * CRC polynomial - used in working out multicast filter bits.
+ */
+#define CRC_POLY 0xedb88320
+
+static void mace68k_set_multicast(struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
+ int i, j, k, b;
+ unsigned long crc;
+
+ mp->maccc &= ~PROM;
+ if (dev->flags & IFF_PROMISC)
+ {
+ mp->maccc |= PROM;
+ } else
+ {
+ unsigned char multicast_filter[8];
+ struct dev_mc_list *dmi = dev->mc_list;
+
+ if (dev->flags & IFF_ALLMULTI)
+ {
+ for (i = 0; i < 8; i++)
+ multicast_filter[i] = 0xff;
+ } else
+ {
+ for (i = 0; i < 8; i++)
+ multicast_filter[i] = 0;
+ for (i = 0; i < dev->mc_count; i++)
+ {
+ crc = ~0;
+ for (j = 0; j < 6; ++j)
+ {
+ b = dmi->dmi_addr[j];
+ for (k = 0; k < 8; ++k)
+ {
+ if ((crc ^ b) & 1)
+ crc = (crc >> 1) ^ CRC_POLY;
+ else
+ crc >>= 1;
+ b >>= 1;
+ }
+ }
+ j = crc >> 26; /* bit number in multicast_filter */
+ multicast_filter[j >> 3] |= 1 << (j & 7);
+ dmi = dmi->next;
+ }
+ }
+#if 0
+ printk("Multicast filter :");
+ for (i = 0; i < 8; i++)
+ printk("%02x ", multicast_filter[i]);
+ printk("\n");
+#endif
+
+ mb->iac = ADDRCHG | LOGADDR;
+ while ((mb->iac & ADDRCHG) != 0);
+
+ for (i = 0; i < 8; ++i)
+ mb->ladrf = multicast_filter[i];
+ }
+ /* reset maccc */
+ mb->maccc = mp->maccc;
+}
+
+/*
+ * Miscellaneous interrupts are handled here. We may end up
+ * having to bash the chip on the head for bad errors
+ */
+
+static void mace68k_handle_misc_intrs(struct mace68k_data *mp, int intr)
+{
+ volatile struct mace *mb = mp->mace;
+ static int mace68k_babbles, mace68k_jabbers;
+
+ if (intr & MPCO)
+ mp->stats.rx_missed_errors += 256;
+ mp->stats.rx_missed_errors += mb->mpc; /* reading clears it */
+ if (intr & RNTPCO)
+ mp->stats.rx_length_errors += 256;
+ mp->stats.rx_length_errors += mb->rntpc; /* reading clears it */
+ if (intr & CERR)
+ ++mp->stats.tx_heartbeat_errors;
+ if (intr & BABBLE)
+ if (mace68k_babbles++ < 4)
+ printk(KERN_DEBUG "mace: babbling transmitter\n");
+ if (intr & JABBER)
+ if (mace68k_jabbers++ < 4)
+ printk(KERN_DEBUG "mace: jabbering transceiver\n");
+}
+
+/*
+ * A transmit error has occured. (We kick the transmit side from
+ * the DMA completion)
+ */
+
+static void mace68k_xmit_error(struct net_device *dev)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
+ u8 xmtfs, xmtrc;
+
+ xmtfs = mb->xmtfs;
+ xmtrc = mb->xmtrc;
+
+ if(xmtfs & XMTSV)
+ {
+ if(xmtfs & UFLO)
+ {
+ printk("%s: DMA underrun.\n", dev->name);
+ mp->stats.tx_errors++;
+ mp->stats.tx_fifo_errors++;
+ mace68k_reset(dev);
+ }
+ if(xmtfs & RTRY)
+ mp->stats.collisions++;
+ }
+ mark_bh(NET_BH);
+}
+
+/*
+ * A receive interrupt occured.
+ */
+
+static void mace68k_recv_interrupt(struct net_device *dev)
+{
+// struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+// volatile struct mace *mb = mp->mace;
+}
+
+/*
+ * Process the chip interrupt
+ */
+
+static void mace68k_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) dev_id;
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ volatile struct mace *mb = mp->mace;
+ u8 ir;
+
+ ir = mb->ir;
+ mace68k_handle_misc_intrs(mp, ir);
+
+ if(ir&XMTINT)
+ mace68k_xmit_error(dev);
+ if(ir&RCVINT)
+ mace68k_recv_interrupt(dev);
+}
+
+static void mace68k_tx_timeout(unsigned long data)
+{
+// struct net_device *dev = (struct net_device *) data;
+// struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+// volatile struct mace *mb = mp->mace;
+}
+
+/*
+ * Handle a newly arrived frame
+ */
+
+static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf)
+{
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+ struct sk_buff *skb;
+
+ if(mf->status&RS_OFLO)
+ {
+ printk("%s: fifo overflow.\n", dev->name);
+ mp->stats.rx_errors++;
+ mp->stats.rx_fifo_errors++;
+ }
+ if(mf->status&(RS_CLSN|RS_FRAMERR|RS_FCSERR))
+ mp->stats.rx_errors++;
+
+ if(mf->status&RS_CLSN)
+ mp->stats.collisions++;
+ if(mf->status&RS_FRAMERR)
+ mp->stats.rx_frame_errors++;
+ if(mf->status&RS_FCSERR)
+ mp->stats.rx_crc_errors++;
+
+ skb = dev_alloc_skb(mf->len+2);
+ if(skb==NULL)
+ {
+ mp->stats.rx_dropped++;
+ return;
+ }
+ skb_reserve(skb,2);
+ memcpy(skb_put(skb, mf->len), mf->data, mf->len);
+
+ skb->protocol = eth_type_trans(skb, dev);
+ netif_rx(skb);
+ mp->stats.rx_packets++;
+ mp->stats.rx_bytes+=mf->len;
+}
+
+/*
+ * The PSC has passed us a DMA interrupt event.
+ */
+
+static void mace68k_dma_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *) dev_id;
+ struct mace68k_data *mp = (struct mace68k_data *) dev->priv;
+
+#if 0
+ u32 psc_status;
+
+ /* It seems this must be allowed to stabilise ?? */
+
+ while((psc_status=psc_read_long(0x0804))!=psc_read_long(0x0804));
+
+ /*
+ * Was this an ethernet event ?
+ */
+
+ if(psc_status&0x60000000)
+ {
+#endif
+ /*
+ * Process the read queue
+ */
+
+ u16 psc_status = psc_read_word(PSC_ENETRD_CTL);
+
+ printk("mace68k_dma_intr: PSC_ENETRD_CTL = %04X\n", (uint) psc_status);
+
+ if (psc_status & 0x2000) {
+ mace68k_rxdma_reset(dev);
+ mp->rx_done = 0;
+ } else if (psc_status & 0x100) {
+ int left;
+
+ psc_write_word(PSC_ENETRD_CMD + mp->rx_slot, 0x1100);
+ left=psc_read_long(PSC_ENETRD_LEN + mp->rx_slot);
+ /* read packets */
+
+ while(mp->rx_done < left)
+ {
+ struct mace_frame *mf=((struct mace_frame *)
+ mp->rx_ring)+mp->rx_done++;
+ mace_dma_rx_frame(dev, mf);
+ }
+
+ if(left == 0) /* Out of DMA room */
+ {
+ psc_load_rxdma_base(mp->rx_slot,
+ (void *)virt_to_phys(mp->rx_ring));
+ mp->rx_slot^=16;
+ mp->rx_done = 0;
+ }
+ else
+ {
+ psc_write_word(PSC_ENETRD_CMD+mp->rx_slot,
+ 0x9800);
+ }
+
+ }
+
+ /*
+ * Process the write queue
+ */
+
+ psc_status = psc_read_word(PSC_ENETWR_CTL);
+ printk("mace68k_dma_intr: PSC_ENETWR_CTL = %04X\n", (uint) psc_status);
+
+ /* apple's driver seems to loop over this until neither */
+ /* condition is true. - jmt */
+
+ if (psc_status & 0x2000) {
+ mace68k_txdma_reset(dev);
+ } else if (psc_status & 0x0100) {
+ psc_write_word(PSC_ENETWR_CMD + mp->tx_slot, 0x0100);
+ mp->tx_slot ^=16;
+ mp->tx_count++;
+ dev->tbusy = 0;
+ mark_bh(NET_BH);
+ }
+#if 0
+ }
+#endif
+}
diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c
index d14ccf3fb..dbb9129d7 100644
--- a/drivers/net/macsonic.c
+++ b/drivers/net/macsonic.c
@@ -42,153 +42,245 @@
#include <asm/pgtable.h>
#include <asm/segment.h>
#include <asm/io.h>
+#include <asm/hwtest.h>
#include <asm/dma.h>
#include <asm/macintosh.h>
+#include <asm/macints.h>
+#include <asm/mac_via.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
-
-#include <config/macsonic.h>
+#include <linux/module.h>
#define SREGS_PAD(n) u16 n;
#include "sonic.h"
-extern int mac_onboard_sonic_probe(void);
+static int sonic_debug = 0;
+static int sonic_version_printed = 0;
-static int setup_debug = -1;
-static int setup_offset = -1;
-static int setup_shift = -1;
+extern int macsonic_probe(struct net_device* dev);
+extern int mac_onboard_sonic_probe(struct net_device* dev);
+extern int mac_nubus_sonic_probe(struct net_device* dev);
-/*
- * This seems to be the right default for the Q800
- */
+/* For onboard SONIC */
+#define ONBOARD_SONIC_REGISTERS 0x50F0A000
+#define ONBOARD_SONIC_PROM_BASE 0x50f08000
-static int reg_offset = 0;
-static int reg_shift = 0;
+enum macsonic_type {
+ MACSONIC_DUODOCK,
+ MACSONIC_APPLE,
+ MACSONIC_APPLE16,
+ MACSONIC_DAYNA,
+ MACSONIC_DAYNALINK
+};
-/*
- * Macros to access SONIC registers
- */
-
-#define MAC_SONIC_REGISTERS 0x50F0A000
-#define MAC_SONIC_PROM_BASE 0x50f08000
-#define MAC_SONIC_IRQ 9 /* Nubus 9 */
+/* For the built-in SONIC in the Duo Dock */
+#define DUODOCK_SONIC_REGISTERS 0xe10000
+#define DUODOCK_SONIC_PROM_BASE 0xe12000
-/*
- * FIXME: We may need to invert the byte ordering. These should
- * be ok for other aspects as they are uncached spaces.
- * The original macros from jazzsonic.c works for me
- * on my LC 630, YMMV /Andreas Ehliar
- */
+/* For Apple-style NuBus SONIC */
+#define APPLE_SONIC_REGISTERS 0
+#define APPLE_SONIC_PROM_BASE 0x40000
-#if 0
-#define SONIC_READ(reg) \
- *((volatile unsigned int *)base_addr+((reg)<<2)+2)
+/* Daynalink LC SONIC */
+#define DAYNALINK_PROM_BASE 0x400000
-#define SONIC_WRITE(reg,val) \
- *((volatile unsigned int *)base_addr+((reg)<<2)+2) = val
-#else
-#define SONIC_READ(reg) \
- *((volatile unsigned int *)base_addr+reg)
+/* For Dayna-style NuBus SONIC (haven't seen one yet) */
+#define DAYNA_SONIC_REGISTERS 0x180000
+/* This is what OpenBSD says. However, this is definitely in NuBus
+ ROM space so we should be able to get it by walking the NuBus
+ resource directories */
+#define DAYNA_SONIC_MAC_ADDR 0xffe004
-#define SONIC_WRITE(reg,val) \
- *((volatile unsigned int *)base_addr+reg) = val
-#endif
+#define SONIC_READ_PROM(addr) readb(prom_addr+addr)
+
+int __init macsonic_probe(struct net_device* dev)
+{
+ int rv;
+
+ /* This will catch fatal stuff like -ENOMEM as well as success */
+ if ((rv = mac_onboard_sonic_probe(dev)) != -ENODEV)
+ return rv;
+ return mac_nubus_sonic_probe(dev);
+}
-#define SONIC_READ_PROM(addr) \
- *((volatile unsigned char *)prom_addr+addr)
/*
- * Function : mac_sonic_setup(char *str, int *ints)
- *
- * Purpose : booter command line initialization of the overrides array,
- *
- * Inputs : str - unused, ints - array of integer parameters with ints[0]
- * equal to the number of ints.
- *
- * Currently unused in the new driver; need to add settable parameters to the
- * detect function.
- *
+ * For reversing the PROM address
*/
-void mac_sonic_setup(char *str, int *ints) {
- /* Format of macsonic parameter is:
- * macsonic=<debug>,<offset>,<shift>
- * Negative values mean don't change.
- */
-
- /* Grmbl... the standard parameter parsing can't handle negative numbers
- * :-( So let's do it ourselves!
- */
+static unsigned char nibbletab[] = {0, 8, 4, 12, 2, 10, 6, 14,
+ 1, 9, 5, 13, 3, 11, 7, 15};
- int i = ints[0]+1, fact;
+static inline void bit_reverse_addr(unsigned char addr[6])
+{
+ int i;
- while( str && (isdigit(*str) || *str == '-') && i <= 10) {
- if (*str == '-')
- fact = -1, ++str;
- else
- fact = 1;
- ints[i++] = simple_strtoul( str, NULL, 0 ) * fact;
- if ((str = strchr( str, ',' )) != NULL)
- ++str;
- }
- ints[0] = i-1;
-
- if (ints[0] < 1) {
- printk( "mac_sonic_setup: no arguments!\n" );
- return;
- }
+ for(i = 0; i < 6; i++)
+ addr[i] = ((nibbletab[addr[i] & 0xf] << 4) |
+ nibbletab[(addr[i] >> 4) &0xf]);
+}
+
+int __init macsonic_init(struct net_device* dev)
+{
+ struct sonic_local* lp = (struct sonic_local *)dev->priv;
+ int i;
- if (ints[0] >= 1) {
- /* 0 <= n <= 2 */
- if (ints[1] >= 0 && ints[1] <= 8)
- setup_debug = ints[1];
- else if (ints[1] > 16)
- printk( "mac_sonic_setup: invalid debug level %d !\n", ints[1] );
+ /* Allocate the entire chunk of memory for the descriptors.
+ Note that this cannot cross a 64K boundary. */
+ for (i = 0; i < 20; i++) {
+ unsigned long desc_base, desc_top;
+ if ((lp->sonic_desc =
+ kmalloc(SIZEOF_SONIC_DESC
+ * SONIC_BUS_SCALE(lp->dma_bitmode), GFP_DMA)) == NULL) {
+ printk(KERN_ERR "%s: couldn't allocate descriptor buffers\n", dev->name);
+ }
+ desc_base = (unsigned long) lp->sonic_desc;
+ desc_top = desc_base + SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode);
+ if ((desc_top & 0xffff) >= (desc_base & 0xffff))
+ break;
+ /* Hmm. try again (FIXME: does this actually work?) */
+ kfree(lp->sonic_desc);
+ printk(KERN_DEBUG
+ "%s: didn't get continguous chunk [%08lx - %08lx], trying again\n",
+ dev->name, desc_base, desc_top);
}
- if (ints[0] >= 2) {
- /* 0 <= n <= 2 */
- if (ints[2] >= 0 && ints[2] <= 16)
- setup_offset = ints[2];
- else if (ints[2] > 16)
- printk( "mac_sonic_setup: invalid offset %d !\n", ints[2] );
+
+ if (lp->sonic_desc == NULL) {
+ printk(KERN_ERR "%s: tried 20 times to allocate descriptor buffers, giving up.\n",
+ dev->name);
+ return -ENOMEM;
+ }
+
+ /* Now set up the pointers to point to the appropriate places */
+ lp->cda = lp->sonic_desc;
+ lp->tda = lp->cda + (SIZEOF_SONIC_CDA * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rda = lp->tda + (SIZEOF_SONIC_TD * SONIC_NUM_TDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+ lp->rra = lp->rda + (SIZEOF_SONIC_RD * SONIC_NUM_RDS
+ * SONIC_BUS_SCALE(lp->dma_bitmode));
+
+ /* FIXME, maybe we should use skbs */
+ if ((lp->rba = (char *)
+ kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_DMA)) == NULL) {
+ printk(KERN_ERR "%s: couldn't allocate receive buffers\n", dev->name);
+ return -ENOMEM;
}
- if (ints[0] >= 3) {
- /* 0 <= n <= 2 */
- if (ints[3] >= 0 && ints[3] <= 16)
- setup_shift = ints[3];
- else if (ints[3] > 16)
- printk( "mac_sonic_setup: invalid shift %d !\n", ints[3] );
+
+ {
+ int rs, ds;
+
+ /* almost always 12*4096, but let's not take chances */
+ rs = ((SONIC_NUM_RRS * SONIC_RBSIZE + 4095) / 4096) * 4096;
+ /* almost always under a page, but let's not take chances */
+ ds = ((SIZEOF_SONIC_DESC + 4095) / 4096) * 4096;
+ kernel_set_cachemode(lp->rba, rs, IOMAP_NOCACHE_SER);
+ kernel_set_cachemode(lp->sonic_desc, ds, IOMAP_NOCACHE_SER);
}
+
+#if 0
+ flush_cache_all();
+#endif
+
+ dev->open = sonic_open;
+ dev->stop = sonic_close;
+ dev->hard_start_xmit = sonic_send_packet;
+ dev->get_stats = sonic_get_stats;
+ dev->set_multicast_list = &sonic_multicast_list;
+
+ /*
+ * clear tally counter
+ */
+ sonic_write(dev, SONIC_CRCT, 0xffff);
+ sonic_write(dev, SONIC_FAET, 0xffff);
+ sonic_write(dev, SONIC_MPT, 0xffff);
+
+ /* Fill in the fields of the device structure with ethernet values. */
+ ether_setup(dev);
+ return 0;
}
-static int sonic_debug = 0;
+int __init mac_onboard_sonic_ethernet_addr(struct net_device* dev)
+{
+ const int prom_addr = ONBOARD_SONIC_PROM_BASE;
+ int i;
-/*
- * For reversing the PROM address
- */
+ /* On NuBus boards we can sometimes look in the ROM resources.
+ No such luck for comm-slot/onboard. */
+ for(i = 0; i < 6; i++)
+ dev->dev_addr[i] = SONIC_READ_PROM(i);
-static unsigned char nibbletab[] = {0, 8, 4, 12, 2, 10, 6, 14,
- 1, 9, 5, 13, 3, 11, 7, 15};
+ /* Most of the time, the address is bit-reversed. The NetBSD
+ source has a rather long and detailed historical account of
+ why this is so. */
+ if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
+ memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+ memcmp(dev->dev_addr, "\x00\x05\x02", 3))
+ bit_reverse_addr(dev->dev_addr);
+ else
+ return 0;
+
+ /* If we still have what seems to be a bogus address, we'll
+ look in the CAM. The top entry should be ours. */
+ /* Danger! This only works if MacOS has already initialized
+ the card... */
+ if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
+ memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+ memcmp(dev->dev_addr, "\x00\x05\x02", 3))
+ {
+ unsigned short val;
+
+ printk(KERN_INFO "macsonic: PROM seems to be wrong, trying CAM entry 15\n");
+
+ sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
+ sonic_write(dev, SONIC_CEP, 15);
+
+ val = sonic_read(dev, SONIC_CAP2);
+ dev->dev_addr[5] = val >> 8;
+ dev->dev_addr[4] = val & 0xff;
+ val = sonic_read(dev, SONIC_CAP1);
+ dev->dev_addr[3] = val >> 8;
+ dev->dev_addr[2] = val & 0xff;
+ val = sonic_read(dev, SONIC_CAP0);
+ dev->dev_addr[1] = val >> 8;
+ dev->dev_addr[0] = val & 0xff;
+
+ printk(KERN_INFO "HW Address from CAM 15: ");
+ for (i = 0; i < 6; i++) {
+ printk("%2.2x", dev->dev_addr[i]);
+ if (i < 5)
+ printk(":");
+ }
+ printk("\n");
+ } else return 0;
-int __init mac_onboard_sonic_probe(void)
+ if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
+ memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
+ memcmp(dev->dev_addr, "\x00\x05\x02", 3))
+ {
+ /*
+ * Still nonsense ... messed up someplace!
+ */
+ printk(KERN_ERR "macsonic: ERROR (INVALID MAC)\n");
+ return -EIO;
+ } else return 0;
+}
+
+int __init mac_onboard_sonic_probe(struct net_device* dev)
{
- struct net_device *dev;
- unsigned int silicon_revision;
- unsigned int val;
- struct sonic_local *lp;
+ /* Bwahahaha */
+ static int once_is_more_than_enough = 0;
+ struct sonic_local* lp;
int i;
- int base_addr = MAC_SONIC_REGISTERS;
- int prom_addr = MAC_SONIC_PROM_BASE;
- static int one=0;
- if (!MACH_IS_MAC)
+ if (once_is_more_than_enough)
return -ENODEV;
+ once_is_more_than_enough = 1;
- if(++one!=1) /* Only one is allowed */
+ if (!MACH_IS_MAC)
return -ENODEV;
printk(KERN_INFO "Checking for internal Macintosh ethernet (SONIC).. ");
@@ -198,288 +290,332 @@ int __init mac_onboard_sonic_probe(void)
printk("none.\n");
return -ENODEV;
}
-
- printk("yes\n");
-
- if (setup_debug >= 0)
- sonic_debug = setup_debug;
- /*
- * This may depend on the actual Mac model ... works for me.
- */
- reg_offset =
- (setup_offset >= 0) ? setup_offset : 0;
- reg_shift =
- (setup_shift >= 0) ? setup_shift : 0;
+ /* Bogus probing, on the models which may or may not have
+ Ethernet (BTW, the Ethernet *is* always at the same
+ address, and nothing else lives there, at least if Apple's
+ documentation is to be believed) */
+ if (macintosh_config->ident == MAC_MODEL_Q630 ||
+ macintosh_config->ident == MAC_MODEL_P588 ||
+ macintosh_config->ident == MAC_MODEL_C610) {
+ unsigned long flags;
+ int card_present;
+
+ save_flags(flags);
+ cli();
+ card_present = hwreg_present((void*)ONBOARD_SONIC_REGISTERS);
+ restore_flags(flags);
+
+ if (!card_present) {
+ printk("none.\n");
+ return -ENODEV;
+ }
+ }
- /*
- * get the Silicon Revision ID. If this is one of the known
- * one assume that we found a SONIC ethernet controller at
- * the expected location.
- * (This is not implemented in the Macintosh driver yet; need
- * to collect values from various sources. Mine is 0x4 ...)
- */
+ printk("yes\n");
- silicon_revision = SONIC_READ(SONIC_SR);
- if (sonic_debug > 1)
- printk("SONIC Silicon Revision = 0x%04x\n", silicon_revision);
+ if (dev) {
+ dev = init_etherdev(dev, sizeof(struct sonic_local));
+ /* methinks this will always be true but better safe than sorry */
+ if (dev->priv == NULL)
+ dev->priv = kmalloc(sizeof(struct sonic_local), GFP_KERNEL);
+ } else {
+ dev = init_etherdev(NULL, sizeof(struct sonic_local));
+ }
- /*
- * We need to allocate sonic_local later on, making sure it's
- * aligned on a 64k boundary. So, no space for dev->priv allocated
- * here ...
- */
- dev = init_etherdev(0,0);
-
- if(dev==NULL)
+ if (dev == NULL)
return -ENOMEM;
- printk("%s: %s found at 0x%08x, ",
- dev->name, "SONIC ethernet", base_addr);
+ lp = (struct sonic_local*) dev->priv;
+ memset(lp, 0, sizeof(struct sonic_local));
+ /* Danger! My arms are flailing wildly! You *must* set this
+ before using sonic_read() */
- if (sonic_debug > 1)
- printk("using offset %d shift %d,", reg_offset, reg_shift);
+ dev->base_addr = ONBOARD_SONIC_REGISTERS;
+ if (via_alt_mapping)
+ dev->irq = IRQ_AUTO_3;
+ else
+ dev->irq = IRQ_NUBUS_9;
- /* Fill in the 'dev' fields. */
- dev->base_addr = base_addr;
- dev->irq = MAC_SONIC_IRQ;
+ if (!sonic_version_printed) {
+ printk(KERN_INFO "%s", version);
+ sonic_version_printed = 1;
+ }
+ printk(KERN_INFO "%s: onboard / comm-slot SONIC at 0x%08lx\n",
+ dev->name, dev->base_addr);
+
+ /* Now do a song and dance routine in an attempt to determine
+ the bus width */
+
+ /* The PowerBook's SONIC is 16 bit always. */
+ if (macintosh_config->ident == MAC_MODEL_PB520) {
+ lp->reg_offset = 0;
+ lp->dma_bitmode = 0;
+ } else {
+ /* Some of the comm-slot cards are 16 bit. But some
+ of them are not. The 32-bit cards use offset 2 and
+ pad with zeroes or sometimes ones (I think...)
+ Therefore, if we try offset 0 and get a silicon
+ revision of 0, we assume 16 bit. */
+ int sr;
+
+ /* Technically this is not necessary since we zeroed
+ it above */
+ lp->reg_offset = 0;
+ lp->dma_bitmode = 0;
+ sr = sonic_read(dev, SONIC_SR);
+ if (sr == 0 || sr == 0xffff) {
+ lp->reg_offset = 2;
+ /* 83932 is 0x0004, 83934 is 0x0100 or 0x0101 */
+ sr = sonic_read(dev, SONIC_SR);
+ lp->dma_bitmode = 1;
+
+ }
+ printk(KERN_INFO
+ "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
+ dev->name, sr, lp->dma_bitmode?32:16, lp->reg_offset);
+ }
- /*
- * Put the sonic into software reset, then
- * retrieve and print the ethernet address.
- */
- SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
+ /* Software reset, then initialize control registers. */
+ sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
+ sonic_write(dev, SONIC_DCR, SONIC_DCR_BMS |
+ SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_EXBUS |
+ (lp->dma_bitmode ? SONIC_DCR_DW : 0));
+ /* This *must* be written back to in order to restore the
+ extended programmable output bits */
+ sonic_write(dev, SONIC_DCR2, 0);
- /*
- * We can't trust MacOS to initialise things it seems.
- */
+ /* Clear *and* disable interrupts to be on the safe side */
+ sonic_write(dev, SONIC_ISR,0x7fff);
+ sonic_write(dev, SONIC_IMR,0);
- if (sonic_debug > 1)
- printk("SONIC_DCR was %X\n",SONIC_READ(SONIC_DCR));
-
- SONIC_WRITE(SONIC_DCR,
- SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_EXBUS | SONIC_DCR_DW);
+ /* Now look for the MAC address. */
+ if (mac_onboard_sonic_ethernet_addr(dev) != 0)
+ return -ENODEV;
- /*
- * We don't want floating spare IRQ's around, not on
- * level triggered systems!
- * Strange though - writing to the ISR only clears currently
- * pending IRQs, but doesn't disable them... Does this make
- * a difference?? Seems it does ...
- */
-#if 1
- SONIC_WRITE(SONIC_ISR,0x7fff);
- SONIC_WRITE(SONIC_IMR,0);
-#else
- SONIC_WRITE(SONIC_ISR, SONIC_IMR_DEFAULT);
-#endif
-
- /* This is how it is done in jazzsonic.c
- * It doesn't seem to work here though.
- */
- if (sonic_debug > 2) {
- printk("Retreiving CAM entry 0. This should be the HW address.\n");
-
- SONIC_WRITE(SONIC_CEP, 0);
- for (i = 0; i < 3; i++)
- {
- val = SONIC_READ(SONIC_CAP0 - i);
- dev->dev_addr[i * 2] = val;
- dev->dev_addr[i * 2 + 1] = val >> 8;
- }
+ printk(KERN_INFO "MAC ");
+ for (i = 0; i < 6; i++) {
+ printk("%2.2x", dev->dev_addr[i]);
+ if (i < 5)
+ printk(":");
+ }
- printk("HW Address from CAM 0: ");
- for (i = 0; i < 6; i++)
- {
- printk("%2.2x", dev->dev_addr[i]);
- if (i < 5)
- printk(":");
- }
- printk("\n");
+ printk(" IRQ %d\n", dev->irq);
- printk("Retreiving CAM entry 15. Another candidate...\n");
+ /* Shared init code */
+ return macsonic_init(dev);
+}
- /*
- * MacOS seems to use CAM entry 15 ...
- */
- SONIC_WRITE(SONIC_CEP, 15);
- for (i = 0; i < 3; i++)
- {
- val = SONIC_READ(SONIC_CAP0 - i);
- dev->dev_addr[i * 2] = val;
- dev->dev_addr[i * 2 + 1] = val >> 8;
- }
+int __init mac_nubus_sonic_ethernet_addr(struct net_device* dev,
+ unsigned long prom_addr,
+ int id)
+{
+ int i;
+ for(i = 0; i < 6; i++)
+ dev->dev_addr[i] = SONIC_READ_PROM(i);
+ /* For now we are going to assume that they're all bit-reversed */
+ bit_reverse_addr(dev->dev_addr);
- printk("HW Address from CAM 15: ");
- for (i = 0; i < 6; i++)
- {
- printk("%2.2x", dev->dev_addr[i]);
- if (i < 5)
- printk(":");
- }
- printk("\n");
- }
+ return 0;
+}
- /*
- * if we can read the PROM, we're safe :-)
- */
- if (sonic_debug > 1)
- printk("Retreiving HW address from the PROM: ");
-
- for(i=0;i<6;i++){
- dev->dev_addr[i]=SONIC_READ_PROM(i);
- }
- if (sonic_debug > 1) {
- for (i = 0; i < 6; i++)
- {
- printk("%2.2x", dev->dev_addr[i]);
- if (i < 5)
- printk(":");
- }
- printk("\n");
+int __init macsonic_ident(struct nubus_dev* ndev)
+{
+ if (ndev->dr_hw == NUBUS_DRHW_ASANTE_LC &&
+ ndev->dr_sw == NUBUS_DRSW_SONIC_LC)
+ return MACSONIC_DAYNALINK;
+ if (ndev->dr_hw == NUBUS_DRHW_SONIC &&
+ ndev->dr_sw == NUBUS_DRSW_APPLE) {
+ /* There has to be a better way to do this... */
+ if (strstr(ndev->board->name, "DuoDock"))
+ return MACSONIC_DUODOCK;
+ else
+ return MACSONIC_APPLE;
}
- /*
- * If its not one of these we have
- * screwed up on this Mac model
- */
+ return -1;
+}
- if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
- memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
- memcmp(dev->dev_addr, "\x00\x05\x02", 3))
+int __init mac_nubus_sonic_probe(struct net_device* dev)
+{
+ static int slots = 0;
+ struct nubus_dev* ndev = NULL;
+ struct sonic_local* lp;
+ unsigned long base_addr, prom_addr;
+ u16 sonic_dcr;
+ int id;
+ int i;
+ int reg_offset, dma_bitmode;
+
+ /* Find the first SONIC that hasn't been initialized already */
+ while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK,
+ NUBUS_TYPE_ETHERNET, ndev)) != NULL)
{
- /*
- * Try bit reversed
- */
- for(i=0;i<6;i++){
- val = SONIC_READ_PROM(i);
- dev->dev_addr[i]=(nibbletab[val & 0xf] << 4) |
- nibbletab[(val >> 4) &0xf];
- }
- if (sonic_debug > 1) {
- printk("Trying bit reversed: ");
- for (i = 0; i < 6; i++)
- {
- printk("%2.2x", dev->dev_addr[i]);
- if (i < 5)
- printk(":");
- }
- printk("\n");
- }
- if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
- memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
- memcmp(dev->dev_addr, "\x00\x05\x02", 3))
- {
- /*
- * Still nonsense ... messed up someplace!
- */
- printk("ERROR (INVALID MAC)\n");
- return -EIO;
- }
+ /* Have we seen it already? */
+ if (slots & (1<<ndev->board->slot))
+ continue;
+ slots |= 1<<ndev->board->slot;
+
+ /* Is it one of ours? */
+ if ((id = macsonic_ident(ndev)) != -1)
+ break;
}
- printk(" MAC ");
- for (i = 0; i < 6; i++)
- {
+ if (ndev == NULL)
+ return -ENODEV;
+
+ switch (id) {
+ case MACSONIC_DUODOCK:
+ base_addr = ndev->board->slot_addr + DUODOCK_SONIC_REGISTERS;
+ prom_addr = ndev->board->slot_addr + DUODOCK_SONIC_PROM_BASE;
+ sonic_dcr = SONIC_DCR_EXBUS | SONIC_DCR_RFT0 | SONIC_DCR_RFT1
+ | SONIC_DCR_TFT0;
+ reg_offset = 2;
+ dma_bitmode = 1;
+ break;
+ case MACSONIC_APPLE:
+ base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
+ prom_addr = ndev->board->slot_addr + APPLE_SONIC_PROM_BASE;
+ sonic_dcr = SONIC_DCR_BMS | SONIC_DCR_RFT1 | SONIC_DCR_TFT0;
+ reg_offset = 0;
+ dma_bitmode = 1;
+ break;
+ case MACSONIC_APPLE16:
+ base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
+ prom_addr = ndev->board->slot_addr + APPLE_SONIC_PROM_BASE;
+ sonic_dcr = SONIC_DCR_EXBUS
+ | SONIC_DCR_RFT1 | SONIC_DCR_TFT0
+ | SONIC_DCR_PO1 | SONIC_DCR_BMS;
+ reg_offset = 0;
+ dma_bitmode = 0;
+ break;
+ case MACSONIC_DAYNALINK:
+ base_addr = ndev->board->slot_addr + APPLE_SONIC_REGISTERS;
+ prom_addr = ndev->board->slot_addr + DAYNALINK_PROM_BASE;
+ sonic_dcr = SONIC_DCR_RFT1 | SONIC_DCR_TFT0
+ | SONIC_DCR_PO1 | SONIC_DCR_BMS;
+ reg_offset = 0;
+ dma_bitmode = 0;
+ break;
+ case MACSONIC_DAYNA:
+ base_addr = ndev->board->slot_addr + DAYNA_SONIC_REGISTERS;
+ prom_addr = ndev->board->slot_addr + DAYNA_SONIC_MAC_ADDR;
+ sonic_dcr = SONIC_DCR_BMS
+ | SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_PO1;
+ reg_offset = 0;
+ dma_bitmode = 0;
+ break;
+ default:
+ printk(KERN_ERR "macsonic: WTF, id is %d\n", id);
+ return -ENODEV;
+ }
+
+ if (dev) {
+ dev = init_etherdev(dev, sizeof(struct sonic_local));
+ /* methinks this will always be true but better safe than sorry */
+ if (dev->priv == NULL)
+ dev->priv = kmalloc(sizeof(struct sonic_local), GFP_KERNEL);
+ } else {
+ dev = init_etherdev(NULL, sizeof(struct sonic_local));
+ }
+
+ if (dev == NULL)
+ return -ENOMEM;
+
+ lp = (struct sonic_local*) dev->priv;
+ memset(lp, 0, sizeof(struct sonic_local));
+ /* Danger! My arms are flailing wildly! You *must* set this
+ before using sonic_read() */
+ lp->reg_offset = reg_offset;
+ lp->dma_bitmode = dma_bitmode;
+ dev->base_addr = base_addr;
+ dev->irq = SLOT2IRQ(ndev->board->slot);
+
+ if (!sonic_version_printed) {
+ printk(KERN_INFO "%s", version);
+ sonic_version_printed = 1;
+ }
+ printk(KERN_INFO "%s: %s in slot %X\n",
+ dev->name, ndev->board->name, ndev->board->slot);
+ printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n",
+ dev->name, sonic_read(dev, SONIC_SR), dma_bitmode?32:16, reg_offset);
+
+ /* Software reset, then initialize control registers. */
+ sonic_write(dev, SONIC_CMD, SONIC_CR_RST);
+ sonic_write(dev, SONIC_DCR, sonic_dcr
+ | (dma_bitmode ? SONIC_DCR_DW : 0));
+
+ /* Clear *and* disable interrupts to be on the safe side */
+ sonic_write(dev, SONIC_ISR,0x7fff);
+ sonic_write(dev, SONIC_IMR,0);
+
+ /* Now look for the MAC address. */
+ if (mac_nubus_sonic_ethernet_addr(dev, prom_addr, id) != 0)
+ return -ENODEV;
+
+ printk(KERN_INFO "MAC ");
+ for (i = 0; i < 6; i++) {
printk("%2.2x", dev->dev_addr[i]);
if (i < 5)
printk(":");
}
+ printk(" IRQ %d\n", dev->irq);
- printk(" IRQ %d\n", MAC_SONIC_IRQ);
-
- /* Initialize the device structure. */
- if (dev->priv == NULL)
- {
- if (sonic_debug > 2) {
- printk("Allocating memory for dev->priv aka lp\n");
- printk("Memory to allocate: %d\n",sizeof(*lp));
- }
- /*
- * the memory be located in the same 64kb segment
- */
- lp = NULL;
- i = 0;
- do
- {
- lp = (struct sonic_local *) kmalloc(sizeof(*lp), GFP_KERNEL);
- if ((unsigned long) lp >> 16 != ((unsigned long) lp + sizeof(*lp)) >> 16)
- {
- /* FIXME, free the memory later */
- kfree(lp);
- lp = NULL;
- }
- }
- while (lp == NULL && i++ < 20);
+ /* Shared init code */
+ return macsonic_init(dev);
+}
- if (lp == NULL)
- {
- printk("%s: couldn't allocate memory for descriptors\n",
- dev->name);
- return -ENOMEM;
- }
+#ifdef MODULE
+static char namespace[16] = "";
+static struct net_device dev_macsonic = {
+ NULL,
+ 0, 0, 0, 0,
+ 0, 0,
+ 0, 0, 0, NULL, NULL };
- if (sonic_debug > 2) {
- printk("Memory allocated after %d tries\n",i);
- }
+MODULE_PARM(sonic_debug, "i");
- /* XXX sonic_local has the TDA, RRA, RDA, don't cache */
- kernel_set_cachemode((u32)lp, 8192, IOMAP_NOCACHE_SER);
- memset(lp, 0, sizeof(struct sonic_local));
+EXPORT_NO_SYMBOLS;
- lp->cda_laddr = (u32)lp;
- if (sonic_debug > 2) {
- printk("memory allocated for sonic at 0x%x\n",lp);
- }
- lp->tda_laddr = lp->cda_laddr + sizeof(lp->cda);
- lp->rra_laddr = lp->tda_laddr + sizeof(lp->tda);
- lp->rda_laddr = lp->rra_laddr + sizeof(lp->rra);
-
- /* allocate receive buffer area */
- /* FIXME, maybe we should use skbs */
- if ((lp->rba = (char *) kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL)
- {
- printk("%s: couldn't allocate receive buffers\n", dev->name);
- return -ENOMEM;
- }
- /* XXX RBA written by Sonic, not cached either */
- kernel_set_cachemode((u32)lp->rba, 6*8192, IOMAP_NOCACHE_SER);
- lp->rba_laddr = (u32)lp->rba;
- flush_cache_all();
- dev->priv = (struct sonic_local *) lp;
- }
- lp = (struct sonic_local *) dev->priv;
- dev->open = sonic_open;
- dev->stop = sonic_close;
- dev->hard_start_xmit = sonic_send_packet;
- dev->get_stats = sonic_get_stats;
- dev->set_multicast_list = &sonic_multicast_list;
+int
+init_module(void)
+{
+ dev_macsonic.name = namespace;
+ dev_macsonic.init = macsonic_probe;
- /* Fill in the fields of the device structure with ethernet values. */
- ether_setup(dev);
+ if (register_netdev(&dev_macsonic) != 0) {
+ printk(KERN_WARNING "macsonic.c: No card found\n");
+ return -ENXIO;
+ }
return 0;
}
-/*
- * SONIC uses a nubus IRQ
- */
+void
+cleanup_module(void)
+{
+ if (dev_macsonic.priv != NULL) {
+ unregister_netdev(&dev_macsonic);
+ kfree(dev_macsonic.priv);
+ dev_macsonic.priv = NULL;
+ }
+}
+#endif /* MODULE */
-#define sonic_request_irq(irq, vec, flags, name, dev) \
- nubus_request_irq(irq, dev, vec)
-#define sonic_free_irq(irq,id) nubus_free_irq(irq)
-/*
- * No funnies on memory mapping.
- */
+#define vdma_alloc(foo, bar) ((u32)foo)
+#define vdma_free(baz)
+#define sonic_chiptomem(bat) (bat)
+#define PHYSADDR(quux) (quux)
-#define sonic_chiptomem(x) (x)
+#include "sonic.c"
/*
- * No VDMA on a Macintosh. So we need request no such facility.
+ * Local variables:
+ * compile-command: "m68k-linux-gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -c -o macsonic.o macsonic.c"
+ * version-control: t
+ * kept-new-versions: 5
+ * c-indent-level: 8
+ * tab-width: 8
+ * End:
+ *
*/
-
-#define vdma_alloc(x,y) ((u32)(x))
-#define vdma_free(x)
-#define PHYSADDR(x) (x)
-
-#include "sonic.c"
diff --git a/drivers/net/sun3lance.c b/drivers/net/sun3lance.c
index 4fff08b7f..006e36f4b 100644
--- a/drivers/net/sun3lance.c
+++ b/drivers/net/sun3lance.c
@@ -21,7 +21,7 @@
*/
-static char *version = "sun3lance.c: v1.0 12/12/96 Sam Creasey (sammy@users.qual.net)\n";
+static char *version = "sun3lance.c: v1.1 11/17/1999 Sam Creasey (sammy@oh.verio.com)\n";
#include <linux/module.h>
@@ -263,6 +263,8 @@ static int __init lance_probe( struct net_device *dev)
int i;
static int did_version = 0;
int found = 0;
+ volatile unsigned short *ioaddr_probe;
+ unsigned short tmp1, tmp2;
/* LANCE_OBIO can be found within the IO pmeg with some effort */
for(ioaddr = 0xfe00000; ioaddr < (0xfe00000 +
@@ -282,6 +284,23 @@ static int __init lance_probe( struct net_device *dev)
if(!found)
return 0;
+ /* test to see if there's really a lance here */
+ /* (CSRO_INIT shouldn't be readable) */
+
+ ioaddr_probe = (volatile unsigned short *)ioaddr;
+ tmp1 = ioaddr_probe[0];
+ tmp2 = ioaddr_probe[1];
+
+ ioaddr_probe[1] = CSR0;
+ ioaddr_probe[0] = CSR0_INIT | CSR0_STOP;
+
+ if(ioaddr_probe[0] != CSR0_STOP) {
+ ioaddr_probe[0] = tmp1;
+ ioaddr_probe[1] = tmp2;
+
+ return 0;
+ }
+
init_etherdev( dev, sizeof(struct lance_private) );
if (!dev->priv)
dev->priv = kmalloc( sizeof(struct lance_private), GFP_KERNEL );
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c
index 10e466a5d..b86c8fdb6 100644
--- a/drivers/net/sunbmac.c
+++ b/drivers/net/sunbmac.c
@@ -1,4 +1,4 @@
-/* $Id: sunbmac.c,v 1.12 1999/12/15 14:07:58 davem Exp $
+/* $Id: sunbmac.c,v 1.13 2000/01/28 13:42:29 jj Exp $
* sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters.
*
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c
index eb76a9fee..65d8315d9 100644
--- a/drivers/net/sunhme.c
+++ b/drivers/net/sunhme.c
@@ -1,4 +1,4 @@
-/* $Id: sunhme.c,v 1.84 1999/12/15 14:08:03 davem Exp $
+/* $Id: sunhme.c,v 1.85 2000/01/28 13:42:27 jj Exp $
* sunhme.c: Sparc HME/BigMac 10/100baseT half/full duplex auto switching,
* auto carrier detecting ethernet driver. Also known as the
* "Happy Meal Ethernet" found on SunSwift SBUS cards.
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c
index 3c499ba38..45b671ae7 100644
--- a/drivers/net/sunlance.c
+++ b/drivers/net/sunlance.c
@@ -1,4 +1,4 @@
-/* $Id: sunlance.c,v 1.92 1999/12/15 14:08:09 davem Exp $
+/* $Id: sunlance.c,v 1.93 2000/01/28 13:42:31 jj Exp $
* lance.c: Linux/Sparc/Lance driver
*
* Written 1995, 1996 by Miguel de Icaza
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c
index 2a170a0a6..53e0c756f 100644
--- a/drivers/net/sunqe.c
+++ b/drivers/net/sunqe.c
@@ -1,4 +1,4 @@
-/* $Id: sunqe.c,v 1.40 1999/12/15 14:08:13 davem Exp $
+/* $Id: sunqe.c,v 1.41 2000/01/28 13:42:30 jj Exp $
* sunqe.c: Sparc QuadEthernet 10baseT SBUS card driver.
* Once again I am out to prove that every ethernet
* controller out there can be most efficiently programmed
diff --git a/drivers/sbus/audio/cs4231.c b/drivers/sbus/audio/cs4231.c
index 442c25206..82e0fc494 100644
--- a/drivers/sbus/audio/cs4231.c
+++ b/drivers/sbus/audio/cs4231.c
@@ -1,4 +1,4 @@
-/* $Id: cs4231.c,v 1.41 1999/12/19 23:28:03 davem Exp $
+/* $Id: cs4231.c,v 1.42 2000/01/28 13:42:48 jj Exp $
* drivers/sbus/audio/cs4231.c
*
* Copyright 1996, 1997, 1998, 1999 Derrick J Brashear (shadow@andrew.cmu.edu)
diff --git a/drivers/sbus/audio/dbri.c b/drivers/sbus/audio/dbri.c
index 0b73b8e0d..a3f083ead 100644
--- a/drivers/sbus/audio/dbri.c
+++ b/drivers/sbus/audio/dbri.c
@@ -1,4 +1,4 @@
-/* $Id: dbri.c,v 1.17 2000/01/20 07:57:47 anton Exp $
+/* $Id: dbri.c,v 1.18 2000/01/28 13:42:50 jj Exp $
* drivers/sbus/audio/dbri.c
*
* Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de)
diff --git a/drivers/sbus/char/zs.c b/drivers/sbus/char/zs.c
index d0ec266c0..77f031cce 100644
--- a/drivers/sbus/char/zs.c
+++ b/drivers/sbus/char/zs.c
@@ -1,4 +1,4 @@
-/* $Id: zs.c,v 1.52 1999/12/15 14:29:20 davem Exp $
+/* $Id: zs.c,v 1.53 2000/01/29 01:29:38 anton Exp $
* zs.c: Zilog serial port driver for the Sparc.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -1928,7 +1928,7 @@ int zs_open(struct tty_struct *tty, struct file * filp)
static void show_serial_version(void)
{
- char *revision = "$Revision: 1.52 $";
+ char *revision = "$Revision: 1.53 $";
char *version, *p;
version = strchr(revision, ' ');
@@ -2076,11 +2076,6 @@ static struct sun_zslayout * __init get_zs(int chip)
static int irq = 0;
int chipid = chip;
-#if CONFIG_AP1000
- printk("No zs chip\n");
- return NULL;
-#endif
-
iospace = 0;
if(chip < 0 || chip >= NUM_SERIAL)
panic("get_zs bogon zs chip number");
@@ -2407,11 +2402,6 @@ int __init zs_init(void)
struct sun_serial *info;
char dummy;
-#if CONFIG_AP1000
- printk("not doing zs_init()\n");
- return 0;
-#endif
-
/* Setup base handler, and timer table. */
init_bh(SERIAL_BH, do_serial_bh);
timer_table[RS_TIMER].fn = zs_timer;
diff --git a/drivers/scsi/esp.c b/drivers/scsi/esp.c
index fd315c1f7..61ce25c36 100644
--- a/drivers/scsi/esp.c
+++ b/drivers/scsi/esp.c
@@ -1,4 +1,4 @@
-/* $Id: esp.c,v 1.89 1999/12/23 01:46:14 davem Exp $
+/* $Id: esp.c,v 1.90 2000/01/28 13:42:56 jj Exp $
* esp.c: EnhancedScsiProcessor Sun SCSI driver code.
*
* Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu)
diff --git a/drivers/scsi/scsi_merge.c b/drivers/scsi/scsi_merge.c
index 290d33d6c..119634641 100644
--- a/drivers/scsi/scsi_merge.c
+++ b/drivers/scsi/scsi_merge.c
@@ -87,7 +87,7 @@ static int dump_stats(struct request *req,
* Dump the information that we have. We know we have an
* inconsistency.
*/
- printk("nr_segments is %lx\n", req->nr_segments);
+ printk("nr_segments is %x\n", req->nr_segments);
printk("counted segments is %x\n", segments);
printk("Flags %d %d\n", use_clustering, dma_host);
for (bh = req->bh; bh->b_reqnext != NULL; bh = bh->b_reqnext)
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 0790a1978..ccbacf127 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -373,6 +373,7 @@ static int sd_init_command(Scsi_Cmnd * SCpnt)
static int sd_open(struct inode *inode, struct file *filp)
{
int target;
+ Scsi_Device * SDev;
target = DEVICE_NR(inode->i_rdev);
SCSI_LOG_HLQUEUE(1, printk("target=%d, max=%d\n", target, sd_template.dev_max));
@@ -412,13 +413,14 @@ static int sd_open(struct inode *inode, struct file *filp)
if ((rscsi_disks[target].write_prot) && (filp->f_mode & 2))
return -EROFS;
}
+ SDev = rscsi_disks[target].device;
/*
* It is possible that the disk changing stuff resulted in the device
* being taken offline. If this is the case, report this to the user,
* and don't pretend that
* the open actually succeeded.
*/
- if (!rscsi_disks[target].device->online) {
+ if (!SDev->online) {
return -ENXIO;
}
/*
@@ -428,13 +430,14 @@ static int sd_open(struct inode *inode, struct file *filp)
if (sd_sizes[SD_PARTITION(inode->i_rdev)] == 0)
return -ENXIO;
- if (rscsi_disks[target].device->removable)
- if (!rscsi_disks[target].device->access_count)
- sd_ioctl(inode, NULL, SCSI_IOCTL_DOORLOCK, 0);
+ if (SDev->removable)
+ if (!SDev->access_count)
+ if (scsi_block_when_processing_errors(SDev))
+ scsi_ioctl(SDev, SCSI_IOCTL_DOORLOCK, NULL);
- rscsi_disks[target].device->access_count++;
- if (rscsi_disks[target].device->host->hostt->module)
- __MOD_INC_USE_COUNT(rscsi_disks[target].device->host->hostt->module);
+ SDev->access_count++;
+ if (SDev->host->hostt->module)
+ __MOD_INC_USE_COUNT(SDev->host->hostt->module);
if (sd_template.module)
__MOD_INC_USE_COUNT(sd_template.module);
return 0;
@@ -443,17 +446,20 @@ static int sd_open(struct inode *inode, struct file *filp)
static int sd_release(struct inode *inode, struct file *file)
{
int target;
+ Scsi_Device * SDev;
target = DEVICE_NR(inode->i_rdev);
+ SDev = rscsi_disks[target].device;
- rscsi_disks[target].device->access_count--;
+ SDev->access_count--;
- if (rscsi_disks[target].device->removable) {
- if (!rscsi_disks[target].device->access_count)
- sd_ioctl(inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0);
+ if (SDev->removable) {
+ if (!SDev->access_count)
+ if (scsi_block_when_processing_errors(SDev))
+ scsi_ioctl(SDev, SCSI_IOCTL_DOORUNLOCK, NULL);
}
- if (rscsi_disks[target].device->host->hostt->module)
- __MOD_DEC_USE_COUNT(rscsi_disks[target].device->host->hostt->module);
+ if (SDev->host->hostt->module)
+ __MOD_DEC_USE_COUNT(SDev->host->hostt->module);
if (sd_template.module)
__MOD_DEC_USE_COUNT(sd_template.module);
return 0;
@@ -580,17 +586,17 @@ static int check_scsidisk_media_change(kdev_t full_dev)
{
int retval;
int target;
- struct inode inode;
int flag = 0;
+ Scsi_Device * SDev;
target = DEVICE_NR(full_dev);
+ SDev = rscsi_disks[target].device;
- if (target >= sd_template.dev_max ||
- !rscsi_disks[target].device) {
+ if (target >= sd_template.dev_max || !SDev) {
printk("SCSI disk request error: invalid device.\n");
return 0;
}
- if (!rscsi_disks[target].device->removable)
+ if (!SDev->removable)
return 0;
/*
@@ -599,13 +605,12 @@ static int check_scsidisk_media_change(kdev_t full_dev)
* can deal with it then. It is only because of unrecoverable errors
* that we would ever take a device offline in the first place.
*/
- if (rscsi_disks[target].device->online == FALSE) {
+ if (SDev->online == FALSE) {
rscsi_disks[target].ready = 0;
- rscsi_disks[target].device->changed = 1;
+ SDev->changed = 1;
return 1; /* This will force a flush, if called from
* check_disk_change */
}
- inode.i_rdev = full_dev; /* This is all we really need here */
/* Using Start/Stop enables differentiation between drive with
* no cartridge loaded - NOT READY, drive with changed cartridge -
@@ -613,7 +618,9 @@ static int check_scsidisk_media_change(kdev_t full_dev)
* This also handles drives that auto spin down. eg iomega jaz 1GB
* as this will spin up the drive.
*/
- retval = sd_ioctl(&inode, NULL, SCSI_IOCTL_START_UNIT, 0);
+ retval = -ENODEV;
+ if (scsi_block_when_processing_errors(SDev))
+ retval = scsi_ioctl(SDev, SCSI_IOCTL_START_UNIT, NULL);
if (retval) { /* Unable to test, unit probably not ready.
* This usually means there is no disc in the
@@ -622,7 +629,7 @@ static int check_scsidisk_media_change(kdev_t full_dev)
* again. */
rscsi_disks[target].ready = 0;
- rscsi_disks[target].device->changed = 1;
+ SDev->changed = 1;
return 1; /* This will force a flush, if called from
* check_disk_change */
}
@@ -634,9 +641,9 @@ static int check_scsidisk_media_change(kdev_t full_dev)
rscsi_disks[target].ready = 1; /* FLOPTICAL */
- retval = rscsi_disks[target].device->changed;
+ retval = SDev->changed;
if (!flag)
- rscsi_disks[target].device->changed = 0;
+ SDev->changed = 0;
return retval;
}
diff --git a/drivers/sound/Config.in b/drivers/sound/Config.in
index 4859685c6..c218ca69d 100644
--- a/drivers/sound/Config.in
+++ b/drivers/sound/Config.in
@@ -26,7 +26,7 @@ if [ "$CONFIG_VISWS" = "y" ]; then
dep_tristate ' SGI Visual Workstation Sound' CONFIG_SOUND_VWSND $CONFIG_SOUND
fi
-dep_tristate ' Trident 4DWave-DX/NX' CONFIG_SOUND_TRIDENT $CONFIG_SOUND
+dep_tristate ' Trident 4DWave DX/NX or SiS 7018 PCI Audio Core' CONFIG_SOUND_TRIDENT $CONFIG_SOUND
dep_tristate ' Support for Turtle Beach MultiSound Classic, Tahiti, Monterey' CONFIG_SOUND_MSNDCLAS $CONFIG_SOUND
if [ "$CONFIG_SOUND_MSNDCLAS" = "y" -o "$CONFIG_SOUND_MSNDCLAS" = "m" ]; then
diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile
index 50ba920b9..17f404531 100644
--- a/drivers/sound/Makefile
+++ b/drivers/sound/Makefile
@@ -25,7 +25,7 @@ endif
export-objs := ad1848.o audio_syms.o midi_syms.o mpu401.o \
msnd.o opl3.o sb_card.o sequencer_syms.o \
sound_core.o sound_syms.o uart401.o ad1816.o \
- nm256_audio.o ac97.o
+ nm256_audio.o ac97.o ac97_codec.o
@@ -84,7 +84,7 @@ obj-$(CONFIG_SOUND_ES1370) += es1370.o
obj-$(CONFIG_SOUND_ES1371) += es1371.o
obj-$(CONFIG_SOUND_ESSSOLO1) += esssolo1.o
obj-$(CONFIG_SOUND_MAESTRO) += maestro.o
-obj-$(CONFIG_SOUND_TRIDENT) += trident.o
+obj-$(CONFIG_SOUND_TRIDENT) += trident.o ac97_codec.o
# Declare multi-part drivers.
diff --git a/drivers/sound/ac97_codec.c b/drivers/sound/ac97_codec.c
new file mode 100644
index 000000000..a1177c6df
--- /dev/null
+++ b/drivers/sound/ac97_codec.c
@@ -0,0 +1,440 @@
+/*
+ * ac97_codec.c: Generic AC97 mixer module
+ *
+ * Derived from ac97 mixer in maestro and trident driver.
+ *
+ * Copyright 2000 Silicon Integrated System Corporation
+ *
+ * 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.
+ *
+ * History
+ * Jan 14 2000 Ollie Lho <ollie@sis.com.tw>
+ * Isloated from trident.c to support multiple ac97 codec
+ */
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/kernel.h>
+
+#include "ac97_codec.h"
+
+static int ac97_read_mixer(struct ac97_codec *codec, int oss_channel);
+static void ac97_write_mixer(struct ac97_codec *codec, int oss_channel,
+ unsigned int left, unsigned int right);
+static void ac97_set_mixer(struct ac97_codec *codec, unsigned int oss_mixer, unsigned int val );
+static int ac97_recmask_io(struct ac97_codec *codec, int rw, int mask);
+static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned long arg);
+
+static struct {
+ unsigned int id;
+ char *name;
+ int (*init) (struct ac97_codec *codec);
+} snd_ac97_codec_ids[] = {
+ {0x414B4D00, "Asahi Kasei AK4540" , NULL},
+ {0x41445340, "Analog Devices AD1881" , NULL},
+ {0x43525900, "Cirrus Logic CS4297" , NULL},
+ {0x43525913, "Cirrus Logic CS4297A" , NULL},
+ {0x43525931, "Cirrus Logic CS4299" , NULL},
+ {0x4e534331, "National Semiconductor LM4549", NULL},
+ {0x83847600, "SigmaTel STAC????" , NULL},
+ {0x83847604, "SigmaTel STAC9701/3/4/5", NULL},
+ {0x83847605, "SigmaTel STAC9704" , NULL},
+ {0x83847608, "SigmaTel STAC9708" , NULL},
+ {0x83847609, "SigmaTel STAC9721/23" , NULL},
+ {0x00000000, NULL, NULL}
+};
+
+
+/* this table has default mixer values for all OSS mixers. */
+static struct mixer_defaults {
+ int mixer;
+ unsigned int value;
+} mixer_defaults[SOUND_MIXER_NRDEVICES] = {
+ /* all values 0 -> 100 in bytes */
+ {SOUND_MIXER_VOLUME, 0x3232},
+ {SOUND_MIXER_BASS, 0x3232},
+ {SOUND_MIXER_TREBLE, 0x3232},
+ {SOUND_MIXER_PCM, 0x3232},
+ {SOUND_MIXER_SPEAKER, 0x3232},
+ {SOUND_MIXER_LINE, 0x3232},
+ {SOUND_MIXER_MIC, 0x3232},
+ {SOUND_MIXER_CD, 0x3232},
+ {SOUND_MIXER_ALTPCM, 0x3232},
+ {SOUND_MIXER_IGAIN, 0x3232},
+ {SOUND_MIXER_LINE1, 0x3232},
+ {SOUND_MIXER_PHONEIN, 0x3232},
+ {SOUND_MIXER_PHONEOUT, 0x3232},
+ {SOUND_MIXER_VIDEO, 0x3232},
+ {-1,0}
+};
+
+/* table to scale scale from OSS mixer value to AC97 mixer register value */
+static struct ac97_mixer_hw {
+ unsigned char offset;
+ int scale;
+} ac97_hw[SOUND_MIXER_NRDEVICES]= {
+ [SOUND_MIXER_VOLUME] = {AC97_MASTER_VOL_STEREO,63},
+ [SOUND_MIXER_BASS] = {AC97_MASTER_TONE, 15},
+ [SOUND_MIXER_TREBLE] = {AC97_MASTER_TONE, 15},
+ [SOUND_MIXER_PCM] = {AC97_PCMOUT_VOL, 31},
+ [SOUND_MIXER_SPEAKER] = {AC97_PCBEEP_VOL, 15},
+ [SOUND_MIXER_LINE] = {AC97_LINEIN_VOL, 31},
+ [SOUND_MIXER_MIC] = {AC97_MIC_VOL, 31},
+ [SOUND_MIXER_CD] = {AC97_CD_VOL, 31},
+ [SOUND_MIXER_ALTPCM] = {AC97_HEADPHONE_VOL, 63},
+ [SOUND_MIXER_IGAIN] = {AC97_RECORD_GAIN, 31},
+ [SOUND_MIXER_LINE1] = {AC97_AUX_VOL, 31},
+ [SOUND_MIXER_PHONEIN] = {AC97_PHONE_VOL, 15},
+ [SOUND_MIXER_PHONEOUT] = {AC97_MASTER_VOL_MONO, 63},
+ [SOUND_MIXER_VIDEO] = {AC97_VIDEO_VOL, 31},
+};
+
+/* the following tables allow us to go from OSS <-> ac97 quickly. */
+enum ac97_recsettings {
+ AC97_REC_MIC=0,
+ AC97_REC_CD,
+ AC97_REC_VIDEO,
+ AC97_REC_AUX,
+ AC97_REC_LINE,
+ AC97_REC_STEREO, /* combination of all enabled outputs.. */
+ AC97_REC_MONO, /*.. or the mono equivalent */
+ AC97_REC_PHONE
+};
+
+static unsigned int ac97_rm2oss[] = {
+ [AC97_REC_MIC] = SOUND_MIXER_MIC,
+ [AC97_REC_CD] = SOUND_MIXER_CD,
+ [AC97_REC_VIDEO] = SOUND_MIXER_VIDEO,
+ [AC97_REC_AUX] = SOUND_MIXER_LINE1,
+ [AC97_REC_LINE] = SOUND_MIXER_LINE,
+ [AC97_REC_PHONE] = SOUND_MIXER_PHONEIN
+};
+
+/* indexed by bit position */
+static unsigned int ac97_oss_rm[] = {
+ [SOUND_MIXER_MIC] = AC97_REC_MIC,
+ [SOUND_MIXER_CD] = AC97_REC_CD,
+ [SOUND_MIXER_VIDEO] = AC97_REC_VIDEO,
+ [SOUND_MIXER_LINE1] = AC97_REC_AUX,
+ [SOUND_MIXER_LINE] = AC97_REC_LINE,
+ [SOUND_MIXER_PHONEIN] = AC97_REC_PHONE
+};
+
+/* reads the given OSS mixer from the ac97 the caller must have insured that the ac97 knows
+ about that given mixer, and should be holding a spinlock for the card */
+static int ac97_read_mixer(struct ac97_codec *codec, int oss_channel)
+{
+ u16 val;
+ int ret = 0;
+ struct ac97_mixer_hw *mh = &ac97_hw[oss_channel];
+
+ val = codec->codec_read(codec , mh->offset);
+
+ if (AC97_STEREO_MASK & (1 << oss_channel)) {
+ /* nice stereo mixers .. */
+ int left,right;
+
+ left = (val >> 8) & 0x7f;
+ right = val & 0x7f;
+
+ if (oss_channel == SOUND_MIXER_IGAIN) {
+ right = (right * 100) / mh->scale;
+ left = (left * 100) / mh->scale;
+ } else {
+ right = 100 - ((right * 100) / mh->scale);
+ left = 100 - ((left * 100) / mh->scale);
+ }
+
+ ret = left | (right << 8);
+ } else if (oss_channel == SOUND_MIXER_SPEAKER) {
+ ret = 100 - ((((val & 0x1e)>>1) * 100) / mh->scale);
+ } else if (oss_channel == SOUND_MIXER_MIC) {
+ ret = 100 - (((val & 0x1f) * 100) / mh->scale);
+ /* the low bit is optional in the tone sliders and masking
+ it lets us avoid the 0xf 'bypass'.. */
+ } else if (oss_channel == SOUND_MIXER_BASS) {
+ ret = 100 - ((((val >> 8) & 0xe) * 100) / mh->scale);
+ } else if (oss_channel == SOUND_MIXER_TREBLE) {
+ ret = 100 - (((val & 0xe) * 100) / mh->scale);
+ }
+
+#ifdef DEBUG
+ printk("ac97_codec: read OSS mixer %2d (ac97 register 0x%02x), "
+ "0x%04x -> 0x%04x\n", oss_channel, mh->offset, val, ret);
+#endif
+
+ return ret;
+}
+
+/* write the OSS encoded volume to the given OSS encoded mixer, again caller's job to
+ make sure all is well in arg land, call with spinlock held */
+static void ac97_write_mixer(struct ac97_codec *codec, int oss_channel,
+ unsigned int left, unsigned int right)
+{
+ u16 val = 0;
+ struct ac97_mixer_hw *mh = &ac97_hw[oss_channel];
+
+#ifdef DEBUG
+ printk("ac97_codec: wrote OSS mixer %2d (%s ac97 register 0x%02x), "
+ "left vol:%2d, right vol:%2d:",
+ oss_channel, codec->id ? "Secondary" : "Primary",
+ mh->offset, left, right);
+#endif
+
+ if (AC97_STEREO_MASK & (1 << oss_channel)) {
+ /* stereo mixers */
+ if (oss_channel == SOUND_MIXER_IGAIN) {
+ right = (right * mh->scale) / 100;
+ left = (left * mh->scale) / 100;
+ } else {
+ right = ((100 - right) * mh->scale) / 100;
+ left = ((100 - left) * mh->scale) / 100;
+ }
+ val = (left << 8) | right;
+ } else if (oss_channel == SOUND_MIXER_SPEAKER) {
+ val = (((100 - left) * mh->scale) / 100) << 1;
+ } else if (oss_channel == SOUND_MIXER_MIC) {
+ val = codec->codec_read(codec , mh->offset) & ~0x801f;
+ val |= (((100 - left) * mh->scale) / 100);
+ /* the low bit is optional in the tone sliders and masking
+ it lets us avoid the 0xf 'bypass'.. */
+ } else if (oss_channel == SOUND_MIXER_BASS) {
+ val = codec->codec_read(codec , mh->offset) & ~0x0f00;
+ val |= ((((100 - left) * mh->scale) / 100) << 8) & 0x0e00;
+ } else if (oss_channel == SOUND_MIXER_TREBLE) {
+ val = codec->codec_read(codec , mh->offset) & ~0x000f;
+ val |= (((100 - left) * mh->scale) / 100) & 0x000e;
+ }
+
+#ifdef DEBUG
+ printk(" 0x%04x", val);
+#endif
+ codec->codec_write(codec, mh->offset, val);
+
+#ifdef DEBUG
+ val = codec->codec_read(codec, mh->offset);
+ printk(" -> 0x%04x\n", val);
+#endif
+}
+
+/* a thin wrapper for write_mixer */
+static void ac97_set_mixer(struct ac97_codec *codec, unsigned int oss_mixer, unsigned int val )
+{
+ unsigned int left,right;
+
+ /* cleanse input a little */
+ right = ((val >> 8) & 0xff) ;
+ left = (val & 0xff) ;
+
+ if (right > 100) right = 100;
+ if (left > 100) left = 100;
+
+ codec->mixer_state[oss_mixer] = (right << 8) | left;
+ codec->write_mixer(codec, oss_mixer, left, right);
+}
+
+/* read or write the recmask, the ac97 can really have left and right recording
+ inputs independantly set, but OSS doesn't seem to want us to express that to
+ the user. the caller guarantees that we have a supported bit set, and they
+ must be holding the card's spinlock */
+static int ac97_recmask_io(struct ac97_codec *codec, int rw, int mask)
+{
+ unsigned int val;
+
+ if (rw) {
+ /* read it from the card */
+ val = codec->codec_read(codec, 0x1a) & 0x7;
+ return ac97_rm2oss[val];
+ }
+
+ /* else, write the first set in the mask as the
+ output */
+
+ val = ffs(mask);
+ val = ac97_oss_rm[val-1];
+ val |= val << 8; /* set both channels */
+
+#ifdef DEBUG
+ printk("ac97_codec: setting ac97 recmask to 0x%x\n", val);
+#endif
+
+ codec->codec_write(codec, 0x1a, val);
+
+ return 0;
+};
+
+static int ac97_mixer_ioctl(struct ac97_codec *codec, unsigned int cmd, unsigned long arg)
+{
+ int i, val = 0;
+
+ if (cmd == SOUND_MIXER_INFO) {
+ mixer_info info;
+ strncpy(info.id, codec->name, sizeof(info.id));
+ strncpy(info.name, codec->name, sizeof(info.name));
+ info.modify_counter = codec->modcnt;
+ if (copy_to_user((void *)arg, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ }
+ if (cmd == SOUND_OLD_MIXER_INFO) {
+ _old_mixer_info info;
+ strncpy(info.id, codec->name, sizeof(info.id));
+ strncpy(info.name, codec->name, sizeof(info.name));
+ if (copy_to_user((void *)arg, &info, sizeof(info)))
+ return -EFAULT;
+ return 0;
+ }
+
+ if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
+ return -EINVAL;
+
+ if (cmd == OSS_GETVERSION)
+ return put_user(SOUND_VERSION, (int *)arg);
+
+ if (_IOC_DIR(cmd) == _IOC_READ) {
+ switch (_IOC_NR(cmd)) {
+ case SOUND_MIXER_RECSRC: /* give them the current record source */
+ if (!codec->recmask_io) {
+ val = 0;
+ } else {
+ val = codec->recmask_io(codec, 1, 0);
+ }
+ break;
+
+ case SOUND_MIXER_DEVMASK: /* give them the supported mixers */
+ val = codec->supported_mixers;
+ break;
+
+ case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
+ val = codec->record_sources;
+ break;
+
+ case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
+ val = codec->stereo_mixers;
+ break;
+
+ case SOUND_MIXER_CAPS:
+ val = SOUND_CAP_EXCL_INPUT;
+ break;
+
+ default: /* read a specific mixer */
+ i = _IOC_NR(cmd);
+
+ if (!supported_mixer(codec, i))
+ return -EINVAL;
+
+ /* do we ever want to touch the hardware? */
+ /* val = codec->read_mixer(card,i); */
+ val = codec->mixer_state[i];
+ break;
+ }
+ return put_user(val,(int *)arg);
+ }
+
+ if (_IOC_DIR(cmd) == (_IOC_WRITE|_IOC_READ)) {
+ codec->modcnt++;
+ get_user_ret(val, (int *)arg, -EFAULT);
+
+ switch (_IOC_NR(cmd)) {
+ case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
+ if (!codec->recmask_io) return -EINVAL;
+ if (!(val &= codec->record_sources)) return -EINVAL;
+
+ codec->recmask_io(codec, 0, val);
+
+ return 0;
+ default: /* write a specific mixer */
+ i = _IOC_NR(cmd);
+
+ if (!supported_mixer(codec, i))
+ return -EINVAL;
+
+ ac97_set_mixer(codec, i, val);
+
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+int ac97_probe_codec(struct ac97_codec *codec)
+{
+ u16 id1, id2, cap;
+ int i;
+
+ /* probing AC97 codec, AC97 2.0 says that bit 15 of register 0x00 (reset) should
+ be read zero. Probing of AC97 in this way is not reliable, it is not even SAFE !! */
+ codec->codec_write(codec, AC97_RESET, 0L);
+ if ((cap = codec->codec_read(codec, AC97_RESET)) & 0x8000)
+ return 0;
+
+ id1 = codec->codec_read(codec, AC97_VENDOR_ID1);
+ id2 = codec->codec_read(codec, AC97_VENDOR_ID2);
+ for (i = 0; i < sizeof (snd_ac97_codec_ids); i++) {
+ if (snd_ac97_codec_ids[i].id == ((id1 << 16) | id2)) {
+ codec->name = snd_ac97_codec_ids[i].name;
+ codec->codec_init = snd_ac97_codec_ids[i].init;
+ break;
+ }
+ }
+ if (codec->name == NULL)
+ codec->name = "Unknown";
+ printk(KERN_INFO "ac97_codec: ac97 vendor id1: 0x%04x, id2: 0x%04x (%s)\n",
+ id1, id2, codec->name);
+ printk(KERN_INFO "ac97_codec: capability: 0x%04x\n", cap);
+
+ /* mixer masks */
+ codec->supported_mixers = AC97_SUPPORTED_MASK;
+ codec->stereo_mixers = AC97_STEREO_MASK;
+ codec->record_sources = AC97_RECORD_MASK;
+ if (!(cap & 0x04))
+ codec->supported_mixers &= ~(SOUND_MASK_BASS|SOUND_MASK_TREBLE);
+
+ /* generic OSS to AC97 wrapper */
+ codec->read_mixer = ac97_read_mixer;
+ codec->write_mixer = ac97_write_mixer;
+ codec->recmask_io = ac97_recmask_io;
+ codec->mixer_ioctl = ac97_mixer_ioctl;
+
+ /* initialize volume level */
+ codec->codec_write(codec, AC97_MASTER_VOL_STEREO, 0L);
+ codec->codec_write(codec, AC97_PCMOUT_VOL, 0L);
+
+ /* codec specific initialization for 4-6 channel output */
+ if (codec->id != 0 && codec->codec_init != NULL) {
+ codec->codec_init(codec);
+ }
+
+ /* initilize mixer channel volumes */
+ for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
+ struct mixer_defaults *md = &mixer_defaults[i];
+ if (md->mixer == -1)
+ break;
+ if (!supported_mixer(codec, md->mixer))
+ continue;
+ ac97_set_mixer(codec, md->mixer, md->value);
+ }
+
+ return 1;
+}
+
+static int sigmatel_init(struct ac97_codec * codec)
+{
+ codec->codec_write(codec, AC97_SURROUND_MASTER, 0L);
+ /* initialize SigmaTel STAC9721/23 */
+ codec->codec_write(codec, 0x74, 0x01);
+ return 1;
+}
+
+EXPORT_SYMBOL(ac97_probe_codec);
diff --git a/drivers/sound/ac97_codec.h b/drivers/sound/ac97_codec.h
new file mode 100644
index 000000000..36d2b052a
--- /dev/null
+++ b/drivers/sound/ac97_codec.h
@@ -0,0 +1,157 @@
+#ifndef _AC97_CODEC_H_
+#define _AC97_CODEC_H_
+
+#include "sound_config.h"
+#include "sound_calls.h"
+
+/* AC97 1.0 */
+#define AC97_RESET 0x0000 //
+#define AC97_MASTER_VOL_STEREO 0x0002 // Line Out
+#define AC97_HEADPHONE_VOL 0x0004 //
+#define AC97_MASTER_VOL_MONO 0x0006 // TAD Output
+#define AC97_MASTER_TONE 0x0008 //
+#define AC97_PCBEEP_VOL 0x000a // none
+#define AC97_PHONE_VOL 0x000c // TAD Input (mono)
+#define AC97_MIC_VOL 0x000e // MIC Input (mono)
+#define AC97_LINEIN_VOL 0x0010 // Line Input (stereo)
+#define AC97_CD_VOL 0x0012 // CD Input (stereo)
+#define AC97_VIDEO_VOL 0x0014 // none
+#define AC97_AUX_VOL 0x0016 // Aux Input (stereo)
+#define AC97_PCMOUT_VOL 0x0018 // Wave Output (stereo)
+#define AC97_RECORD_SELECT 0x001a //
+#define AC97_RECORD_GAIN 0x001c
+#define AC97_RECORD_GAIN_MIC 0x001e
+#define AC97_GENERAL_PURPOSE 0x0020
+#define AC97_3D_CONTROL 0x0022
+#define AC97_MODEM_RATE 0x0024
+#define AC97_POWER_CONTROL 0x0026
+
+/* AC'97 2.0 */
+#define AC97_EXTENDED_ID 0x0028 /* Extended Audio ID */
+#define AC97_EXTENDED_STATUS 0x002A /* Extended Audio Status */
+#define AC97_PCM_FRONT_DAC_RATE 0x002C /* PCM Front DAC Rate */
+#define AC97_PCM_SURR_DAC_RATE 0x002E /* PCM Surround DAC Rate */
+#define AC97_PCM_LFE_DAC_RATE 0x0030 /* PCM LFE DAC Rate */
+#define AC97_PCM_LR_DAC_RATE 0x0032 /* PCM LR DAC Rate */
+#define AC97_PCM_MIC_ADC_RATE 0x0034 /* PCM MIC ADC Rate */
+#define AC97_CENTER_LFE_MASTER 0x0036 /* Center + LFE Master Volume */
+#define AC97_SURROUND_MASTER 0x0038 /* Surround (Rear) Master Volume */
+#define AC97_RESERVED_3A 0x003A /* Reserved */
+
+/* range 0x3c-0x58 - MODEM */
+
+/* registers 0x005a - 0x007a are vendor reserved */
+
+#define AC97_VENDOR_ID1 0x007c
+#define AC97_VENDOR_ID2 0x007e
+
+/* volume control bit defines */
+#define AC97_MUTE 0x8000
+#define AC97_MICBOOST 0x0040
+#define AC97_LEFTVOL 0x3f00
+#define AC97_RIGHTVOL 0x003f
+
+/* record mux defines */
+#define AC97_RECMUX_MIC 0x0000
+#define AC97_RECMUX_CD 0x0101
+#define AC97_RECMUX_VIDEO 0x0202 /* not used */
+#define AC97_RECMUX_AUX 0x0303
+#define AC97_RECMUX_LINE 0x0404
+#define AC97_RECMUX_STEREO_MIX 0x0505
+#define AC97_RECMUX_MONO_MIX 0x0606
+#define AC97_RECMUX_PHONE 0x0707
+
+
+/* general purpose register bit defines */
+#define AC97_GP_LPBK 0x0080 /* Loopback mode */
+#define AC97_GP_MS 0x0100 /* Mic Select 0=Mic1, 1=Mic2 */
+#define AC97_GP_MIX 0x0200 /* Mono output select 0=Mix, 1=Mic */
+#define AC97_GP_RLBK 0x0400 /* Remote Loopback - Modem line codec */
+#define AC97_GP_LLBK 0x0800 /* Local Loopback - Modem Line codec */
+#define AC97_GP_LD 0x1000 /* Loudness 1=on */
+#define AC97_GP_3D 0x2000 /* 3D Enhancement 1=on */
+#define AC97_GP_ST 0x4000 /* Stereo Enhancement 1=on */
+#define AC97_GP_POP 0x8000 /* Pcm Out Path, 0=pre 3D, 1=post 3D */
+
+
+/* powerdown control and status bit defines */
+
+/* status */
+#define AC97_PWR_MDM 0x0010 /* Modem section ready */
+#define AC97_PWR_REF 0x0008 /* Vref nominal */
+#define AC97_PWR_ANL 0x0004 /* Analog section ready */
+#define AC97_PWR_DAC 0x0002 /* DAC section ready */
+#define AC97_PWR_ADC 0x0001 /* ADC section ready */
+
+/* control */
+#define AC97_PWR_PR0 0x0100 /* ADC and Mux powerdown */
+#define AC97_PWR_PR1 0x0200 /* DAC powerdown */
+#define AC97_PWR_PR2 0x0400 /* Output mixer powerdown (Vref on) */
+#define AC97_PWR_PR3 0x0800 /* Output mixer powerdown (Vref off) */
+#define AC97_PWR_PR4 0x1000 /* AC-link powerdown */
+#define AC97_PWR_PR5 0x2000 /* Internal Clk disable */
+#define AC97_PWR_PR6 0x4000 /* HP amp powerdown */
+#define AC97_PWR_PR7 0x8000 /* Modem off - if supported */
+
+/* useful power states */
+#define AC97_PWR_D0 0x0000 /* everything on */
+#define AC97_PWR_D1 AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR4
+#define AC97_PWR_D2 AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR3|AC97_PWR_PR4
+#define AC97_PWR_D3 AC97_PWR_PR0|AC97_PWR_PR1|AC97_PWR_PR2|AC97_PWR_PR3|AC97_PWR_PR4
+#define AC97_PWR_ANLOFF AC97_PWR_PR2|AC97_PWR_PR3 /* analog section off */
+
+/* Total number of defined registers. */
+#define AC97_REG_CNT 64
+
+
+/* OSS interface to the ac97s.. */
+#define AC97_STEREO_MASK (SOUND_MASK_VOLUME|SOUND_MASK_PCM|\
+ SOUND_MASK_LINE|SOUND_MASK_CD|\
+ SOUND_MIXER_ALTPCM|SOUND_MASK_IGAIN|\
+ SOUND_MASK_LINE1|SOUND_MASK_VIDEO)
+
+#define AC97_SUPPORTED_MASK (AC97_STEREO_MASK | \
+ SOUND_MASK_BASS|SOUND_MASK_TREBLE|\
+ SOUND_MASK_SPEAKER|SOUND_MASK_MIC|\
+ SOUND_MIXER_PHONEIN|SOUND_MIXER_PHONEOUT)
+
+#define AC97_RECORD_MASK (SOUND_MASK_MIC|\
+ SOUND_MASK_CD| SOUND_MASK_VIDEO| SOUND_MASK_LINE1| SOUND_MASK_LINE|\
+ SOUND_MASK_PHONEIN)
+
+#define supported_mixer(CODEC,FOO) ( CODEC->supported_mixers & (1<<FOO) )
+
+struct ac97_codec {
+ /* AC97 controller connected with */
+ void *private_data;
+
+ char *name;
+ int id;
+ int dev_mixer;
+
+ /* codec specific init/reset routines, used mainly for 4 or 6 channel support */
+ int (*codec_init) (struct ac97_codec *codec);
+
+ /* controller specific lower leverl ac97 accessing routines */
+ u16 (*codec_read) (struct ac97_codec *codec, u8 reg);
+ void (*codec_write) (struct ac97_codec *codec, u8 reg, u16 val);
+
+ /* OSS mixer masks */
+ int modcnt;
+ int supported_mixers;
+ int stereo_mixers;
+ int record_sources;
+
+ /* OSS mixer interface */
+ int (*read_mixer) (struct ac97_codec *codec, int oss_channel);
+ void (*write_mixer)(struct ac97_codec *codec, int oss_channel,
+ unsigned int left, unsigned int right);
+ int (*recmask_io) (struct ac97_codec *codec, int rw, int mask);
+ int (*mixer_ioctl)(struct ac97_codec *codec, unsigned int cmd, unsigned long arg);
+
+ /* saved OSS mixer states */
+ unsigned int mixer_state[SOUND_MIXER_NRDEVICES];
+};
+
+extern int ac97_probe_codec(struct ac97_codec *);
+#endif
diff --git a/drivers/sound/trident.c b/drivers/sound/trident.c
index c8c0cd0c3..2f808c92c 100644
--- a/drivers/sound/trident.c
+++ b/drivers/sound/trident.c
@@ -29,16 +29,36 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* History
+ * v0.11 Jan 27 2000 Ollie Lho
+ * DMA bug, scheduler latency, second try
+ * v0.10 Jan 24 2000 Ollie Lho
+ * DMA bug fixed, found kernel scheduling problem
+ * v0.09 Jan 20 2000 Ollie Lho
+ * Clean up of channel register access routine (prepare for channel binding)
+ * v0.08 Jan 14 2000 Ollie Lho
+ * Isolation of AC97 codec code
+ * v0.07 Jan 13 2000 Ollie Lho
+ * Get rid of ugly old low level access routines (e.g. CHRegs.lp****)
+ * v0.06 Jan 11 2000 Ollie Lho
+ * Preliminary support for dual (more ?) AC97 codecs
* v0.05 Jan 08 2000 Luca Montecchiani <m.luca@iname.com>
- * adapt to 2.3.x new __setup/__initcall
+ * adapt to 2.3.x new __setup/__init call
* v0.04 Dec 31 1999 Ollie Lho
- * Multiple Open, useing Middle Loop Interrupt to smooth playback
+ * Multiple Open, using Middle Loop Interrupt to smooth playback
* v0.03 Dec 24 1999 Ollie Lho
* mem leak in prog_dmabuf and dealloc_dmabuf removed
* v0.02 Dec 15 1999 Ollie Lho
* SiS 7018 support added, playback O.K.
* v0.01 Alan Cox et. al.
* Initial Release in kernel 2.3.30, does not work
+ *
+ * ToDo
+ * Clean up of low level channel register access code. (done)
+ * Fix the bug on dma buffer management in update_ptr, read/write, drain_dac (done)
+ * Dual AC97 codecs support (done partially, need channel binding to test)
+ * Recording support
+ * Mmap support
+ * "Channel Binding" ioctl extension
*/
#include <linux/config.h>
@@ -66,34 +86,40 @@
#endif
#include "trident.h"
-#include "ac97.h"
+#include "ac97_codec.h"
#undef DEBUG
-#define DRIVER_VERSION "0.05"
-
-#define TRIDENT_FMT_STEREO 0x01
-#define TRIDENT_FMT_16BIT 0x02
-#define TRIDENT_FMT_MASK 0x03
-#define TRIDENT_DAC_SHIFT 0
-#define TRIDENT_ADC_SHIFT 4
-
-#define TRIDENT_ENABLE_PE 1
-#define TRIDENT_ENABLE_RE 2
-#define DAC_RUNNING 1
-#define ADC_RUNNING 2
+#define DRIVER_VERSION "0.11"
+/* magic numbers to protect our data structures */
#define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */
#define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */
-/* number of instances of opening /dev/dsp, can your CPU handle this ? */
-#define NR_DSPS 32
+/* The first 32 channels are called Bank A. They are (should be) reserved
+ for MIDI synthesizer. But since that is not supported yet, we can (ab)use
+ them to play PCM samples */
+#undef ABUSE_BANK_A
+
+/* maxinum number of instances of opening /dev/dspN, can your CPU handle this ?
+ NOTE: If /dev/dsp is opened O_RDWR (i.e. full duplex) it will consume 2 HW
+ channels */
+#ifdef ABUSE_BANK_A
+#define NR_HW_CH 64
+#else
+#define NR_HW_CH 32
+#endif
+
+/* maxinum nuber of AC97 codecs connected, AC97 2.0 defined 4, but 7018 and 4D-NX only
+ have 2 SDATA_IN lines (currently) */
+#define NR_AC97 2
+/* minor number of /dev/dspW */
#define SND_DEV_DSP16 5
static const unsigned sample_size[] = { 1, 2, 2, 4 };
static const unsigned sample_shift[] = { 0, 1, 1, 2 };
-static const char *sample_format[] = {"8 bits Mono", "8 bits Stereo", "16 bits Mono", "16 bits Stereo"};
+
static const char invalid_magic[] = KERN_CRIT "trident: invalid magic value in %s\n";
struct pci_audio_info {
@@ -108,52 +134,12 @@ static struct pci_audio_info pci_audio_devices[] = {
{PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018, "SiS 7018 PCI Audio"}
};
-static struct {
- unsigned int id;
- char *name;
-} snd_ac97_codec_ids[] = {
- {0x414B4D00, "Asahi Kasei AK4540" },
- {0x41445340, "Analog Devices AD1881" },
- {0x43525900, "Cirrus Logic CS4297" },
- {0x43525913, "Cirrus Logic CS4297A" },
- {0x43525931, "Cirrus Logic CS4299" },
- {0x4e534331, "National Semiconductor LM4549"},
- {0x83847600, "SigmaTel STAC????" },
- {0x83847604, "SigmaTel STAC9701/3/4/5"},
- {0x83847605, "SigmaTel STAC9704" },
- {0x83847608, "SigmaTel STAC9708" },
- {0x83847609, "SigmaTel STAC9721/23" },
- {0x00000000, NULL}
-};
-
-typedef struct tChannelControl
-{
- // register data
- unsigned int * lpChStart;
- unsigned int * lpChStop;
- unsigned int * lpChAint;
- unsigned int * lpChAinten;
-
- // register addresses
- unsigned int * lpAChStart;
- unsigned int * lpAChStop;
- unsigned int * lpAChAint;
- unsigned int * lpAChAinten;
-
- unsigned int data[16];
-
-} CHANNELCONTROL;
-
/* "software" or virtual channel, an instance of opened /dev/dsp */
struct trident_state {
unsigned int magic;
struct trident_card *card; /* Card info */
- /* wave stuff */
- unsigned int rateadc, ratedac;
- unsigned char fmt, enable;
-
- /* single opne lock mechanism, should be removed */
+ /* single open lock mechanism, only used for recording */
struct semaphore open_sem;
wait_queue_head_t open_wait;
@@ -164,26 +150,33 @@ struct trident_state {
int virt;
struct dmabuf {
+ /* wave sample stuff */
+ unsigned int rate;
+ unsigned char fmt, enable;
+
+ /* hardware channel */
+ struct trident_channel *channel;
+
+ /* OSS buffer manangemeent stuff */
void *rawbuf;
unsigned buforder;
unsigned numfrag;
unsigned fragshift;
- /* hardware channel number */
- int chan;
+ /* our buffer acts like a circular ring */
+ unsigned hwptr; /* where dma last started, update by update_ptr */
+ unsigned swptr; /* where driver last clear/filled, updated by read/write */
+ int count; /* bytes to be comsumed by dma machine */
+ unsigned total_bytes; /* total bytes dmaed by hardware */
- /* XXX zab - swptr only in here so that it can be referenced by
- clear_advance, as far as I can tell :( */
- unsigned hwptr, swptr;
- unsigned total_bytes;
- int count;
- unsigned error; /* over/underrun */
- wait_queue_head_t wait;
+ unsigned error; /* number of over/underruns */
+ wait_queue_head_t wait; /* put process on wait queue when no more space in buffer */
/* redundant, but makes calculations easier */
unsigned fragsize;
unsigned dmasize;
unsigned fragsamples;
+
/* OSS stuff */
unsigned mapped:1;
unsigned ready:1;
@@ -192,44 +185,45 @@ struct trident_state {
int ossmaxfrags;
unsigned subdivision;
} dma_dac, dma_adc;
-
- u8 bDMAStart;
-
};
/* hardware channels */
struct trident_channel {
- int chan; /* channel number */
- u32 lba;
- u32 eso;
+ int num; /* channel number */
+ u32 lba; /* reg 0xe4 */
+ u32 eso; /* reg 0xe8 */
u32 delta;
- u16 attribute;
-
+ u16 attribute; /* reg 0xec */
+ u16 fm_vol;
+ u32 control; /* reg 0xf0 */
};
-struct trident_pcm_bank {
- /* registers to control bank operations */
+struct trident_pcm_bank_address {
u32 start;
u32 stop;
u32 aint;
u32 aint_en;
+};
+static struct trident_pcm_bank_address bank_a_addrs =
+{
+ T4D_START_A,
+ T4D_STOP_A,
+ T4D_AINT_A,
+ T4D_AINTEN_A
+};
+static struct trident_pcm_bank_address bank_b_addrs =
+{
+ T4D_START_B,
+ T4D_STOP_B,
+ T4D_AINT_B,
+ T4D_AINTEN_B
+};
+struct trident_pcm_bank {
+ /* register addresses to control bank operations */
+ struct trident_pcm_bank_address *addresses;
/* each bank has 32 channels */
u32 bitmap; /* channel allocation bitmap */
- //struct trident_channel channels[32];
-};
-
-struct trident_mixer {
- int modcnt;
- int supported_mixers;
- int stereo_mixers;
- int record_sources;
-
- /* the caller must guarantee arg sanity before calling these */
- /* int (*read_mixer)(struct trident_card *card, int index);*/
- void (*write_mixer)(struct trident_card *card,int mixer, unsigned int left,
- unsigned int right);
- int (*recmask_io)(struct trident_card *card,int rw,int mask);
- unsigned int mixer_state[SOUND_MIXER_NRDEVICES];
+ struct trident_channel channels[32];
};
struct trident_card {
@@ -239,7 +233,7 @@ struct trident_card {
struct trident_card *next;
/* The trident has a certain amount of cross channel interaction
- so we use a single per card lock */
+ so we use a single per card lock */
spinlock_t lock;
/* PCI device stuff */
@@ -249,286 +243,225 @@ struct trident_card {
/* soundcore stuff */
int dev_audio;
- int dev_mixer;
- struct trident_mixer mix;
- struct trident_state *channels[NR_DSPS];
+ /* structures for abstraction of hardware facilities, codecs, banks and channels*/
+ struct ac97_codec *ac97_codec[NR_AC97];
+ struct trident_pcm_bank banks[NR_BANKS];
+ struct trident_state *states[NR_HW_CH];
/* hardware resources */
unsigned long iobase;
u32 irq;
-
- /* hardware channel allocation bitmap */
- u32 bitmap[2];
-
- /* ugly stupid thing, remove ASAP */
- CHANNELCONTROL ChRegs;
- int ChanDwordCount;
};
static struct trident_card *devs = NULL;
-/*
- * Trident support library routines
- */
-
-/*---------------------------------------------------------------------------
- void ResetAinten( struct trident_state *trident, int ChannelNum)
-
- Description: This routine will disable interrupts and ack any
- existing interrupts for specified channel.
-
- Parameters: trident - pointer to target device class for 4DWave.
- ChannelNum - channel number
-
- returns: TRUE if everything went ok, else FALSE.
-
- ---------------------------------------------------------------------------*/
-
-static void ResetAinten(struct trident_card * trident, int ChannelNum)
-{
- unsigned int dwMask;
- unsigned int x = ChannelNum >> 5;
- unsigned int ChanDwordCount = trident->ChanDwordCount;
-
- IReadAinten(&trident->ChRegs);
- dwMask = 1 << (ChannelNum & 0x1f);
- trident->ChRegs.lpChAinten[x] &= ~dwMask;
- IWriteAinten(&trident->ChRegs);
- // Ack the channel in case the interrupt was set before we disable it.
- outl(dwMask, TRID_REG(trident, trident->ChRegs.lpAChAint[x]));
-}
+static void trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val);
+static u16 trident_ac97_get(struct ac97_codec *codec, u8 reg);
-/*---------------------------------------------------------------------------
- void EnableEndInterrupts( struct trident_card *trident)
-
- Description: This routine will enable end of loop interrupts.
- End of loop interrupts will occur when a running
- channel reaches ESO.
-
- Parameters: trident - pointer to target device class for 4DWave.
-
- returns: TRUE if everything went ok, else FALSE.
-
- ---------------------------------------------------------------------------*/
-
-static int trident_enable_end_interrupts(struct trident_card * trident)
+static int trident_open_mixdev(struct inode *inode, struct file *file);
+static int trident_release_mixdev(struct inode *inode, struct file *file);
+static int trident_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg);
+static loff_t trident_llseek(struct file *file, loff_t offset, int origin);
+
+static int trident_enable_loop_interrupts(struct trident_card * card)
{
u32 global_control;
- global_control = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
+ global_control = inl(TRID_REG(card, T4D_LFO_GC_CIR));
- switch (trident->pci_id)
+ switch (card->pci_id)
{
case PCI_DEVICE_ID_SI_7018:
- global_control |= (ENDLP_IE | BANK_B_EN);
+ global_control |= (ENDLP_IE | MIDLP_IE| BANK_B_EN);
break;
case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- global_control |= ENDLP_IE;
+ global_control |= (ENDLP_IE | MIDLP_IE);
break;
default:
return FALSE;
}
- outl(global_control, TRID_REG(trident, T4D_LFO_GC_CIR));
+ outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR));
#ifdef DEBUG
- printk("trident: Enable End Interrupts, globctl = 0x%08X\n", global_control);
+ printk("trident: Enable Loop Interrupts, globctl = 0x%08X\n",
+ global_control);
#endif
return (TRUE);
}
-static int trident_enable_middle_interrupts(struct trident_card * trident)
+static int trident_disable_loop_interrupts(struct trident_card * card)
{
u32 global_control;
- global_control = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
-
- switch (trident->pci_id)
- {
- case PCI_DEVICE_ID_SI_7018:
- global_control |= (MIDLP_IE | BANK_B_EN);
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- default:
- global_control |= MIDLP_IE;
- break;
- }
-
- outl(global_control, TRID_REG(trident, T4D_LFO_GC_CIR));
+ global_control = inl(TRID_REG(card, T4D_LFO_GC_CIR));
+ global_control &= ~(ENDLP_IE | MIDLP_IE);
+ outl(global_control, TRID_REG(card, T4D_LFO_GC_CIR));
#ifdef DEBUG
- printk("trident: Enable Middle Interrupts, globctl = 0x%08X\n", global_control);
+ printk("trident: Disabled Loop Interrupts, globctl = 0x%08X\n",
+ global_control);
#endif
return (TRUE);
}
-/*---------------------------------------------------------------------------
- void DisableEndInterrupts( struct trident_card *trident)
-
- Description: This routine will disable end of loop interrupts.
- End of loop interrupts will occur when a running
- channel reaches ESO.
-
- Parameters:
- trident - pointer to target device class for 4DWave.
-
- returns: TRUE if everything went ok, else FALSE.
-
- ---------------------------------------------------------------------------*/
-
-static int trident_disable_end_interrupts(struct trident_card * trident)
+
+static void trident_enable_voice_irq(struct trident_card * card, unsigned int channel)
{
- u32 global_control;
+ unsigned int mask = 1 << (channel & 0x1f);
+ struct trident_pcm_bank *bank = &card->banks[channel >> 5];
+ u32 reg, addr = bank->addresses->aint_en;
- global_control = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
- global_control &= ~ENDLP_IE;
- outl(global_control, TRID_REG(trident, T4D_LFO_GC_CIR));
+ reg = inl(TRID_REG(card, addr));
+ reg |= mask;
+ outl(reg, TRID_REG(card, addr));
#ifdef DEBUG
- printk("trident: Disabled End Interrupts, globctl = 0x%08X\n", global_control);
+ reg = inl(TRID_REG(card, T4D_AINTEN_B));
+ printk("trident: enabled IRQ on channel %d, AINTEN_B = 0x%08x\n",
+ channel, reg);
#endif
- return (TRUE);
}
-static int trident_disable_middle_interrupts(struct trident_card * trident)
+static void trident_disable_voice_irq(struct trident_card * card, unsigned int channel)
{
- u32 global_control;
-
- global_control = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
- global_control &= ~MIDLP_IE;
- outl(global_control, TRID_REG(trident, T4D_LFO_GC_CIR));
+ unsigned int mask = 1 << (channel & 0x1f);
+ struct trident_pcm_bank *bank = &card->banks[channel >> 5];
+ u32 reg, addr = bank->addresses->aint_en;
+
+ reg = inl(TRID_REG(card, addr));
+ reg &= ~mask;
+ outl(reg, TRID_REG(card, addr));
+
+ /* Ack the channel in case the interrupt was set before we disable it. */
+ outl(mask, TRID_REG(card, bank->addresses->aint));
#ifdef DEBUG
- printk("trident: Disabled Middle Interrupts, globctl = 0x%08X\n", global_control);
+ reg = inl(TRID_REG(card, T4D_AINTEN_B));
+ printk("trident: disabled IRQ on channel %d, AINTEN_B = 0x%08x\n",
+ channel, reg);
#endif
- return (TRUE);
}
-/*---------------------------------------------------------------------------
- void trident_enable_voice_irq( unsigned int HwChannel )
-
- Description: Enable an interrupt channel, any channel 0 thru n.
- This routine automatically handles the fact that there are
- more than 32 channels available.
-
- Parameters : HwChannel - Channel number 0 thru n.
- trident - pointer to target device class for 4DWave.
-
- Return Value: None.
-
- ---------------------------------------------------------------------------*/
-void trident_enable_voice_irq(struct trident_card * trident, unsigned int channel)
+
+static void trident_start_voice(struct trident_card * card, unsigned int channel)
{
- unsigned int bank, mask, ChanDwordCount;
+ unsigned int mask = 1 << (channel & 0x1f);
+ struct trident_pcm_bank *bank = &card->banks[channel >> 5];
+ u32 addr = bank->addresses->start;
+
+#ifdef DEBUG
u32 reg;
+#endif
- bank = channel >> 5;
- mask = 1 << (channel & 0x1f);
+ outl(mask, TRID_REG(card, addr));
- ChanDwordCount = trident->ChanDwordCount;
+#ifdef DEBUG
+ reg = inl(TRID_REG(card, T4D_START_B));
+ printk("trident: start voice on channel %d, START_B = 0x%08x\n",
+ channel, reg);
+#endif
+}
- IReadAinten(&trident->ChRegs);
- trident->ChRegs.lpChAinten[bank] |= mask;
- IWriteAinten(&trident->ChRegs);
+static void trident_stop_voice(struct trident_card * card, unsigned int channel)
+{
+ unsigned int mask = 1 << (channel & 0x1f);
+ struct trident_pcm_bank *bank = &card->banks[channel >> 5];
+ u32 addr = bank->addresses->stop;
#ifdef DEBUG
- reg = inl(TRID_REG(trident, T4D_AINTEN_B));
- printk("trident: enabled IRQ on channel %d\n", channel);
+ u32 reg;
+#endif
+
+ outl(mask, TRID_REG(card, addr));
+
+#ifdef DEBUG
+ reg = inl(TRID_REG(card, T4D_STOP_B));
+ printk("trident: stop voice on channel %d, STOP_B = 0x%08x\n",
+ channel, reg);
#endif
}
-/*---------------------------------------------------------------------------
- void trident_disable_voice_irq( unsigned int HwChannel )
-
- Description: Disable an interrupt channel, any channel 0 thru n.
- This routine automatically handles the fact that there are
- more than 32 channels available.
-
- Parameters : HwChannel - Channel number 0 thru n.
- trident - pointer to target device class for 4DWave.
-
- Return Value: None.
-
- ---------------------------------------------------------------------------*/
-void trident_disable_voice_irq(struct trident_card * trident, unsigned int channel)
+static int trident_check_channel_interrupt(struct trident_card * card, int channel)
{
- unsigned int bank, mask, ChanDwordCount;
- u32 reg;
+ unsigned int mask = 1 << (channel & 0x1f);
+ struct trident_pcm_bank *bank = &card->banks[channel >> 5];
+ u32 reg, addr = bank->addresses->aint;
- bank = channel >> 5;
- mask = 1 << (channel & 0x1f);
+ reg = inl(TRID_REG(card, addr));
+
+#ifdef DEBUG
+ if (reg & mask)
+ printk("trident: channel %d has interrupt, AINT_B = 0x%08x\n",
+ channel, reg);
+#endif
+ return (reg & mask) ? TRUE : FALSE;
+}
+
+static void trident_ack_channel_interrupt(struct trident_card * card, int channel)
+{
+ unsigned int mask = 1 << (channel & 0x1f);
+ struct trident_pcm_bank *bank = &card->banks[channel >> 5];
+ u32 reg, addr = bank->addresses->aint;
- ChanDwordCount = trident->ChanDwordCount;
- IReadAinten(&trident->ChRegs);
- trident->ChRegs.lpChAinten[bank] &= ~mask;
- IWriteAinten(&trident->ChRegs);
+ reg = inl(TRID_REG(card, addr));
+ reg &= mask;
+ outl(reg, TRID_REG(card, addr));
#ifdef DEBUG
- reg = inl(TRID_REG(trident, T4D_AINTEN_B));
- printk("trident: disabled IRQ on channel %d\n", channel);
+ reg = inl(TRID_REG(card, T4D_AINT_B));
+ printk("trident: Ack channel %d interrupt, AINT_B = 0x%08x\n",
+ channel, reg);
#endif
}
-/*---------------------------------------------------------------------------
- unsigned int AllocateChannelPCM( void )
-
- Description: Allocate hardware channel by reverse order (63-0).
-
- Parameters : trident - pointer to target device class for 4DWave.
-
- Return Value: hardware channel - 0-63 or -1 when no channel is available
-
- ---------------------------------------------------------------------------*/
-
-static int trident_alloc_pcm_channel(struct trident_card *trident)
+static struct trident_channel * trident_alloc_pcm_channel(struct trident_card *card)
{
+ struct trident_pcm_bank *bank;
int idx;
- if (trident->bitmap[BANK_B] == ~0UL) {
+ bank = &card->banks[BANK_B];
+ if (bank->bitmap == ~0UL) {
/* no more free channels avaliable */
printk(KERN_ERR "trident: no more channels available on Bank B.\n");
- return -1;
+#ifdef ABUSE_BANK_A
+ goto bank_a;
+#endif
+ return NULL;
}
for (idx = 31; idx >= 0; idx--) {
- if (!(trident->bitmap[BANK_B] & (1 << idx))) {
- trident->bitmap[BANK_B] |= 1 << idx;
- return idx + 32;
+ if (!(bank->bitmap & (1 << idx))) {
+ struct trident_channel *channel = &bank->channels[idx];
+ bank->bitmap |= 1 << idx;
+ channel->num = idx + 32;
+ return channel;
}
}
#ifdef ABUSE_BANK_A
/* channels in Bank A should be reserved for synthesizer
not for normal use (channels in Bank A can't record) */
- if (trident->bitmap[BANK_A] == ~0UL) {
+ bank_a:
+ bank = &card->banks[BANK_A];
+ if (bank->bitmap == ~0UL) {
/* no more free channels avaliable */
- printk(KERN_ERR "trident: no channels available on Bank A.\n");
- return -1;
+ printk(KERN_ERR "trident: no more channels available on Bank A.\n");
+ return NULL;
}
for (idx = 31; idx >= 0; idx--) {
- if (!(trident->bitmap[BANK_A] & (1 << idx))) {
- trident->bitmap[BANK_A] |= 1 << idx;
- return idx;
+ if (!(bank->bitmap & (1 << idx))) {
+ struct trident_channel *channel = &bank->channels[idx];
+ banks->bitmap |= 1 << idx;
+ channel->num = idx;
+ return channels;
}
}
#endif
-
- return -1;
+ return NULL;
}
-/*---------------------------------------------------------------------------
- void FreeChannelPCM( int channel )
-
- Description: Free hardware channel.
-
- Parameters : trident - pointer to target device class for 4DWave.
- channel - hardware channel number 0-63
-
- Return Value: none
-
- ---------------------------------------------------------------------------*/
-
-static void trident_free_pcm_channel(struct trident_card *trident, int channel)
+static void trident_free_pcm_channel(struct trident_card *card, int channel)
{
int bank;
@@ -543,236 +476,74 @@ static void trident_free_pcm_channel(struct trident_card *trident, int channel)
bank = channel >> 5;
channel = channel & 0x1f;
- if (trident->bitmap[bank] & (1 << (channel))) {
- trident->bitmap[bank] &= ~(1 << (channel));
+ if (card->banks[bank].bitmap & (1 << (channel))) {
+ card->banks[bank].bitmap &= ~(1 << (channel));
}
}
-/*---------------------------------------------------------------------------
- void trident_start_voice( ULONG HwChannel )
-
- Description: Start a channel, any channel 0 thru n.
- This routine automatically handles the fact that there are
- more than 32 channels available.
-
- Parameters : HwChannel - Channel number 0 thru n.
- trident - pointer to target device class for 4DWave.
-
- Return Value: None.
-
- ---------------------------------------------------------------------------*/
-void trident_start_voice(struct trident_card * trident, unsigned int channel)
-{
- unsigned int bank = channel >> 5;
- unsigned int mask = 1 << (channel & 0x1f);
-
- outl(mask, TRID_REG(trident, trident->ChRegs.lpAChStart[bank]));
-#ifdef DEBUG
- printk("trident: start voice on channel %d\n", channel);
-#endif
-}
-
-/*---------------------------------------------------------------------------
- void trident_stop_voice( ULONG HwChannel )
-
- Description: Stop a channel, any channel 0 thru n.
- This routine automatically handles the fact that there are
- more than 32 channels available.
-
- Parameters : HwChannel - Channel number 0 thru n.
- trident - pointer to target device class for 4DWave.
-
- Return Value: None.
-
- ---------------------------------------------------------------------------*/
-void trident_stop_voice(struct trident_card * trident, unsigned int channel)
+/* called with spin lock held */
+static int trident_load_channel_registers(struct trident_card *card, u32 *data, unsigned int channel)
{
- unsigned int bank = channel >> 5;
- unsigned int mask = 1 << (channel & 0x1f);
-
- outl(mask, TRID_REG(trident, trident->ChRegs.lpAChStop[bank]));
-#ifdef DEBUG
- printk("trident: stop voice on channel %d\n", channel);
-#endif
-}
-
-/*---------------------------------------------------------------------------
- int DidChannelInterrupt( )
-
- Description: Check if interrupt channel occurred.
-
- Parameters : trident - pointer to target device class for 4DWave.
-
- Return Value: TRUE if interrupt occurred, else FALSE.
-
- ---------------------------------------------------------------------------*/
-static int trident_check_channel_interrupt(struct trident_card * trident, int channel)
-{
- unsigned int ChanDwordCount = NUM_BANKS;
- unsigned int bank = channel >> 5;
- unsigned int mask = 1 << (channel & 0x1f);
-
- ReadAint(&trident->ChRegs);
-
-#ifdef DEBUG
- if (trident->ChRegs.lpChAint[bank] & mask)
- printk("trident: channel %d has interrupt\n", channel);
-#endif
- return (trident->ChRegs.lpChAint[bank] & mask) ? TRUE : FALSE;
-}
-
-/*---------------------------------------------------------------------------
- void AckChannelInterrupt( )
-
- Description: Acknowledge the interrupt bit for channel intrs.
-
- Parameters : trident - pointer to target device class for 4DWave.
-
- Return Value: None
-
- ---------------------------------------------------------------------------*/
-static void trident_ack_channel_interrupt(struct trident_card * trident, int channel)
-{
- unsigned int ChanDwordCount = NUM_BANKS;
- unsigned int bank = channel >> 5;
- unsigned int mask = 1 << (channel & 0x1f);
-
- ReadAint(&trident->ChRegs);
- trident->ChRegs.lpChAint[bank] &= mask;
- IWriteAint(&trident->ChRegs);
-}
-
-/*---------------------------------------------------------------------------
- int trident_load_hw_delta( unsigned int HwChannel, unsigned int Delta )
-
- Description: This routine writes Delta to the hardware.
-
- Parameters: Delta - data to write (2 Bytes only)
- HwChannel - Hardware channel to write to.
- trident - pointer to target device class for 4DWave.
-
- Returns: TRUE if all goes well, else FALSE.
-
- ---------------------------------------------------------------------------*/
-static int trident_load_hw_delta (struct trident_card * trident, unsigned int channel,
- unsigned short delta)
-{
- /* select a channel for output */
- outb(channel, TRID_REG(trident, T4D_LFO_GC_CIR));
+ int i;
- switch (trident->pci_id)
- {
- case PCI_DEVICE_ID_SI_7018:
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
- outw((u16) delta, TRID_REG(trident, CH_DX_ESO_DELTA));
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- outb(delta & 0xff, TRID_REG(trident, CH_NX_DELTA_CSO + 3));
- outb((delta >> 8)& 0xff, TRID_REG(trident, CH_NX_DELTA_ESO + 3));
- break;
- default:
+ if (channel > 63)
return FALSE;
- }
- return TRUE;
-}
-/*---------------------------------------------------------------------------
- int LoadVirtualChannel( ULONG *Data, ULONG HwChannel)
-
- Description: This routine writes all required channel registers to hardware.
-
- Parameters: *Data - a pointer to the data to write (5 ULONGS always).
- HwChannel - Hardware channel to write to.
- trident - pointer to target device class for 4DWave.
-
- Returns: TRUE if all goes well, else FALSE.
-
- ---------------------------------------------------------------------------*/
-static int LoadVirtualChannel(struct trident_card * trident, unsigned int *Data, unsigned int HwChannel)
-{
- unsigned int ChanData[CHANNEL_REGS];
- unsigned int ULONGSToDo = CHANNEL_REGS;
- unsigned int i;
- unsigned int Address = CHANNEL_START;
-
- /* Copy the data first... Hack... Before mucking with Volume! */
- memcpy((unsigned char *) ChanData, (unsigned char *) Data, ULONGSToDo * 4);
-
- outb((unsigned char) HwChannel, TRID_REG(trident, T4D_LFO_GC_CIR));
+ /* select hardware channel to write */
+ outb(channel, TRID_REG(card, T4D_LFO_GC_CIR));
+ /* output the channel registers */
+ for (i = 0; i < CHANNEL_REGS; i++) {
+ outl(data[i], TRID_REG(card, CHANNEL_START + 4*i));
+ }
- for (i = 0; i < ULONGSToDo; i++, Address += 4)
- outl(ChanData[i], TRID_REG(trident, Address));
-#ifdef DEBUG
- printk("(trident) load virtual channel %d\n", HwChannel);
-#endif
return TRUE;
}
-/*---------------------------------------------------------------------------
- trident_write_voice_regs
-
- Description: This routine will write the 5 hardware channel registers
- to hardware.
-
- Paramters: trident - pointer to target device class for 4DWave.
- Channel - Real or Virtual channel number.
- Each register field.
-
- Returns: TRUE if all goes well, else FALSE.
-
- ---------------------------------------------------------------------------*/
-int trident_write_voice_regs(struct trident_card * trident,
- unsigned int Channel,
- unsigned int LBA,
- unsigned int CSO,
- unsigned int ESO,
- unsigned int DELTA,
- unsigned int ALPHA_FMS,
- unsigned int FMC_RVOL_CVOL,
- unsigned int GVSEL,
- unsigned int PAN,
- unsigned int VOL,
- unsigned int CTRL,
- unsigned int EC)
+/* called with spin lock held */
+static int trident_write_voice_regs(struct trident_state *state, unsigned int rec)
{
- unsigned int ChanData[CHANNEL_REGS + 1], FmcRvolCvol;
+ unsigned int data[CHANNEL_REGS + 1];
+ struct trident_channel *channel;
- ChanData[1] = LBA;
- ChanData[4] = (GVSEL << 31) |
- ((PAN & 0x0000007f) << 24) |
- ((VOL & 0x000000ff) << 16) |
- ((CTRL & 0x0000000f) << 12) |
- (EC & 0x00000fff);
+ if (rec)
+ channel = state->dma_adc.channel;
+ else
+ channel = state->dma_dac.channel;
- FmcRvolCvol = FMC_RVOL_CVOL & 0x0000ffff;
+ data[1] = channel->lba;
+ data[4] = channel->control;
- switch (trident->pci_id)
+ switch (state->card->pci_id)
{
case PCI_DEVICE_ID_SI_7018:
+ data[0] = 0; /* Current Sample Offset */
+ data[2] = (channel->eso << 16) | (channel->delta & 0xffff);
+ data[3] = (channel->attribute << 16) | (channel->fm_vol & 0xffff);
+ break;
case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
- ChanData[0] = (CSO << 16) | (ALPHA_FMS & 0x0000ffff);
- ChanData[2] = (ESO << 16) | (DELTA & 0x0000ffff);
- ChanData[3] = FmcRvolCvol;
+ data[0] = 0; /* Current Sample Offset */
+ data[2] = (channel->eso << 16) | (channel->delta & 0xffff);
+ data[3] = channel->fm_vol & 0xffff;
break;
case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- ChanData[0] = (DELTA << 24) | (CSO & 0x00ffffff);
- ChanData[2] = ((DELTA << 16) & 0xff000000) | (ESO & 0x00ffffff);
- ChanData[3] = (ALPHA_FMS << 16) | FmcRvolCvol;
+ data[0] = (channel->delta << 24);
+ data[2] = ((channel->delta << 24) & 0xff000000) | (channel->eso & 0x00ffffff);
+ data[3] = channel->fm_vol & 0xffff;
break;
+ default:
+ return FALSE;
}
- LoadVirtualChannel(trident, ChanData, Channel);
-
- return TRUE;
+ return trident_load_channel_registers(state->card, data, channel->num);
}
static int compute_rate(u32 rate)
{
int delta;
- // We special case 44100 and 8000 since rounding with the equation
- // does not give us an accurate enough value. For 11025 and 22050
- // the equation gives us the best answer. All other frequencies will
- // also use the equation. JDW
+ /* We special case 44100 and 8000 since rounding with the equation
+ does not give us an accurate enough value. For 11025 and 22050
+ the equation gives us the best answer. All other frequencies will
+ also use the equation. JDW */
if (rate == 44100)
delta = 0xeb3;
else if (rate == 8000)
@@ -784,838 +555,267 @@ static int compute_rate(u32 rate)
return delta;
}
-/*---------------------------------------------------------------------------
- trident_set_dac_rate
-
- Description: This routine will set the sample rate for playback.
-
- Paramters: trident - pointer to target device class for 4DWave.
- rate - desired sample rate
- set - actually write hardware if set is true.
-
- Returns: The rate allowed by device.
-
- ---------------------------------------------------------------------------*/
-
-static unsigned int trident_set_dac_rate(struct trident_state * trident,
- unsigned int rate, int set)
-{
- u16 delta;
+/* set playback sample rate */
+static unsigned int trident_set_dac_rate(struct trident_state * state, unsigned int rate)
+{
+ struct dmabuf *dmabuf = &state->dma_dac;
if (rate > 48000)
rate = 48000;
if (rate < 4000)
rate = 4000;
- delta = compute_rate(rate);
- trident->ratedac = rate;
+ dmabuf->rate = rate;
+ dmabuf->channel->delta = compute_rate(rate);
- if (set)
- trident_load_hw_delta(trident->card, trident->dma_dac.chan,
- delta);
-#ifdef DEBUG
- printk("trident: called trident_set_dac_rate : rate = %d, "
- "set = %d, delta = 0x%04x\n", rate, set, delta);
+ trident_write_voice_regs(state, 0);
+
+#ifdef DEBUG
+ printk("trident: called trident_set_dac_rate : rate = %d\n", rate);
#endif
return rate;
}
-/*---------------------------------------------------------------------------
- trident_set_adc_rate
-
- Description: This routine will set the sample rate for capture.
-
- Paramters: trident - pointer to target device class for 4DWave.
- rate - desired sample rate
- set - actually write hardware if set is true.
-
- Returns: The rate allowed by device.
-
- ---------------------------------------------------------------------------*/
-
-static unsigned int trident_set_adc_rate(struct trident_state * trident,
- unsigned int rate, int set)
+/* set recording sample rate */
+static unsigned int trident_set_adc_rate(struct trident_state * state, unsigned int rate)
{
- u16 delta;
-
+ struct dmabuf *dmabuf = &state->dma_adc;
if (rate > 48000)
rate = 48000;
if (rate < 4000)
rate = 4000;
- delta = compute_rate(rate);
- trident->ratedac = rate;
-
-#if 0 /* It seems that 4D-Wave can not use wave tables channels for recording */
- if (set)
- trident_load_hw_delta(trident->card, trident->dma_adc.chan,
- delta);
-#endif
-#ifdef DEBUG
- printk("trident: called trident_set_adc_rate : rate = %d, "
- "set = %d, delta = 0x%04x\n", rate, set, delta);
-#endif
- return rate;
-}
-
-extern __inline__ unsigned ld2(unsigned int x)
-{
- unsigned r = 0;
-
- if (x >= 0x10000) {
- x >>= 16;
- r += 16;
- }
- if (x >= 0x100) {
- x >>= 8;
- r += 8;
- }
- if (x >= 0x10) {
- x >>= 4;
- r += 4;
- }
- if (x >= 4) {
- x >>= 2;
- r += 2;
- }
- if (x >= 2)
- r++;
- return r;
-}
-
-/* Write AC97 mixer registers */
-static void trident_ac97_set(struct trident_card *trident, u8 cmd, u16 val)
-{
- unsigned int address, mask, busy;
- unsigned short count = 0xffff;
- u32 data;
-
- data = ((u32) val) << 16;
-
- switch (trident->pci_id)
- {
- default:
- case PCI_DEVICE_ID_SI_7018:
- address = SI_AC97_WRITE;
- mask = SI_AC97_BUSY_WRITE | SI_AC97_AUDIO_BUSY;
- busy = SI_AC97_BUSY_WRITE;
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
- address = DX_ACR0_AC97_W;
- mask = busy = DX_AC97_BUSY_WRITE;
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- address = NX_ACR1_AC97_W;
- mask = busy = NX_AC97_BUSY_WRITE;
- break;
- }
-
- do {
- if ((inw(TRID_REG(trident, address)) & busy) == 0)
- break;
- } while (count--);
-
- data |= (mask | (cmd & AC97_REG_ADDR));
-
- if (count == 0) {
- printk(KERN_ERR "trident: AC97 CODEC write timed out.\n");
- return;
- }
- outl(data, TRID_REG(trident, address));
-}
-
-/* Read AC97 codec registers */
-static u16 trident_ac97_get(struct trident_card *trident, u8 cmd)
-{
- unsigned int address, mask, busy;
- unsigned short count = 0xffff;
- u32 data;
-
- switch (trident->pci_id)
- {
- default:
- case PCI_DEVICE_ID_SI_7018:
- address = SI_AC97_READ;
- mask = SI_AC97_BUSY_READ | SI_AC97_AUDIO_BUSY;
- busy = SI_AC97_BUSY_READ;
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
- address = DX_ACR1_AC97_R;
- mask = busy = DX_AC97_BUSY_READ;
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- address = NX_ACR2_AC97_R_PRIMARY;
- mask = NX_AC97_BUSY_READ;
- busy = 0x0c00;
- break;
- }
+ dmabuf->rate = rate;
+ dmabuf->channel->delta = compute_rate(rate);
- data = (mask | (cmd & AC97_REG_ADDR));
- outl(data, TRID_REG(trident, address));
-
- do {
- data = inl(TRID_REG(trident, address));
- if ((data & busy) == 0)
- break;
- } while (count--);
-
- if (count == 0) {
- printk(KERN_ERR "trident: AC97 CODEC read timed out.\n");
- data = 0;
- }
- return ((u16) (data >> 16));
-}
-
-/* OSS interface to the ac97s.. */
-
-#define AC97_STEREO_MASK (SOUND_MASK_VOLUME|\
- SOUND_MASK_PCM|SOUND_MASK_LINE|SOUND_MASK_CD|\
- SOUND_MASK_VIDEO|SOUND_MASK_LINE1|SOUND_MASK_IGAIN)
-
-#define AC97_SUPPORTED_MASK (AC97_STEREO_MASK | \
- SOUND_MASK_BASS|SOUND_MASK_TREBLE|SOUND_MASK_MIC|\
- SOUND_MASK_SPEAKER)
-
-#define AC97_RECORD_MASK (SOUND_MASK_MIC|\
- SOUND_MASK_CD| SOUND_MASK_VIDEO| SOUND_MASK_LINE1| SOUND_MASK_LINE|\
- SOUND_MASK_PHONEIN)
-
-#define supported_mixer(CARD,FOO) ( CARD->mix.supported_mixers & (1<<FOO) )
-
-/* this table has default mixer values for all OSS mixers.
- be sure to fill it in if you add oss mixers
- to anyone's supported mixer defines */
-
-/* possible __init */
-static struct mixer_defaults {
- int mixer;
- unsigned int value;
-} mixer_defaults[SOUND_MIXER_NRDEVICES] = {
- /* all values 0 -> 100 in bytes */
- {SOUND_MIXER_VOLUME, 0x3232},
- {SOUND_MIXER_BASS, 0x3232},
- {SOUND_MIXER_TREBLE, 0x3232},
- {SOUND_MIXER_SPEAKER, 0x3232},
- {SOUND_MIXER_MIC, 0x3232},
- {SOUND_MIXER_LINE, 0x3232},
- {SOUND_MIXER_CD, 0x3232},
- {SOUND_MIXER_VIDEO, 0x3232},
- {SOUND_MIXER_LINE1, 0x3232},
- {SOUND_MIXER_PCM, 0x3232},
- {SOUND_MIXER_IGAIN, 0x3232},
- {-1,0}
-};
-
-static struct ac97_mixer_hw {
- unsigned char offset;
- int scale;
-} ac97_hw[SOUND_MIXER_NRDEVICES]= {
- [SOUND_MIXER_VOLUME] = {AC97_MASTER_VOL_STEREO,63},
- [SOUND_MIXER_BASS] = {AC97_MASTER_TONE, 15},
- [SOUND_MIXER_TREBLE] = {AC97_MASTER_TONE, 15},
- [SOUND_MIXER_SPEAKER] = {AC97_PCBEEP_VOL, 15},
- [SOUND_MIXER_MIC] = {AC97_MIC_VOL, 31},
- [SOUND_MIXER_LINE] = {AC97_LINEIN_VOL, 31},
- [SOUND_MIXER_CD] = {AC97_CD_VOL, 31},
- [SOUND_MIXER_VIDEO] = {AC97_VIDEO_VOL, 31},
- [SOUND_MIXER_LINE1] = {AC97_AUX_VOL, 31},
- [SOUND_MIXER_PCM] = {AC97_PCMOUT_VOL, 31},
- [SOUND_MIXER_IGAIN] = {AC97_RECORD_GAIN, 31}
-};
-
-#if 0 /* *shrug* removed simply because we never used it.
- feel free to implement again if needed */
-
-/* reads the given OSS mixer from the ac97
- the caller must have insured that the ac97 knows
- about that given mixer, and should be holding a
- spinlock for the card */
-static int ac97_read_mixer(struct trident_card *card, int mixer)
-{
- u16 val;
- int ret = 0;
- struct ac97_mixer_hw *mh = &ac97_hw[mixer];
-
- val = trident_ac97_get(card , mh->offset);
-
- if (AC97_STEREO_MASK & (1<<mixer)) {
- /* nice stereo mixers .. */
- int left,right;
-
- left = (val >> 8) & 0x7f;
- right = val & 0x7f;
-
- if (mixer == SOUND_MIXER_IGAIN) {
- right = (right * 100) / mh->scale;
- left = (left * 100) / mh->scale;
- else {
- right = 100 - ((right * 100) / mh->scale);
- left = 100 - ((left * 100) / mh->scale);
- }
-
- ret = left | (right << 8);
- } else if (mixer == SOUND_MIXER_SPEAKER) {
- ret = 100 - ((((val & 0x1e)>>1) * 100) / mh->scale);
- } else if (mixer == SOUND_MIXER_MIC) {
- ret = 100 - (((val & 0x1f) * 100) / mh->scale);
- /* the low bit is optional in the tone sliders and masking
- it lets us avoid the 0xf 'bypass'.. */
- } else if (mixer == SOUND_MIXER_BASS) {
- ret = 100 - ((((val >> 8) & 0xe) * 100) / mh->scale);
- } else if (mixer == SOUND_MIXER_TREBLE) {
- ret = 100 - (((val & 0xe) * 100) / mh->scale);
- }
+ trident_write_voice_regs(state, 1);
#ifdef DEBUG
- printk("trident: read OSS mixer %2d (ac97 register 0x%02x), "
- "0x%04x -> 0x%04x\n", mixer, mh->offset, val, ret);
+ printk("trident: called trident_set_adc_rate : rate = %d\n", rate);
#endif
-
- return ret;
+ return rate;
}
-#endif
-/* write the OSS encoded volume to the given OSS encoded mixer,
- again caller's job to make sure all is well in arg land,
- call with spinlock held */
-static void ac97_write_mixer(struct trident_card *card, int mixer,
- unsigned int left, unsigned int right)
+/* prepare channel attributes for playback */
+static void trident_play_setup(struct trident_state *state)
{
- u16 val = 0;
- struct ac97_mixer_hw *mh = &ac97_hw[mixer];
+ struct dmabuf *dmabuf = &state->dma_dac;
+ struct trident_channel *channel = dmabuf->channel;
-#ifdef DEBUG
- printk("trident: wrote OSS mixer %2d (ac97 register 0x%02x), "
- "left vol:%2d, right vol:%2d:",
- mixer, mh->offset, left, right);
-#endif
+ channel->lba = virt_to_bus(dmabuf->rawbuf);
+ channel->delta = compute_rate(dmabuf->rate);
- if (AC97_STEREO_MASK & (1 << mixer)) {
- /* stereo mixers */
- if (mixer == SOUND_MIXER_IGAIN) {
- right = (right * mh->scale) / 100;
- left = (left * mh->scale) / 100;
- } else {
- right = ((100 - right) * mh->scale) / 100;
- left = ((100 - left) * mh->scale) / 100;
- }
+ channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt];
+ channel->eso -= 1;
- val = (left << 8) | right;
- } else if (mixer == SOUND_MIXER_SPEAKER) {
- val = (((100 - left) * mh->scale) / 100) << 1;
- } else if (mixer == SOUND_MIXER_MIC) {
- val = trident_ac97_get(card , mh->offset) & ~0x801f;
- val |= (((100 - left) * mh->scale) / 100);
- /* the low bit is optional in the tone sliders and masking
- it lets us avoid the 0xf 'bypass'.. */
- } else if (mixer == SOUND_MIXER_BASS) {
- val = trident_ac97_get(card , mh->offset) & ~0x0f00;
- val |= ((((100 - left) * mh->scale) / 100) << 8) & 0x0e00;
- } else if (mixer == SOUND_MIXER_TREBLE) {
- val = trident_ac97_get(card , mh->offset) & ~0x000f;
- val |= (((100 - left) * mh->scale) / 100) & 0x000e;
+ if (state->card->pci_id == PCI_DEVICE_ID_SI_7018) {
+ /* FIXME: channel attributes are configured by ioctls, but it is not implemented
+ so just set to ZERO for the moment */
+ channel->attribute = 0;
+ } else {
+ channel->attribute = 0;
}
-#ifdef DEBUG
- printk(" 0x%04x", val);
-#endif
- trident_ac97_set(card, mh->offset, val);
-
-#ifdef DEBUG
- val = trident_ac97_get(card, mh->offset);
- printk(" -> 0x%04x\n", val);
-#endif
-}
-
-/* the following tables allow us to go from
- OSS <-> ac97 quickly. */
-
-enum ac97_recsettings {
- AC97_REC_MIC=0,
- AC97_REC_CD,
- AC97_REC_VIDEO,
- AC97_REC_AUX,
- AC97_REC_LINE,
- AC97_REC_STEREO, /* combination of all enabled outputs.. */
- AC97_REC_MONO, /*.. or the mono equivalent */
- AC97_REC_PHONE
-};
-
-static unsigned int ac97_rm2oss[] = {
- [AC97_REC_MIC] = SOUND_MIXER_MIC,
- [AC97_REC_CD] = SOUND_MIXER_CD,
- [AC97_REC_VIDEO] = SOUND_MIXER_VIDEO,
- [AC97_REC_AUX] = SOUND_MIXER_LINE1,
- [AC97_REC_LINE] = SOUND_MIXER_LINE,
- [AC97_REC_PHONE] = SOUND_MIXER_PHONEIN
-};
-
-/* indexed by bit position */
-static unsigned int ac97_oss_rm[] = {
- [SOUND_MIXER_MIC] = AC97_REC_MIC,
- [SOUND_MIXER_CD] = AC97_REC_CD,
- [SOUND_MIXER_VIDEO] = AC97_REC_VIDEO,
- [SOUND_MIXER_LINE1] = AC97_REC_AUX,
- [SOUND_MIXER_LINE] = AC97_REC_LINE,
- [SOUND_MIXER_PHONEIN] = AC97_REC_PHONE
-};
+ channel->fm_vol = 0x0;
-/* read or write the recmask
- the ac97 can really have left and right recording
- inputs independantly set, but OSS doesn't seem to
- want us to express that to the user.
- the caller guarantees that we have a supported bit set,
- and they must be holding the card's spinlock */
-static int ac97_recmask_io(struct trident_card *card, int rw, int mask)
-{
- unsigned int val;
-
- if (rw) {
- /* read it from the card */
- val = trident_ac97_get(card, 0x1a) & 0x7;
- return ac97_rm2oss[val];
- }
-
- /* else, write the first set in the mask as the
- output */
-
- val = ffs(mask);
- val = ac97_oss_rm[val-1];
- val |= val << 8; /* set both channels */
-#ifdef DEBUG
- printk("trident: setting ac97 recmask to 0x%x\n", val);
-#endif
- trident_ac97_set(card, 0x1a, val);
-
- return 0;
-};
-
-/* AC97 codec initialisation. */
-static u16 trident_ac97_init(struct trident_card *trident)
-{
- u16 id1, id2;
- char *ac97_name = NULL;
- int i;
-
- /* initialize controller side of AC link */
- switch (trident->pci_id)
- {
- case PCI_DEVICE_ID_SI_7018:
- /* disable AC97 GPIO interrupt */
- outl(0x00, TRID_REG(trident, SI_AC97_GPIO));
- /* stop AC97 cold reset process */
- outl(0x00014000, TRID_REG(trident, SI_SERIAL_INTF_CTRL));
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
- /* playback on */
- outl(0x02, TRID_REG(trident, DX_ACR2_AC97_COM_STAT));
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- /* enable AC97 Output Slot 3,4 (PCM Left/Right Playback) */
- outl(0x02, TRID_REG(trident, NX_ACR0_AC97_COM_STAT));
- break;
- }
-
- /* get some information about our AC97 codec */
- id1 = trident_ac97_get(trident, AC97_VENDOR_ID1);
- id2 = trident_ac97_get(trident, AC97_VENDOR_ID2);
- for (i = 0; i < sizeof (snd_ac97_codec_ids); i++) {
- if (snd_ac97_codec_ids[i].id == ((id1 << 16) | id2)) {
- ac97_name = snd_ac97_codec_ids[i].name;
- break;
- }
- }
- if (ac97_name == NULL)
- ac97_name = "Unknown";
- printk(KERN_INFO "trident: ac97 vendor id1: 0x%04x, id2: 0x%04x (%s)\n",
- id1, id2, ac97_name);
-
- /* initialize volume level */
- trident_ac97_set(trident, AC97_RESET, 0L);
- trident_ac97_set(trident, AC97_MASTER_VOL_STEREO, 0L);
- trident_ac97_set(trident, AC97_PCMOUT_VOL, 0L);
-
- /* set appropriate masks and function pointers */
- trident->mix.supported_mixers = AC97_SUPPORTED_MASK;
- trident->mix.stereo_mixers = AC97_STEREO_MASK;
- trident->mix.record_sources = AC97_RECORD_MASK;
- /* FIXME: trident->mix.read_mixer = ac97_read_mixer; */
- trident->mix.write_mixer = ac97_write_mixer;
- trident->mix.recmask_io = ac97_recmask_io;
-
- return 0;
-}
-
-/* this function only update fmt field in trident_state, the hardware channel attribute
- will be update in trident_play(rec)_setup() which will be called every time a new
- sample is played(recorded) */
-static void set_fmt(struct trident_state *s, unsigned char mask, unsigned char data)
-{
- s->fmt = (s->fmt & mask) | data;
-}
-
-/* the mode passed should be already shifted and masked */
-/* trident_play_setup: initialize channel for play back, mode specify the format of samples to
- be played.
- default values:
-*/
-
-static void trident_play_setup(struct trident_state *trident, int mode, u32 rate,
- void *buffer, int size)
-{
- unsigned int LBA;
- unsigned int Delta;
- unsigned int ESO;
- unsigned int CTRL;
- unsigned int FMC_RVOL_CVOL;
- unsigned int GVSEL;
- unsigned int PAN;
- unsigned int VOL;
- unsigned int EC;
-
- /* set Loop Begin Address */
- LBA = virt_to_bus(buffer);
- Delta = compute_rate(rate);
-
- /* set ESO */
- ESO = size;
- if (mode & TRIDENT_FMT_16BIT)
- ESO /= 2;
- if (mode & TRIDENT_FMT_STEREO)
- ESO /= 2;
- ESO = ESO - 1;
-
- /* loop mode enable */
- CTRL = 0x00000001;
- if (mode & TRIDENT_FMT_16BIT) {
+ channel->control = CHANNEL_LOOP;
+ if (dmabuf->fmt & TRIDENT_FMT_16BIT) {
/* 16-bits */
- CTRL |= 0x00000008;
+ channel->control |= CHANNEL_16BITS;
/* signed */
- CTRL |= 0x00000002;
+ channel->control |= CHANNEL_SIGNED;
}
- if (mode & TRIDENT_FMT_STEREO)
+ if (dmabuf->fmt & TRIDENT_FMT_STEREO)
/* stereo */
- CTRL |= 0x00000004;
-
- /* FIXME: some difference between 4D and 7018 in FMC_RVOL_CVOL */
- /* right vol: mute, ledt vol: mute */
- FMC_RVOL_CVOL = 0x0000ffff;
- GVSEL = 1;
- PAN = 0;
- VOL = 0;
- EC = 0;
-
- trident_write_voice_regs(trident->card,
- trident->dma_dac.chan,
- LBA,
- 0, /* cso */
- ESO,
- Delta,
- 0, /* alpha */
- FMC_RVOL_CVOL,
- GVSEL,
- PAN,
- VOL,
- CTRL,
- EC);
-
+ channel->control |= CHANNEL_STEREO;
+#ifdef DEBUG
+ printk("trident: trident_play_setup, LBA = 0x%08x, "
+ "Delat = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n",
+ channel->lba, channel->delta, channel->eso, channel->control);
+#endif
+ trident_write_voice_regs(state, 0);
}
-/*
- * Native record driver
- */
-/* FIXME: Not exammed yet */
-/* again, passed mode is alrady shifted/masked */
-
-static void trident_rec_setup(struct trident_state *trident, int mode, u32 rate,
- void *buffer, int size)
+/* prepare channel attributes for recording */
+static void trident_rec_setup(struct trident_state *state)
{
- unsigned int LBA;
- unsigned int Delta;
- unsigned int ESO;
- unsigned int CTRL;
- unsigned int FMC_RVOL_CVOL;
- unsigned int GVSEL;
- unsigned int PAN;
- unsigned int VOL;
- unsigned int EC;
- unsigned char bValue;
- unsigned short wValue;
- unsigned int dwValue;
- unsigned short wRecCODECSamples;
- unsigned int dwChanFlags;
- struct trident_card *card = trident->card;
-
-#ifdef DEBUG
- printk("trident: trident_rec_setup called\n");
-#endif
+ u16 w;
+ struct trident_card *card = state->card;
+ struct dmabuf *dmabuf = &state->dma_adc;
+ struct trident_channel *channel = dmabuf->channel;
- // Enable AC-97 ADC (capture), disable capture interrupt
+ /* Enable AC-97 ADC (capture) */
switch (card->pci_id)
{
case PCI_DEVICE_ID_SI_7018:
/* for 7018, the ac97 is always in playback/record (duplex) mode */
break;
case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
- bValue = inb(TRID_REG(card, DX_ACR2_AC97_COM_STAT));
- outb(bValue | 0x48, TRID_REG(card, DX_ACR2_AC97_COM_STAT));
+ w = inb(TRID_REG(card, DX_ACR2_AC97_COM_STAT));
+ outb(w | 0x48, TRID_REG(card, DX_ACR2_AC97_COM_STAT));
break;
case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- wValue = inw(TRID_REG(card, T4D_MISCINT));
- outw(wValue | 0x1000, TRID_REG(card, T4D_MISCINT));
+ w = inw(TRID_REG(card, T4D_MISCINT));
+ outw(w | 0x1000, TRID_REG(card, T4D_MISCINT));
break;
+ default:
+ return;
}
- // Initilize the channel and set channel Mode
- outb(0, TRID_REG(card, LEGACY_DMAR15));
-
- // Set DMA channel operation mode register
- bValue = inb(TRID_REG(card, LEGACY_DMAR11)) & 0x03;
- outb(bValue | 0x54, TRID_REG(card, LEGACY_DMAR11));
-
- // Set channel buffer Address
- LBA = virt_to_bus(buffer);
- outl(LBA, TRID_REG(card, LEGACY_DMAR0));
-
- /* set ESO */
- ESO = size;
+ channel->lba = virt_to_bus(dmabuf->rawbuf);
+ channel->delta = compute_rate(dmabuf->rate);
- dwValue = inl(TRID_REG(card, LEGACY_DMAR4)) & 0xff000000;
- dwValue |= (ESO - 1) & 0x0000ffff;
- outl(dwValue, TRID_REG(card, LEGACY_DMAR4));
+ channel->eso = dmabuf->dmasize >> sample_shift[dmabuf->fmt];
+ channel->eso -= 1;
- // Set channel sample rate , 4.12 format
- dwValue = (((unsigned int) 48000L << 12) / (unsigned long) (rate));
- outw((unsigned short) dwValue, TRID_REG(card, T4D_SBDELTA_DELTA_R));
-
- // Set channel interrupt blk length
- if (mode & TRIDENT_FMT_16BIT) {
- wRecCODECSamples = (unsigned short) ((ESO >> 1) - 1);
- dwChanFlags = 0xffffb000;
+ if (state->card->pci_id == PCI_DEVICE_ID_SI_7018) {
+ /* FIXME: channel attributes are configured by ioctls, but it is not implemented
+ so just set to ZERO for the moment */
+ channel->attribute = 0;
} else {
- wRecCODECSamples = (unsigned short) (ESO - 1);
- dwChanFlags = 0xffff1000;
+ channel->attribute = 0;
}
- dwValue = ((unsigned int) wRecCODECSamples) << 16;
- dwValue |= (unsigned int) (wRecCODECSamples) & 0x0000ffff;
- outl(dwValue, TRID_REG(card, T4D_SBBL_SBCL));
-
- // Right now, set format and start to run capturing,
- // continuous run loop enable.
- trident->bDMAStart = 0x19; // 0001 1001b
-
- if (mode & TRIDENT_FMT_16BIT)
- trident->bDMAStart |= 0xa0;
- if (mode & TRIDENT_FMT_STEREO)
- trident->bDMAStart |= 0x40;
-
- // Prepare capture intr channel
-
- Delta = ((((unsigned int) rate) << 12) / ((unsigned long) (48000L)));
-
- /* set Loop Back Address */
- LBA = virt_to_bus(buffer);
-
- /* set ESO */
- ESO = size;
- if (mode & TRIDENT_FMT_16BIT)
- ESO /= 2;
- if (mode & TRIDENT_FMT_STEREO)
- ESO /= 2;
-
- ESO = ESO - 1;
- //snd_printk("trid: ESO = %d\n", ESO);
-
- /* set ctrl mode
- CTRL default: 8-bit (unsigned) mono, loop mode enabled
- */
- CTRL = 0x00000001;
- if (mode & TRIDENT_FMT_16BIT)
- CTRL |= 0x00000008; // 16-bit data
- /* XXX DO UNSIGNED XXX */
- //if (!(mode & SND_PCM1_MODE_U))
- // CTRL |= 0x00000002; // signed data
- if (mode& TRIDENT_FMT_STEREO)
- CTRL |= 0x00000004; // stereo data
-
- FMC_RVOL_CVOL = 0x0000ffff;
- GVSEL = 1;
- PAN = 0xff;
- VOL = 0xff;
- EC = 0;
-
- trident_write_voice_regs(card,
- trident->dma_adc.chan,
- LBA,
- 0, /* cso */
- ESO,
- Delta,
- 0, /* alpha */
- FMC_RVOL_CVOL,
- GVSEL,
- PAN,
- VOL,
- CTRL,
- EC);
-
+ channel->fm_vol = 0x0;
+
+ channel->control = CHANNEL_LOOP;
+ if (dmabuf->fmt & TRIDENT_FMT_16BIT) {
+ /* 16-bits */
+ channel->control |= CHANNEL_16BITS;
+ /* signed */
+ channel->control |= CHANNEL_SIGNED;
+ }
+ if (dmabuf->fmt & TRIDENT_FMT_STEREO)
+ /* stereo */
+ channel->control |= CHANNEL_STEREO;
+#ifdef DEBUG
+ printk("trident: trident_rec_setup, LBA = 0x%08x, "
+ "Delat = 0x%08x, ESO = 0x%08x, Control = 0x%08x\n",
+ channel->lba, channel->delta, channel->eso, channel->control);
+#endif
+ trident_write_voice_regs(state, 1);
}
-/* get current playback pointer */
-__inline__ unsigned int get_dmaa(struct trident_state *trident)
+/* get current playback/recording dma buffer pointer (byte offset from LBA),
+ called with spinlock held! */
+extern __inline__ unsigned trident_get_dma_addr(struct trident_state *state, unsigned rec)
{
+ struct dmabuf *dmabuf;
u32 cso;
- u32 eso;
-#if 0
- /* FIXME: does this mean that FULL duplex is not supported ? */
- if (!(trident->enable & ADC_RUNNING))
+
+ if (rec)
+ dmabuf = &state->dma_adc;
+ else
+ dmabuf = &state->dma_dac;
+
+ if (!dmabuf->enable)
return 0;
-#endif
- outb(trident->dma_dac.chan, TRID_REG(trident->card, T4D_LFO_GC_CIR));
- switch (trident->card->pci_id)
+ outb(dmabuf->channel->num, TRID_REG(state->card, T4D_LFO_GC_CIR));
+
+ switch (state->card->pci_id)
{
case PCI_DEVICE_ID_SI_7018:
case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
/* 16 bits ESO, CSO for 7018 and DX */
- cso = inw(TRID_REG(trident->card, CH_DX_CSO_ALPHA_FMS + 2));
- eso = inw(TRID_REG(trident->card, CH_DX_ESO_DELTA + 2));
+ cso = inw(TRID_REG(state->card, CH_DX_CSO_ALPHA_FMS + 2));
break;
case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
/* 24 bits ESO, CSO for NX */
- cso = inl(TRID_REG(trident->card, CH_NX_DELTA_CSO)) & 0x00ffffff;
- eso = inl(TRID_REG(trident->card, CH_NX_DELTA_ESO)) & 0x00ffffff;
+ cso = inl(TRID_REG(state->card, CH_NX_DELTA_CSO)) & 0x00ffffff;
break;
default:
return 0;
}
#ifdef DEBUG
- printk("trident: get_dmaa: chip reported channel: %d, cso = %d, eso = %d\n",
- trident->dma_dac.chan, cso, eso);
+ printk("trident: trident_get_dma_addr: chip reported channel: %d, cso = %d\n",
+ dmabuf->channel->num, cso);
#endif
/* ESO and CSO are in units of Samples, convert to byte offset */
- if (cso > eso)
- cso = eso;
- if (trident->fmt & TRIDENT_FMT_16BIT)
- cso *= 2;
- if (trident->fmt & TRIDENT_FMT_STEREO)
- cso *= 2;
- return cso;
+ cso <<= sample_shift[dmabuf->fmt];
+
+ return (cso % dmabuf->dmasize);
}
-/* get current recording pointer */
-extern __inline__ unsigned get_dmac(struct trident_state *trident)
+/* Stop recording (lock held) */
+extern __inline__ void __stop_adc(struct trident_state *state)
{
- u32 cso;
-#if 0
- /* FIXME: does this mean that FULL duplex is not supported ? */
- if (!(trident->enable & DAC_RUNNING))
- return 0;
-#endif
- outb(trident->dma_adc.chan, TRID_REG(trident->card, T4D_LFO_GC_CIR));
+ struct dmabuf *dmabuf = &state->dma_adc;
+ unsigned int chan_num = dmabuf->channel->num;
+ struct trident_card *card = state->card;
- switch (trident->card->pci_id)
- {
- default:
- case PCI_DEVICE_ID_SI_7018:
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
- /* 16 bits ESO, CSO for 7018 and DX */
- cso = inw(TRID_REG(trident->card, CH_DX_CSO_ALPHA_FMS + 2));
- break;
- case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- /* 24 bits ESO, CSO for NX */
- cso = inl(TRID_REG(trident->card, CH_NX_DELTA_CSO)) & 0x00ffffff;
- break;
- }
-
-#ifdef DEBUG
- printk("(trident) get_dmac: chip reported cso = %d\n", cso);
-#endif
- /* ESO and CSO are in units of Samples, convert to byte offset */
- if (trident->fmt & TRIDENT_FMT_16BIT)
- cso *= 2;
- if (trident->fmt & TRIDENT_FMT_STEREO)
- cso *= 2;
- return cso;
+ dmabuf->enable &= ~DMA_RUNNING;
+ trident_stop_voice(card, chan_num);
+ trident_disable_voice_irq(card, chan_num);
}
-/* Stop recording (lock held) */
-extern inline void __stop_adc(struct trident_state *s)
+static void stop_adc(struct trident_state *state)
{
- struct trident_card *trident = s->card;
-#ifdef DEBUG
- printk("(trident) stopping ADC\n");
-#endif
- s->enable &= ~ADC_RUNNING;
- trident_disable_voice_irq(trident, s->dma_adc.chan);
- outb(0x00, TRID_REG(trident, T4D_SBCTRL_SBE2R_SBDD));
- trident_disable_voice_irq(trident, s->dma_adc.chan);
- trident_stop_voice(trident, s->dma_adc.chan);
- ResetAinten(trident, s->dma_adc.chan);
-}
+ struct trident_card *card = state->card;
+ unsigned long flags;
+
+ spin_lock_irqsave(&card->lock, flags);
+ __stop_adc(state);
+ spin_unlock_irqrestore(&card->lock, flags);
+}
-extern inline void stop_adc(struct trident_state *s)
+static void start_adc(struct trident_state *state)
{
+ struct dmabuf *dmabuf = &state->dma_adc;
+ unsigned int chan_num = dmabuf->channel->num;
+ struct trident_card *card = state->card;
unsigned long flags;
- struct trident_card *trident = s->card;
- spin_lock_irqsave(&trident->lock, flags);
- __stop_adc(s);
- spin_unlock_irqrestore(&trident->lock, flags);
-}
+ spin_lock_irqsave(&card->lock, flags);
+ if ((dmabuf->mapped ||
+ dmabuf->count < (signed)(dmabuf->dmasize - 2*dmabuf->fragsize))
+ && dmabuf->ready) {
+ dmabuf->enable |= DMA_RUNNING;
+ trident_enable_voice_irq(card, chan_num);
+ trident_start_voice(card, chan_num);
+ }
+ spin_unlock_irqrestore(&card->lock, flags);
+}
/* stop playback (lock held) */
-extern inline void __stop_dac(struct trident_state *state)
+extern __inline__ void __stop_dac(struct trident_state *state)
{
- struct trident_card *trident = state->card;
- trident_stop_voice(trident, state->dma_dac.chan);
- trident_disable_voice_irq(trident, state->dma_dac.chan);
- state->enable &= ~DAC_RUNNING;
-}
+ struct dmabuf *dmabuf = &state->dma_dac;
+ unsigned int chan_num = dmabuf->channel->num;
+ struct trident_card *card = state->card;
-extern inline void stop_dac(struct trident_state *state)
+ dmabuf->enable &= ~DMA_RUNNING;
+ trident_stop_voice(card, chan_num);
+ trident_disable_voice_irq(card, chan_num);
+}
+
+static void stop_dac(struct trident_state *state)
{
- struct trident_card *trident = state->card;
+ struct trident_card *card = state->card;
unsigned long flags;
- spin_lock_irqsave(&trident->lock, flags);
+ spin_lock_irqsave(&card->lock, flags);
__stop_dac(state);
- spin_unlock_irqrestore(&trident->lock, flags);
+ spin_unlock_irqrestore(&card->lock, flags);
}
static void start_dac(struct trident_state *state)
{
+ struct dmabuf *dmabuf = &state->dma_dac;
+ unsigned int chan_num = dmabuf->channel->num;
+ struct trident_card *card = state->card;
unsigned long flags;
- struct trident_card *trident = state->card;
- spin_lock_irqsave(&state->card->lock, flags);
- if ((state->dma_dac.mapped || state->dma_dac.count > 0) && state->dma_dac.ready) {
- state->enable |= DAC_RUNNING;
- trident_enable_voice_irq(trident, state->dma_dac.chan);
- trident_start_voice(trident, state->dma_dac.chan);
+ spin_lock_irqsave(&card->lock, flags);
+ if ((dmabuf->mapped || dmabuf->count > 0) && dmabuf->ready) {
+ dmabuf->enable |= DMA_RUNNING;
+ trident_enable_voice_irq(card, chan_num);
+ trident_start_voice(card, chan_num);
}
- spin_unlock_irqrestore(&state->card->lock, flags);
-}
-
-static void start_adc(struct trident_state *s)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&s->card->lock, flags);
- if ((s->dma_adc.mapped || s->dma_adc.count < (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize))
- && s->dma_adc.ready) {
- s->enable |= ADC_RUNNING;
- trident_enable_voice_irq(s->card, s->dma_adc.chan);
- outb(s->bDMAStart, TRID_REG(s->card, T4D_SBCTRL_SBE2R_SBDD));
- trident_start_voice(s->card, s->dma_adc.chan);
-#ifdef DEBUG
- printk("(trident) starting ADC\n");
-#endif
- }
- spin_unlock_irqrestore(&s->card->lock, flags);
-}
+ spin_unlock_irqrestore(&card->lock, flags);
+}
#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)
#define DMABUF_MINORDER 1
@@ -1623,10 +823,16 @@ static void start_adc(struct trident_state *s)
/* allocate DMA buffer, playback and recording buffer should be allocated seperately */
static int alloc_dmabuf(struct trident_state *state, unsigned rec)
{
+ struct dmabuf *dmabuf;
void *rawbuf;
int order;
unsigned long map, mapend;
+ if (rec)
+ dmabuf = &state->dma_adc;
+ else
+ dmabuf = &state->dma_dac;
+
/* alloc as big a chunk as we can, FIXME: is this necessary ?? */
for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)
if ((rawbuf = (void *)__get_free_pages(GFP_KERNEL, order)))
@@ -1634,7 +840,7 @@ static int alloc_dmabuf(struct trident_state *state, unsigned rec)
if (!rawbuf)
return -ENOMEM;
#ifdef DEBUG
- printk("trident: allocated %ld (%d) bytes at %p\n",
+ printk("trident: allocated %ld (order = %d) bytes at %p\n",
PAGE_SIZE << order, order, rawbuf);
#endif
@@ -1648,17 +854,10 @@ static int alloc_dmabuf(struct trident_state *state, unsigned rec)
return -ENOMEM;
}
- if (rec) {
- state->dma_adc.ready = state->dma_adc.mapped = 0;
- state->dma_adc.rawbuf = rawbuf;
- state->dma_adc.buforder = order;
- }
- else {
- state->dma_dac.ready = state->dma_dac.mapped = 0;
- state->dma_dac.rawbuf = rawbuf;
- state->dma_dac.buforder = order;
- }
-
+ dmabuf->ready = dmabuf->mapped = 0;
+ dmabuf->rawbuf = rawbuf;
+ dmabuf->buforder = order;
+
/* now mark the pages as reserved; otherwise remap_page_range doesn't do what we want */
mapend = MAP_NR(rawbuf + (PAGE_SIZE << order) - 1);
for (map = MAP_NR(rawbuf); map <= mapend; map++)
@@ -1668,180 +867,237 @@ static int alloc_dmabuf(struct trident_state *state, unsigned rec)
}
/* free DMA buffer */
-static void dealloc_dmabuf(struct dmabuf *db)
+static void dealloc_dmabuf(struct dmabuf *dmabuf)
{
unsigned long map, mapend;
- if (db->rawbuf) {
+ if (dmabuf->rawbuf) {
/* undo marking the pages as reserved */
- mapend = MAP_NR(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
- for (map = MAP_NR(db->rawbuf); map <= mapend; map++)
+ mapend = MAP_NR(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1);
+ for (map = MAP_NR(dmabuf->rawbuf); map <= mapend; map++)
clear_bit(PG_reserved, &mem_map[map].flags);
- free_pages((unsigned long)db->rawbuf, db->buforder);
+ free_pages((unsigned long)dmabuf->rawbuf, dmabuf->buforder);
}
- db->rawbuf = NULL;
- db->mapped = db->ready = 0;
+ dmabuf->rawbuf = NULL;
+ dmabuf->mapped = dmabuf->ready = 0;
}
static int prog_dmabuf(struct trident_state *state, unsigned rec)
{
- struct dmabuf *db = rec ? &state->dma_adc : &state->dma_dac;
- unsigned rate = rec ? state->rateadc : state->ratedac;
+ struct dmabuf *dmabuf;
unsigned bytepersec;
- unsigned bufs;
- unsigned char fmt;
+ unsigned bufsize;
unsigned long flags;
int ret;
+ if (rec)
+ dmabuf = &state->dma_adc;
+ else
+ dmabuf = &state->dma_dac;
+
spin_lock_irqsave(&state->card->lock, flags);
- fmt = state->fmt;
- if (rec) {
- state->enable &= ~TRIDENT_ENABLE_RE;
- fmt >>= TRIDENT_ADC_SHIFT;
- } else {
- state->enable &= ~TRIDENT_ENABLE_PE;
- fmt >>= TRIDENT_DAC_SHIFT;
- }
+ dmabuf->hwptr = dmabuf->swptr = dmabuf->total_bytes = 0;
+ dmabuf->count = dmabuf->error = dmabuf->endcleared = 0;
spin_unlock_irqrestore(&state->card->lock, flags);
- fmt &= TRIDENT_FMT_MASK;
-
- db->hwptr = db->swptr = db->total_bytes = 0;
- db->count = db->error = db->endcleared = 0;
-
/* allocate DMA buffer if not allocated yet */
- if (!db->rawbuf)
+ if (!dmabuf->rawbuf)
if ((ret = alloc_dmabuf(state, rec)))
return ret;
- bytepersec = rate << sample_shift[fmt];
- bufs = PAGE_SIZE << db->buforder;
- if (db->ossfragshift) {
- if ((1000 << db->ossfragshift) < bytepersec)
- db->fragshift = ld2(bytepersec/1000);
+ /* FIXME: figure out all this OSS fragment stuff */
+ bytepersec = dmabuf->rate << sample_shift[dmabuf->fmt];
+ bufsize = PAGE_SIZE << dmabuf->buforder;
+ if (dmabuf->ossfragshift) {
+ if ((1000 << dmabuf->ossfragshift) < bytepersec)
+ dmabuf->fragshift = ld2(bytepersec/1000);
else
- db->fragshift = db->ossfragshift;
+ dmabuf->fragshift = dmabuf->ossfragshift;
} else {
/* lets hand out reasonable big ass buffers by default */
- db->fragshift = (db->buforder + PAGE_SHIFT -2);
+ dmabuf->fragshift = (dmabuf->buforder + PAGE_SHIFT -2);
}
- db->numfrag = bufs >> db->fragshift;
- while (db->numfrag < 4 && db->fragshift > 3) {
- db->fragshift--;
- db->numfrag = bufs >> db->fragshift;
+ dmabuf->numfrag = bufsize >> dmabuf->fragshift;
+ while (dmabuf->numfrag < 4 && dmabuf->fragshift > 3) {
+ dmabuf->fragshift--;
+ dmabuf->numfrag = bufsize >> dmabuf->fragshift;
}
- db->fragsize = 1 << db->fragshift;
- if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag)
- db->numfrag = db->ossmaxfrags;
- db->fragsamples = db->fragsize >> sample_shift[fmt];
- db->dmasize = db->numfrag << db->fragshift;
+ dmabuf->fragsize = 1 << dmabuf->fragshift;
+ if (dmabuf->ossmaxfrags >= 4 && dmabuf->ossmaxfrags < dmabuf->numfrag)
+ dmabuf->numfrag = dmabuf->ossmaxfrags;
+ dmabuf->fragsamples = dmabuf->fragsize >> sample_shift[dmabuf->fmt];
+ dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift;
- memset(db->rawbuf, (fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80, db->dmasize);
+ memset(dmabuf->rawbuf, (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80,
+ dmabuf->dmasize);
spin_lock_irqsave(&state->card->lock, flags);
if (rec) {
- trident_rec_setup(state, fmt, state->rateadc,
- db->rawbuf, db->numfrag << db->fragshift);
+ trident_rec_setup(state);
} else {
- trident_play_setup(state, fmt, state->ratedac,
- db->rawbuf, db->numfrag << db->fragshift);
+ trident_play_setup(state);
}
spin_unlock_irqrestore(&state->card->lock, flags);
/* set the ready flag for the dma buffer */
- db->ready = 1;
+ dmabuf->ready = 1;
#ifdef DEBUG
printk("trident: prog_dmabuf, sample rate = %d, format = %d, numfrag = %d, "
"fragsize = %d dmasize = %d\n",
- rate, fmt, db->numfrag, db->fragsize, db->dmasize);
+ dmabuf->rate, dmabuf->fmt, dmabuf->numfrag,
+ dmabuf->fragsize, dmabuf->dmasize);
#endif
return 0;
}
-extern __inline__ void clear_advance(struct trident_state *s)
+/* we are doing quantum mechanics here, the buffer can only be empty, half or full filled i.e.
+ |------------|------------| or |xxxxxxxxxxxx|------------| or |xxxxxxxxxxxx|xxxxxxxxxxxx|
+ but we almost always get this
+ |xxxxxx------|------------| or |xxxxxxxxxxxx|xxxxx-------|
+ so we have to clear the tail space to "silence"
+ |xxxxxx000000|------------| or |xxxxxxxxxxxx|xxxxxx000000|
+*/
+static void trident_clear_tail(struct trident_state *state)
{
- unsigned char c = ((s->fmt >> TRIDENT_DAC_SHIFT) & TRIDENT_FMT_16BIT) ? 0 : 0x80;
- unsigned char *buf = s->dma_dac.rawbuf;
- unsigned bsize = s->dma_dac.dmasize;
- unsigned bptr = s->dma_dac.swptr;
- unsigned len = s->dma_dac.fragsize;
-
- if (bptr + len > bsize) {
- unsigned x = bsize - bptr;
- memset(buf + bptr, c, x);
- /* account for wrapping? */
- bptr = 0;
- len -= x;
+ struct dmabuf *dmabuf = &state->dma_dac;
+ unsigned swptr;
+ unsigned char silence = (dmabuf->fmt & TRIDENT_FMT_16BIT) ? 0 : 0x80;
+ unsigned int len;
+ unsigned long flags;
+
+ spin_lock_irqsave(&state->card->lock, flags);
+ swptr = dmabuf->swptr;
+ spin_unlock_irqrestore(&state->card->lock, flags);
+
+ if (swptr == 0 || swptr == dmabuf->dmasize / 2 || swptr == dmabuf->dmasize)
+ return;
+
+
+ if (swptr < dmabuf->dmasize/2)
+ len = dmabuf->dmasize/2 - swptr;
+ else
+ len = dmabuf->dmasize - swptr;
+
+ memset(dmabuf->rawbuf + swptr, silence, len);
+
+ spin_lock_irqsave(&state->card->lock, flags);
+ dmabuf->swptr += len;
+ dmabuf->count += len;
+ spin_unlock_irqrestore(&state->card->lock, flags);
+
+ /* restart the dma machine in case it is halted */
+ start_dac(state);
+}
+
+static int drain_dac(struct trident_state *state, int nonblock)
+{
+ DECLARE_WAITQUEUE(wait, current);
+ struct dmabuf *dmabuf = &state->dma_dac;
+ unsigned long flags;
+ unsigned long tmo;
+ int count;
+
+ if (dmabuf->mapped || !dmabuf->ready)
+ return 0;
+
+ add_wait_queue(&dmabuf->wait, &wait);
+ for (;;) {
+ /* It seems that we have to set the current state to TASK_INTERRUPTIBLE
+ every time to make the process really go to sleep */
+ current->state = TASK_INTERRUPTIBLE;
+
+ spin_lock_irqsave(&state->card->lock, flags);
+ count = dmabuf->count;
+ spin_unlock_irqrestore(&state->card->lock, flags);
+
+ if (count <= 0)
+ break;
+
+ if (signal_pending(current))
+ break;
+
+ if (nonblock) {
+ remove_wait_queue(&dmabuf->wait, &wait);
+ current->state = TASK_RUNNING;
+ return -EBUSY;
+ }
+
+ /* No matter how much data left in the buffer, we have to wait untill
+ CSO == ESO/2 or CSO == ESO when address engine interrupts */
+ tmo = (dmabuf->dmasize * HZ) / dmabuf->rate;
+ tmo >>= sample_shift[dmabuf->fmt];
+ if (!schedule_timeout(tmo ? tmo : 1) && tmo){
+ printk(KERN_ERR "trident: drain_dac, dma timeout?\n");
+ break;
+ }
}
- memset(buf + bptr, c, len);
+ remove_wait_queue(&dmabuf->wait, &wait);
+ current->state = TASK_RUNNING;
+ if (signal_pending(current))
+ return -ERESTARTSYS;
+
+ return 0;
}
/* call with spinlock held! */
-static void trident_update_ptr(struct trident_state *s)
+static void trident_update_ptr(struct trident_state *state)
{
+ struct dmabuf *dmabuf;
unsigned hwptr;
int diff;
/* update ADC pointer */
- if (s->dma_adc.ready) {
- hwptr = get_dmac(s) % s->dma_adc.dmasize;
- diff = (s->dma_adc.dmasize + hwptr - s->dma_adc.hwptr) %
- s->dma_adc.dmasize;
- s->dma_adc.hwptr = hwptr;
- s->dma_adc.total_bytes += diff;
- s->dma_adc.count += diff;
- if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
- wake_up(&s->dma_adc.wait);
- if (!s->dma_adc.mapped) {
- if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) {
- s->enable &= ~TRIDENT_ENABLE_RE;
- __stop_adc(s);
- s->dma_adc.error++;
+ if (state->dma_adc.ready) {
+ dmabuf = &state->dma_adc;
+ hwptr = trident_get_dma_addr(state, 1);
+ diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
+
+ dmabuf->hwptr = hwptr;
+ dmabuf->total_bytes += diff;
+ dmabuf->count += diff;
+
+ if (dmabuf->count >= (signed)dmabuf->fragsize)
+ wake_up(&dmabuf->wait);
+ if (!dmabuf->mapped) {
+ if (dmabuf->count > (signed)(dmabuf->dmasize - ((3 * dmabuf->fragsize) >> 1))) {
+ __stop_adc(state);
+ dmabuf->error++;
}
}
}
/* update DAC pointer */
- if (s->dma_dac.ready) {
- hwptr = get_dmaa(s) % s->dma_dac.dmasize;
- diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) %
- s->dma_dac.dmasize;
- s->dma_dac.hwptr = hwptr;
- s->dma_dac.total_bytes += diff;
- if (s->dma_dac.mapped) {
- s->dma_dac.count += diff;
- if (s->dma_dac.count >= (signed)s->dma_dac.fragsize)
- wake_up(&s->dma_dac.wait);
- }
+ if (state->dma_dac.ready) {
+ dmabuf = &state->dma_dac;
+ hwptr = trident_get_dma_addr(state, 0);
+ diff = (dmabuf->dmasize + hwptr - dmabuf->hwptr) % dmabuf->dmasize;
+
+ dmabuf->hwptr = hwptr;
+ dmabuf->total_bytes += diff;
+
+ if (dmabuf->mapped) {
+ dmabuf->count += diff;
+ if (dmabuf->count >= (signed)dmabuf->fragsize)
+ wake_up(&dmabuf->wait);
+ }
else {
- s->dma_dac.count -= diff;
- if (s->dma_dac.count <= 0) {
- s->enable &= ~TRIDENT_ENABLE_PE;
- /* Lock already held */
- __stop_dac(s);
- /* brute force everyone back in sync, sigh */
- s->dma_dac.count = 0;
- s->dma_dac.swptr = 0;
- s->dma_dac.hwptr = 0;
- s->dma_dac.error++;
- }
- else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize &&
- !s->dma_dac.endcleared) {
- clear_advance(s);
- s->dma_dac.endcleared = 1;
+ dmabuf->count -= diff;
+ if (dmabuf->count < 0 || dmabuf->count > dmabuf->dmasize) {
+ /* buffer underrun or buffer overrun, we have no way to recover
+ it here, just stop the machine and let the process force hwptr
+ and swptr to sync */
+ __stop_dac(state);
+ dmabuf->error++;
}
-
- if (s->dma_dac.count + (signed)s->dma_dac.fragsize <= (signed)s->dma_dac.dmasize)
- wake_up(&s->dma_dac.wait);
+ /* since dma machine only interrupts at ESO and ESO/2, we sure have at
+ least half of dma buffer free, so wake up the process unconditionally */
+ wake_up(&dmabuf->wait);
}
}
}
-/*
- * Trident interrupt handlers.
- */
static void trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct trident_state *state;
@@ -1858,19 +1114,17 @@ static void trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (event & ADDRESS_IRQ) {
/* Update the pointers for all channels we are running. */
- /* FIXME: improve interrupt latency !!! */
- for (i = 0; i < NR_DSPS; i++) {
- state = card->channels[i];
+ /* FIXME: should read interrupt status only once */
+ for (i = 0; i < NR_HW_CH; i++) {
if (trident_check_channel_interrupt(card, 63 - i)) {
trident_ack_channel_interrupt(card, 63 - i);
- if (state != NULL)
+ if ((state = card->states[i]) != NULL) {
trident_update_ptr(state);
- else {
- /* Spurious ? */
- printk("trident: spurious channel irq %d.\n",
+ } else {
+ printk("trident: spurious channel irq %d.\n",
63 - i);
trident_stop_voice(card, i);
- trident_disable_voice_irq(card, i);
+ trident_disable_voice_irq(card, i);
}
}
}
@@ -1886,254 +1140,29 @@ static void trident_interrupt(int irq, void *dev_id, struct pt_regs *regs)
spin_unlock(&card->lock);
}
-static void set_mixer(struct trident_card *card,unsigned int mixer, unsigned int val )
-{
- unsigned int left,right;
-
- /* cleanse input a little */
- right = ((val >> 8) & 0xff) ;
- left = (val & 0xff) ;
-
- if (right > 100) right = 100;
- if (left > 100) left = 100;
-
- card->mix.mixer_state[mixer] = (right << 8) | left;
- card->mix.write_mixer(card, mixer, left, right);
-}
-
-static int mixer_ioctl(struct trident_card *card, unsigned int cmd, unsigned long arg)
-{
- unsigned long flags;
- int i, val = 0;
-
- VALIDATE_CARD(card);
- if (cmd == SOUND_MIXER_INFO) {
- mixer_info info;
- strncpy(info.id, card->pci_info->name, sizeof(info.id));
- strncpy(info.name, card->pci_info->name, sizeof(info.name));
- info.modify_counter = card->mix.modcnt;
- if (copy_to_user((void *)arg, &info, sizeof(info)))
- return -EFAULT;
- return 0;
- }
- if (cmd == SOUND_OLD_MIXER_INFO) {
- _old_mixer_info info;
- strncpy(info.id, card->pci_info->name, sizeof(info.id));
- strncpy(info.name, card->pci_info->name, sizeof(info.name));
- if (copy_to_user((void *)arg, &info, sizeof(info)))
- return -EFAULT;
- return 0;
- }
-
- if (_IOC_TYPE(cmd) != 'M' || _IOC_SIZE(cmd) != sizeof(int))
- return -EINVAL;
-
- if (cmd == OSS_GETVERSION)
- return put_user(SOUND_VERSION, (int *)arg);
-
- if (_IOC_DIR(cmd) == _IOC_READ) {
- switch (_IOC_NR(cmd)) {
- case SOUND_MIXER_RECSRC: /* give them the current record source */
- if (!card->mix.recmask_io) {
- val = 0;
- } else {
- spin_lock_irqsave(&card->lock, flags);
- val = card->mix.recmask_io(card,1,0);
- spin_unlock_irqrestore(&card->lock, flags);
- }
- break;
-
- case SOUND_MIXER_DEVMASK: /* give them the supported mixers */
- val = card->mix.supported_mixers;
- break;
-
- case SOUND_MIXER_RECMASK: /* Arg contains a bit for each supported recording source */
- val = card->mix.record_sources;
- break;
-
- case SOUND_MIXER_STEREODEVS: /* Mixer channels supporting stereo */
- val = card->mix.stereo_mixers;
- break;
-
- case SOUND_MIXER_CAPS:
- val = SOUND_CAP_EXCL_INPUT;
- break;
-
- default: /* read a specific mixer */
- i = _IOC_NR(cmd);
-
- if (!supported_mixer(card,i))
- return -EINVAL;
-
- /* do we ever want to touch the hardware? */
- /* spin_lock_irqsave(&s->lock, flags);
- val = card->mix.read_mixer(card,i);
- spin_unlock_irqrestore(&s->lock, flags);*/
-
- val = card->mix.mixer_state[i];
- /* printk("returned 0x%x for mixer %d\n",val,i);*/
- break;
- }
- return put_user(val,(int *)arg);
- }
-
- if (_IOC_DIR(cmd) == (_IOC_WRITE|_IOC_READ)) {
- card->mix.modcnt++;
- get_user_ret(val, (int *)arg, -EFAULT);
-
- switch (_IOC_NR(cmd)) {
- case SOUND_MIXER_RECSRC: /* Arg contains a bit for each recording source */
- if (!card->mix.recmask_io) return -EINVAL;
- if (!(val &= card->mix.record_sources)) return -EINVAL;
-
- spin_lock_irqsave(&card->lock, flags);
- card->mix.recmask_io(card, 0, val);
- spin_unlock_irqrestore(&card->lock, flags);
-
- return 0;
- default: /* write a specific mixer */
- i = _IOC_NR(cmd);
-
- if (!supported_mixer(card, i))
- return -EINVAL;
-
- spin_lock_irqsave(&card->lock, flags);
- set_mixer(card, i, val);
- spin_unlock_irqrestore(&card->lock, flags);
-
- return 0;
- }
- }
- return -EINVAL;
-}
-
-static int trident_open_mixdev(struct inode *inode, struct file *file)
-{
- int minor = MINOR(inode->i_rdev);
- struct trident_card *card = devs;
-
- while (card && card->dev_mixer != minor)
- card = card->next;
- if (!card)
- return -ENODEV;
-
- file->private_data = card;
-
- //FIXME put back in
- //MOD_INC_USE_COUNT;
- return 0;
-}
-
-static int trident_release_mixdev(struct inode *inode, struct file *file)
-{
- struct trident_card *card = (struct trident_card *)file->private_data;
-
- VALIDATE_CARD(card);
-
- //FIXME put back in
- //MOD_DEC_USE_COUNT;
- return 0;
-}
-
-static int trident_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct trident_card *card = (struct trident_card *)file->private_data;
-
- VALIDATE_CARD(card);
- return mixer_ioctl(card, cmd, arg);
-}
-
static loff_t trident_llseek(struct file *file, loff_t offset, int origin)
{
return -ESPIPE;
}
-static /*const*/ struct file_operations trident_mixer_fops = {
- &trident_llseek,
- NULL, /* read */
- NULL, /* write */
- NULL, /* readdir */
- NULL, /* poll */
- &trident_ioctl_mixdev,
- NULL, /* mmap */
- &trident_open_mixdev,
- NULL, /* flush */
- &trident_release_mixdev,
- NULL, /* fsync */
- NULL, /* fasync */
- NULL, /* lock */
-};
-
-/* drain the DAC buffer
- FIXME: This function will block (forever ??) when using
- XMMS Qsound plugin and direct cat sample.wav > /dev/dsp
- This behavior is when drain_dac is called by trident_release. */
-static int drain_dac(struct trident_state *s, int nonblock)
-{
- DECLARE_WAITQUEUE(wait, current);
- unsigned long flags;
- int count;
- signed long tmo;
-
- if (s->dma_dac.mapped || !s->dma_dac.ready)
- return 0;
-
- current->state = TASK_INTERRUPTIBLE;
- add_wait_queue(&s->dma_dac.wait, &wait);
- for (;;) {
- spin_lock_irqsave(&s->card->lock, flags);
- count = s->dma_dac.count;
- spin_unlock_irqrestore(&s->card->lock, flags);
-
- if (count <= 0)
- break;
-
- if (signal_pending(current))
- break;
-
- if (nonblock) {
- remove_wait_queue(&s->dma_dac.wait, &wait);
- current->state = TASK_RUNNING;
- return -EBUSY;
- }
-
- tmo = (count * HZ) / s->ratedac;
- tmo >>= sample_shift[(s->fmt >> TRIDENT_DAC_SHIFT) & TRIDENT_FMT_MASK];
-
- /* XXX this is just broken. someone is waking us up alot,
- or schedule_timeout is broken.
- or something. who cares. - zach */
- if (!schedule_timeout(tmo ? tmo : 1) && tmo)
- printk(KERN_ERR "trident: drain_dac, "
- "dma timed out? jiffies = %ld\n",
- jiffies);
- }
- remove_wait_queue(&s->dma_dac.wait, &wait);
- current->state = TASK_RUNNING;
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- return 0;
-}
-
/* in this loop, dma_adc.count signifies the amount of data thats waiting
to be copied to the user's buffer. it is filled by the interrupt
handler and drained by this loop. */
static ssize_t trident_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
{
struct trident_state *state = (struct trident_state *)file->private_data;
+ struct dmabuf *dmabuf = &state->dma_dac;
ssize_t ret;
unsigned long flags;
unsigned swptr;
int cnt;
-
+
VALIDATE_STATE(state);
if (ppos != &file->f_pos)
return -ESPIPE;
- if (state->dma_adc.mapped)
+ if (dmabuf->mapped)
return -ENXIO;
- if (!state->dma_adc.ready && (ret = prog_dmabuf(state, 1)))
+ if (!dmabuf->ready && (ret = prog_dmabuf(state, 1)))
return ret;
if (!access_ok(VERIFY_WRITE, buffer, count))
return -EFAULT;
@@ -2141,12 +1170,10 @@ static ssize_t trident_read(struct file *file, char *buffer, size_t count, loff_
while (count > 0) {
spin_lock_irqsave(&state->card->lock, flags);
- /* remember, all these things are expressed in bytes to be
- sent to the user.. hence the evil / 2 down below */
- swptr = state->dma_adc.swptr;
- cnt = state->dma_adc.dmasize - swptr;
- if (state->dma_adc.count < cnt)
- cnt = state->dma_adc.count;
+ swptr = dmabuf->swptr;
+ cnt = dmabuf->dmasize - swptr;
+ if (dmabuf->count < cnt)
+ cnt = dmabuf->count;
spin_unlock_irqrestore(&state->card->lock, flags);
if (cnt > count)
@@ -2158,20 +1185,17 @@ static ssize_t trident_read(struct file *file, char *buffer, size_t count, loff_
ret = ret ? ret : -EAGAIN;
return ret;
}
- if (!interruptible_sleep_on_timeout(&state->dma_adc.wait, HZ)) {
- printk(KERN_DEBUG "(trident) read: chip lockup? "
+ if (!interruptible_sleep_on_timeout(&dmabuf->wait, HZ)) {
+ printk(KERN_ERR
+ "(trident) read: chip lockup? "
"dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
- state->dma_adc.dmasize,
- state->dma_adc.fragsize,
- state->dma_adc.count,
- state->dma_adc.hwptr,
- state->dma_adc.swptr);
+ dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
+ dmabuf->hwptr, dmabuf->swptr);
stop_adc(state);
-
spin_lock_irqsave(&state->card->lock, flags);
- state->dma_adc.count = 0;
- state->dma_adc.hwptr = 0;
- state->dma_adc.swptr = 0;
+ dmabuf->count = 0;
+ dmabuf->hwptr = 0;
+ dmabuf->swptr = 0;
spin_unlock_irqrestore(&state->card->lock, flags);
}
if (signal_pending(current)) {
@@ -2180,17 +1204,19 @@ static ssize_t trident_read(struct file *file, char *buffer, size_t count, loff_
}
continue;
}
-
- if (copy_to_user(buffer, state->dma_adc.rawbuf + swptr, cnt)) {
+
+ if (copy_to_user(buffer, dmabuf->rawbuf + swptr, cnt)) {
ret = ret ? ret : -EFAULT;
return ret;
}
- swptr = (swptr + cnt) % state->dma_adc.dmasize;
+ swptr = (swptr + cnt) % dmabuf->dmasize;
+
spin_lock_irqsave(&state->card->lock, flags);
- state->dma_adc.swptr = swptr;
- state->dma_adc.count -= cnt;
+ dmabuf->swptr = swptr;
+ dmabuf->count -= cnt;
spin_unlock_irqrestore(&state->card->lock, flags);
+
count -= cnt;
buffer += cnt;
ret += cnt;
@@ -2203,11 +1229,11 @@ static ssize_t trident_read(struct file *file, char *buffer, size_t count, loff_
static ssize_t trident_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
{
struct trident_state *state = (struct trident_state *)file->private_data;
+ struct dmabuf *dmabuf = &state->dma_dac;
ssize_t ret;
unsigned long flags;
unsigned swptr;
int cnt;
- int mode = (state->fmt >> TRIDENT_DAC_SHIFT) & TRIDENT_FMT_MASK;
#ifdef DEBUG
printk("trident: trident_write called, count = %d\n", count);
@@ -2216,9 +1242,9 @@ static ssize_t trident_write(struct file *file, const char *buffer, size_t count
VALIDATE_STATE(state);
if (ppos != &file->f_pos)
return -ESPIPE;
- if (state->dma_dac.mapped)
+ if (dmabuf->mapped)
return -ENXIO;
- if (!state->dma_dac.ready && (ret = prog_dmabuf(state, 0)))
+ if (!dmabuf->ready && (ret = prog_dmabuf(state, 0)))
return ret;
if (!access_ok(VERIFY_READ, buffer, count))
return -EFAULT;
@@ -2226,41 +1252,47 @@ static ssize_t trident_write(struct file *file, const char *buffer, size_t count
while (count > 0) {
spin_lock_irqsave(&state->card->lock, flags);
- if (state->dma_dac.count < 0) {
- state->dma_dac.count = 0;
- state->dma_dac.swptr = state->dma_dac.hwptr;
+ if (dmabuf->count < 0) {
+ /* buffer underrun, we are recovering from sleep_on_timeout,
+ resync hwptr and swptr */
+ dmabuf->count = 0;
+ dmabuf->swptr = dmabuf->hwptr;
}
- swptr = state->dma_dac.swptr;
- cnt = state->dma_dac.dmasize - swptr;
- if (state->dma_dac.count + cnt > state->dma_dac.dmasize)
- cnt = state->dma_dac.dmasize - state->dma_dac.count;
+ swptr = dmabuf->swptr;
+ cnt = dmabuf->dmasize - swptr;
+ if (dmabuf->count + cnt > dmabuf->dmasize)
+ cnt = dmabuf->dmasize - dmabuf->count;
spin_unlock_irqrestore(&state->card->lock, flags);
if (cnt > count)
cnt = count;
if (cnt <= 0) {
- /* buffer is full, wait for it to be played */
+ unsigned long tmo;
+ /* buffer is full, start the dma machine and wait for data to be played */
start_dac(state);
if (file->f_flags & O_NONBLOCK) {
if (!ret) ret = -EAGAIN;
return ret;
}
- if (!interruptible_sleep_on_timeout(&state->dma_dac.wait, HZ)) {
- printk(KERN_ERR
- "trident: write: chip lockup? "
- "dmasz %u fragsz %u count %i "
- "hwptr %u swptr %u\n",
- state->dma_dac.dmasize,
- state->dma_dac.fragsize,
- state->dma_dac.count,
- state->dma_dac.hwptr,
- state->dma_dac.swptr);
- stop_dac(state);
- spin_lock_irqsave(&state->card->lock, flags);
- state->dma_dac.count = 0;
- state->dma_dac.hwptr = 0;
- state->dma_dac.swptr = 0;
- spin_unlock_irqrestore(&state->card->lock, flags);
+ /* No matter how much data left in the buffer, we have to wait untill
+ CSO == ESO/2 or CSO == ESO when address engine interrupts */
+ tmo = (dmabuf->dmasize * HZ) / (dmabuf->rate * 2);
+ tmo >>= sample_shift[dmabuf->fmt];
+ /* There are two situations when sleep_on_timeout returns, one is when the
+ interrupt is serviced correctly and the process is waked up by ISR ON TIME.
+ Another is when timeout is expired, which means that either interrupt is NOT
+ serviced correctly (pending interrupt) or it is TOO LATE for the process to
+ be scheduled to run (scheduler latency) which results in a (potential) buffer
+ underrun. And worse, there is NOTHING we can do to prevent it. */
+ if (!interruptible_sleep_on_timeout(&dmabuf->wait, tmo)) {
+#ifdef DEBUG
+ printk(KERN_ERR "trident: schedule timeout, "
+ "dmasz %u fragsz %u count %i hwptr %u swptr %u\n",
+ dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
+ dmabuf->hwptr, dmabuf->swptr);
+#endif
+ /* a buffer underrun, we delay the recovery untill next time the
+ while loop begin and we REALLY have data to play */
}
if (signal_pending(current)) {
if (!ret) ret = -ERESTARTSYS;
@@ -2268,18 +1300,17 @@ static ssize_t trident_write(struct file *file, const char *buffer, size_t count
}
continue;
}
- if (copy_from_user(state->dma_dac.rawbuf + swptr, buffer, cnt)) {
- if (!ret)
- ret = -EFAULT;
+ if (copy_from_user(dmabuf->rawbuf + swptr, buffer, cnt)) {
+ if (!ret) ret = -EFAULT;
return ret;
}
- swptr = (swptr + cnt) % state->dma_dac.dmasize;
+ swptr = (swptr + cnt) % dmabuf->dmasize;
spin_lock_irqsave(&state->card->lock, flags);
- state->dma_dac.swptr = swptr;
- state->dma_dac.count += cnt;
- state->dma_dac.endcleared = 0;
+ dmabuf->swptr = swptr;
+ dmabuf->count += cnt;
+ dmabuf->endcleared = 0;
spin_unlock_irqrestore(&state->card->lock, flags);
count -= cnt;
@@ -2304,7 +1335,6 @@ static unsigned int trident_poll(struct file *file, struct poll_table_struct *wa
spin_lock_irqsave(&s->card->lock, flags);
trident_update_ptr(s);
-
if (file->f_mode & FMODE_READ) {
if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
mask |= POLLIN | POLLRDNORM;
@@ -2319,56 +1349,56 @@ static unsigned int trident_poll(struct file *file, struct poll_table_struct *wa
}
}
spin_unlock_irqrestore(&s->card->lock, flags);
+
return mask;
}
-/* this needs to be fixed to deal with the dual apus/buffers */
-#if 0
static int trident_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct trident_state *s = (struct trident_state *)file->private_data;
- struct dmabuf *db;
+ struct trident_state *state = (struct trident_state *)file->private_data;
+ struct dmabuf *dmabuf;
int ret;
unsigned long size;
- VALIDATE_STATE(s);
+ VALIDATE_STATE(state);
if (vma->vm_flags & VM_WRITE) {
- if ((ret = prog_dmabuf(s, 0)) != 0)
+ if ((ret = prog_dmabuf(state, 0)) != 0)
return ret;
- db = &s->dma_dac;
+ dmabuf = &state->dma_dac;
} else if (vma->vm_flags & VM_READ) {
- if ((ret = prog_dmabuf(s, 1)) != 0)
+ if ((ret = prog_dmabuf(state, 1)) != 0)
return ret;
- db = &s->dma_adc;
+ dmabuf = &state->dma_adc;
} else
return -EINVAL;
- if (vma->vm_offset != 0)
+
+ if (vma->vm_pgoff != 0)
return -EINVAL;
size = vma->vm_end - vma->vm_start;
- if (size > (PAGE_SIZE << db->buforder))
+ if (size > (PAGE_SIZE << dmabuf->buforder))
return -EINVAL;
- if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
+ if (remap_page_range(vma->vm_start, virt_to_phys(dmabuf->rawbuf),
+ size, vma->vm_page_prot))
return -EAGAIN;
- db->mapped = 1;
+ dmabuf->mapped = 1;
+
return 0;
}
-#endif
static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
- struct trident_state *s = (struct trident_state *)file->private_data;
+ struct trident_state *state = (struct trident_state *)file->private_data;
unsigned long flags;
audio_buf_info abinfo;
count_info cinfo;
int val, mapped, ret;
- unsigned char fmtm, fmtd;
- VALIDATE_STATE(s);
- mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) ||
- ((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
+ VALIDATE_STATE(state);
+ mapped = ((file->f_mode & FMODE_WRITE) && state->dma_dac.mapped) ||
+ ((file->f_mode & FMODE_READ) && state->dma_adc.mapped);
#ifdef DEBUG
- printk("trident: trident_ioctl, command = %2d, arg = 0x%08x\n",_IOC_NR(cmd),
- arg ? *(int *)arg : 0);
+ printk("trident: trident_ioctl, command = %2d, arg = 0x%08x\n",
+ _IOC_NR(cmd), arg ? *(int *)arg : 0);
#endif
switch (cmd)
@@ -2378,189 +1408,218 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm
case SNDCTL_DSP_RESET:
if (file->f_mode & FMODE_WRITE) {
- stop_dac(s);
+ stop_dac(state);
synchronize_irq();
- s->dma_dac.swptr = s->dma_dac.hwptr = 0;
- s->dma_dac.count = s->dma_dac.total_bytes = 0;
+ state->dma_dac.ready = 0;
+ state->dma_dac.swptr = state->dma_dac.hwptr = 0;
+ state->dma_dac.count = state->dma_dac.total_bytes = 0;
}
if (file->f_mode & FMODE_READ) {
- stop_adc(s);
+ stop_adc(state);
synchronize_irq();
- s->dma_adc.swptr = s->dma_adc.hwptr = 0;
- s->dma_adc.count = s->dma_adc.total_bytes = 0;
+ state->dma_adc.ready = 0;
+ state->dma_adc.swptr = state->dma_adc.hwptr = 0;
+ state->dma_adc.count = state->dma_adc.total_bytes = 0;
}
return 0;
case SNDCTL_DSP_SYNC:
if (file->f_mode & FMODE_WRITE)
- return drain_dac(s, file->f_flags & O_NONBLOCK);
+ return drain_dac(state, file->f_flags & O_NONBLOCK);
return 0;
- case SNDCTL_DSP_SPEED:
+ case SNDCTL_DSP_SPEED: /* set smaple rate */
get_user_ret(val, (int *)arg, -EFAULT);
if (val >= 0) {
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- s->dma_adc.ready = 0;
- trident_set_adc_rate(s, val, 1);
- }
if (file->f_mode & FMODE_WRITE) {
- stop_dac(s);
- s->dma_dac.ready = 0;
- trident_set_dac_rate(s, val, 1);
+ stop_dac(state);
+ state->dma_dac.ready = 0;
+ spin_lock_irqsave(&state->card->lock, flags);
+ trident_set_dac_rate(state, val);
+ spin_unlock_irqrestore(&state->card->lock, flags);
+ }
+ if (file->f_mode & FMODE_READ) {
+ stop_adc(state);
+ state->dma_adc.ready = 0;
+ spin_lock_irqsave(&state->card->lock, flags);
+ trident_set_adc_rate(state, val);
+ spin_unlock_irqrestore(&state->card->lock, flags);
}
}
- return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac,
+ return put_user((file->f_mode & FMODE_READ) ? state->dma_adc.rate :
+ state->dma_dac.rate,
(int *)arg);
- case SNDCTL_DSP_STEREO:
+ case SNDCTL_DSP_STEREO: /* set stereo or mono channel */
get_user_ret(val, (int *)arg, -EFAULT);
- fmtd = 0;
- fmtm = ~0;
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- s->dma_adc.ready = 0;
+ if (file->f_mode & FMODE_WRITE) {
+ stop_dac(state);
+ state->dma_dac.ready = 0;
if (val)
- fmtd |= TRIDENT_FMT_STEREO << TRIDENT_ADC_SHIFT;
+ state->dma_dac.fmt |= TRIDENT_FMT_STEREO;
else
- fmtm &= ~(TRIDENT_FMT_STEREO << TRIDENT_ADC_SHIFT);
+ state->dma_dac.fmt &= ~TRIDENT_FMT_STEREO;
}
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(s);
- s->dma_dac.ready = 0;
+ if (file->f_mode & FMODE_READ) {
+ stop_adc(state);
+ state->dma_adc.ready = 0;
if (val)
- fmtd |= TRIDENT_FMT_STEREO << TRIDENT_DAC_SHIFT;
+ state->dma_adc.fmt |= TRIDENT_FMT_STEREO;
else
- fmtm &= ~(TRIDENT_FMT_STEREO << TRIDENT_DAC_SHIFT);
+ state->dma_adc.fmt &= ~TRIDENT_FMT_STEREO;
}
- set_fmt(s, fmtm, fmtd);
return 0;
case SNDCTL_DSP_GETBLKSIZE:
if (file->f_mode & FMODE_WRITE) {
- if ((val = prog_dmabuf(s, 0)))
+ if ((val = prog_dmabuf(state, 0)))
return val;
- return put_user(s->dma_dac.fragsize, (int *)arg);
+ return put_user(state->dma_dac.fragsize, (int *)arg);
+ }
+ if (file->f_mode & FMODE_READ) {
+ if ((val = prog_dmabuf(state, 1)))
+ return val;
+ return put_user(state->dma_adc.fragsize, (int *)arg);
}
- if ((val = prog_dmabuf(s, 1)))
- return val;
- return put_user(s->dma_adc.fragsize, (int *)arg);
- case SNDCTL_DSP_GETFMTS: /* Returns a mask */
- return put_user(AFMT_S8|AFMT_S16_LE, (int *)arg);
- case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
+ case SNDCTL_DSP_GETFMTS: /* Returns a mask of supported sample format*/
+ return put_user(AFMT_S16_LE|AFMT_U16_LE|AFMT_S8|AFMT_U8, (int *)arg);
+
+ case SNDCTL_DSP_SETFMT: /* Select sample format */
get_user_ret(val, (int *)arg, -EFAULT);
if (val != AFMT_QUERY) {
- fmtd = 0;
- fmtm = ~0;
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- s->dma_adc.ready = 0;
- /* fixed at 16bit for now */
- fmtd |= TRIDENT_FMT_16BIT << TRIDENT_ADC_SHIFT;
-#if 0
+ if (file->f_mode & FMODE_WRITE) {
+ stop_dac(state);
+ state->dma_dac.ready = 0;
if (val == AFMT_S16_LE)
- fmtd |= TRIDENT_FMT_16BIT << TRIDENT_ADC_SHIFT;
+ state->dma_dac.fmt |= TRIDENT_FMT_16BIT;
else
- fmtm &= ~(TRIDENT_FMT_16BIT << TRIDENT_ADC_SHIFT);
-#endif
+ state->dma_dac.fmt &= ~TRIDENT_FMT_16BIT;
}
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(s);
- s->dma_dac.ready = 0;
+ if (file->f_mode & FMODE_READ) {
+ stop_adc(state);
+ state->dma_adc.ready = 0;
if (val == AFMT_S16_LE)
- fmtd |= TRIDENT_FMT_16BIT << TRIDENT_DAC_SHIFT;
+ state->dma_adc.fmt |= TRIDENT_FMT_16BIT;
else
- fmtm &= ~(TRIDENT_FMT_16BIT << TRIDENT_DAC_SHIFT);
+ state->dma_adc.fmt &= ~TRIDENT_FMT_16BIT;
}
- set_fmt(s, fmtm, fmtd);
}
- return put_user((s->fmt & ((file->f_mode & FMODE_READ) ?
- (TRIDENT_FMT_16BIT << TRIDENT_ADC_SHIFT) :
- (TRIDENT_FMT_16BIT << TRIDENT_DAC_SHIFT))) ?
- AFMT_S16_LE : AFMT_S8, (int *)arg);
+ if (file->f_mode & FMODE_WRITE)
+ return put_user((state->dma_dac.fmt & TRIDENT_FMT_16BIT) ?
+ AFMT_S16_LE : AFMT_U8, (int *)arg);
+ else
+ return put_user((state->dma_adc.fmt & TRIDENT_FMT_16BIT) ?
+ AFMT_S16_LE : AFMT_U8, (int *)arg);
case SNDCTL_DSP_CHANNELS:
get_user_ret(val, (int *)arg, -EFAULT);
if (val != 0) {
- fmtd = 0;
- fmtm = ~0;
-
- if (file->f_mode & FMODE_READ) {
- stop_adc(s);
- s->dma_adc.ready = 0;
+ if (file->f_mode & FMODE_WRITE) {
+ stop_dac(state);
+ state->dma_dac.ready = 0;
if (val >= 2)
- fmtd |= TRIDENT_FMT_STEREO << TRIDENT_ADC_SHIFT;
+ state->dma_dac.fmt |= TRIDENT_FMT_STEREO;
else
- fmtm &= ~(TRIDENT_FMT_STEREO << TRIDENT_ADC_SHIFT);
+ state->dma_dac.fmt &= ~TRIDENT_FMT_STEREO;
}
-
- if (file->f_mode & FMODE_WRITE) {
- stop_dac(s);
- s->dma_dac.ready = 0;
+ if (file->f_mode & FMODE_READ) {
+ stop_adc(state);
+ state->dma_adc.ready = 0;
if (val >= 2)
- fmtd |= TRIDENT_FMT_STEREO << TRIDENT_DAC_SHIFT;
+ state->dma_adc.fmt |= TRIDENT_FMT_STEREO;
else
- fmtm &= ~(TRIDENT_FMT_STEREO << TRIDENT_DAC_SHIFT);
+ state->dma_adc.fmt &= ~TRIDENT_FMT_STEREO;
}
- set_fmt(s, fmtm, fmtd);
}
- return put_user((s->fmt & ((file->f_mode & FMODE_READ) ?
- (TRIDENT_FMT_STEREO << TRIDENT_ADC_SHIFT) :
- (TRIDENT_FMT_STEREO << TRIDENT_DAC_SHIFT))) ? 2 : 1, (int *)arg);
+ if (file->f_mode & FMODE_WRITE)
+ return put_user((state->dma_dac.fmt & TRIDENT_FMT_STEREO) ? 2 : 1,
+ (int *)arg);
+ else
+ return put_user((state->dma_adc.fmt & TRIDENT_FMT_STEREO) ? 2 : 1,
+ (int *)arg);
case SNDCTL_DSP_POST:
+ /* FIXME: the same as RESET ?? */
return 0;
case SNDCTL_DSP_SUBDIVIDE:
- if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
- (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))
+ if ((file->f_mode & FMODE_READ && state->dma_adc.subdivision) ||
+ (file->f_mode & FMODE_WRITE && state->dma_dac.subdivision))
return -EINVAL;
get_user_ret(val, (int *)arg, -EFAULT);
if (val != 1 && val != 2 && val != 4)
return -EINVAL;
if (file->f_mode & FMODE_READ)
- s->dma_adc.subdivision = val;
+ state->dma_adc.subdivision = val;
if (file->f_mode & FMODE_WRITE)
- s->dma_dac.subdivision = val;
+ state->dma_dac.subdivision = val;
return 0;
case SNDCTL_DSP_SETFRAGMENT:
get_user_ret(val, (int *)arg, -EFAULT);
if (file->f_mode & FMODE_READ) {
- s->dma_adc.ossfragshift = val & 0xffff;
- s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
- if (s->dma_adc.ossfragshift < 4)
- s->dma_adc.ossfragshift = 4;
- if (s->dma_adc.ossfragshift > 15)
- s->dma_adc.ossfragshift = 15;
- if (s->dma_adc.ossmaxfrags < 4)
- s->dma_adc.ossmaxfrags = 4;
+ state->dma_adc.ossfragshift = val & 0xffff;
+ state->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
+ if (state->dma_adc.ossfragshift < 4)
+ state->dma_adc.ossfragshift = 4;
+ if (state->dma_adc.ossfragshift > 15)
+ state->dma_adc.ossfragshift = 15;
+ if (state->dma_adc.ossmaxfrags < 4)
+ state->dma_adc.ossmaxfrags = 4;
}
if (file->f_mode & FMODE_WRITE) {
- s->dma_dac.ossfragshift = val & 0xffff;
- s->dma_dac.ossmaxfrags = (val >> 16) & 0xffff;
- if (s->dma_dac.ossfragshift < 4)
- s->dma_dac.ossfragshift = 4;
- if (s->dma_dac.ossfragshift > 15)
- s->dma_dac.ossfragshift = 15;
- if (s->dma_dac.ossmaxfrags < 4)
- s->dma_dac.ossmaxfrags = 4;
+ state->dma_dac.ossfragshift = val & 0xffff;
+ state->dma_dac.ossmaxfrags = (val >> 16) & 0xffff;
+ if (state->dma_dac.ossfragshift < 4)
+ state->dma_dac.ossfragshift = 4;
+ if (state->dma_dac.ossfragshift > 15)
+ state->dma_dac.ossfragshift = 15;
+ if (state->dma_dac.ossmaxfrags < 4)
+ state->dma_dac.ossmaxfrags = 4;
}
return 0;
- case SNDCTL_DSP_GETCAPS:
- return put_user(0/* DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP */,
- (int *)arg);
-
- case SNDCTL_DSP_SETDUPLEX:
- /* XXX fix */
+ case SNDCTL_DSP_GETOSPACE:
+ if (!(file->f_mode & FMODE_WRITE))
+ return -EINVAL;
+ if (!state->dma_dac.enable && (val = prog_dmabuf(state, 0)) != 0)
+ return val;
+ spin_lock_irqsave(&state->card->lock, flags);
+ trident_update_ptr(state);
+ abinfo.fragsize = state->dma_dac.fragsize;
+ abinfo.bytes = state->dma_dac.dmasize - state->dma_dac.count;
+ abinfo.fragstotal = state->dma_dac.numfrag;
+ abinfo.fragments = abinfo.bytes >> state->dma_dac.fragshift;
+ spin_unlock_irqrestore(&state->card->lock, flags);
+ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+
+ case SNDCTL_DSP_GETISPACE:
+ if (!(file->f_mode & FMODE_READ))
+ return -EINVAL;
+ if (!state->dma_adc.enable && (val = prog_dmabuf(state, 1)) != 0)
+ return val;
+ spin_lock_irqsave(&state->card->lock, flags);
+ trident_update_ptr(state);
+ abinfo.fragsize = state->dma_adc.fragsize;
+ abinfo.bytes = state->dma_adc.count;
+ abinfo.fragstotal = state->dma_adc.numfrag;
+ abinfo.fragments = abinfo.bytes >> state->dma_adc.fragshift;
+ spin_unlock_irqrestore(&state->card->lock, flags);
+ return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+
+ case SNDCTL_DSP_NONBLOCK:
+ file->f_flags |= O_NONBLOCK;
return 0;
+ case SNDCTL_DSP_GETCAPS:
+ return put_user(/* DSP_CAP_DUPLEX|*/DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP,
+ (int *)arg);
+
case SNDCTL_DSP_GETTRIGGER:
val = 0;
- if (file->f_mode & FMODE_READ && s->enable & TRIDENT_ENABLE_RE)
+ if (file->f_mode & FMODE_READ && state->dma_adc.enable)
val |= PCM_ENABLE_INPUT;
- if (file->f_mode & FMODE_WRITE && s->enable & TRIDENT_ENABLE_PE)
+ if (file->f_mode & FMODE_WRITE && state->dma_dac.enable)
val |= PCM_ENABLE_OUTPUT;
return put_user(val, (int *)arg);
@@ -2568,106 +1627,86 @@ static int trident_ioctl(struct inode *inode, struct file *file, unsigned int cm
get_user_ret(val, (int *)arg, -EFAULT);
if (file->f_mode & FMODE_READ) {
if (val & PCM_ENABLE_INPUT) {
- if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))
+ if (!state->dma_adc.ready && (ret = prog_dmabuf(state, 1)))
return ret;
- start_adc(s);
+ start_adc(state);
}
else
- stop_adc(s);
+ stop_adc(state);
}
if (file->f_mode & FMODE_WRITE) {
if (val & PCM_ENABLE_OUTPUT) {
- if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+ if (!state->dma_dac.ready && (ret = prog_dmabuf(state, 0)))
return ret;
- start_dac(s);
+ start_dac(state);
}
else
- stop_dac(s);
+ stop_dac(state);
}
return 0;
- case SNDCTL_DSP_GETOSPACE:
- if (!(file->f_mode & FMODE_WRITE))
- return -EINVAL;
- if (!(s->enable & TRIDENT_ENABLE_PE) && (val = prog_dmabuf(s, 0)) != 0)
- return val;
- spin_lock_irqsave(&s->card->lock, flags);
- trident_update_ptr(s);
- abinfo.fragsize = s->dma_dac.fragsize;
- abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count;
- abinfo.fragstotal = s->dma_dac.numfrag;
- abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;
- spin_unlock_irqrestore(&s->card->lock, flags);
- return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-
- case SNDCTL_DSP_GETISPACE:
- if (!(file->f_mode & FMODE_READ))
- return -EINVAL;
- if (!(s->enable & TRIDENT_ENABLE_RE) && (val = prog_dmabuf(s, 1)) != 0)
- return val;
- spin_lock_irqsave(&s->card->lock, flags);
- trident_update_ptr(s);
- abinfo.fragsize = s->dma_adc.fragsize;
- abinfo.bytes = s->dma_adc.count;
- abinfo.fragstotal = s->dma_adc.numfrag;
- abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;
- spin_unlock_irqrestore(&s->card->lock, flags);
- return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
-
- case SNDCTL_DSP_NONBLOCK:
- file->f_flags |= O_NONBLOCK;
- return 0;
-
- case SNDCTL_DSP_GETODELAY:
- if (!(file->f_mode & FMODE_WRITE))
- return -EINVAL;
- spin_lock_irqsave(&s->card->lock, flags);
- trident_update_ptr(s);
- val = s->dma_dac.count;
- spin_unlock_irqrestore(&s->card->lock, flags);
- return put_user(val, (int *)arg);
-
case SNDCTL_DSP_GETIPTR:
if (!(file->f_mode & FMODE_READ))
return -EINVAL;
- spin_lock_irqsave(&s->card->lock, flags);
- trident_update_ptr(s);
- cinfo.bytes = s->dma_adc.total_bytes;
- cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
- cinfo.ptr = s->dma_adc.hwptr;
- if (s->dma_adc.mapped)
- s->dma_adc.count &= s->dma_adc.fragsize-1;
- spin_unlock_irqrestore(&s->card->lock, flags);
+ spin_lock_irqsave(&state->card->lock, flags);
+ trident_update_ptr(state);
+ cinfo.bytes = state->dma_adc.total_bytes;
+ cinfo.blocks = state->dma_adc.count >> state->dma_adc.fragshift;
+ cinfo.ptr = state->dma_adc.hwptr;
+ if (state->dma_adc.mapped)
+ state->dma_adc.count &= state->dma_adc.fragsize-1;
+ spin_unlock_irqrestore(&state->card->lock, flags);
return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
case SNDCTL_DSP_GETOPTR:
if (!(file->f_mode & FMODE_WRITE))
return -EINVAL;
- spin_lock_irqsave(&s->card->lock, flags);
- trident_update_ptr(s);
- cinfo.bytes = s->dma_dac.total_bytes;
- cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift;
- cinfo.ptr = s->dma_dac.hwptr;
- if (s->dma_dac.mapped)
- s->dma_dac.count &= s->dma_dac.fragsize-1;
- spin_unlock_irqrestore(&s->card->lock, flags);
+ spin_lock_irqsave(&state->card->lock, flags);
+ trident_update_ptr(state);
+ cinfo.bytes = state->dma_dac.total_bytes;
+ cinfo.blocks = state->dma_dac.count >> state->dma_dac.fragshift;
+ cinfo.ptr = state->dma_dac.hwptr;
+ if (state->dma_dac.mapped)
+ state->dma_dac.count &= state->dma_dac.fragsize-1;
+ spin_unlock_irqrestore(&state->card->lock, flags);
return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+ case SNDCTL_DSP_SETDUPLEX:
+ /* XXX fix */
+ return 0;
+
+ case SNDCTL_DSP_GETODELAY:
+ if (!(file->f_mode & FMODE_WRITE))
+ return -EINVAL;
+ spin_lock_irqsave(&state->card->lock, flags);
+ trident_update_ptr(state);
+ val = state->dma_dac.count;
+ spin_unlock_irqrestore(&state->card->lock, flags);
+ return put_user(val, (int *)arg);
+
case SOUND_PCM_READ_RATE:
- return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
+ return put_user((file->f_mode & FMODE_READ) ? state->dma_adc.rate :
+ state->dma_dac.rate, (int *)arg);
case SOUND_PCM_READ_CHANNELS:
- return put_user((s->fmt & ((file->f_mode & FMODE_READ) ?
- (TRIDENT_FMT_STEREO << TRIDENT_ADC_SHIFT) :
- (TRIDENT_FMT_STEREO << TRIDENT_DAC_SHIFT))) ? 2 : 1, (int *)arg);
+ if (file->f_mode & FMODE_WRITE)
+ return put_user((state->dma_dac.fmt & TRIDENT_FMT_STEREO) ? 2 : 1,
+ (int *)arg);
+ else
+ return put_user((state->dma_adc.fmt & TRIDENT_FMT_STEREO) ? 2 : 1,
+ (int *)arg);
case SOUND_PCM_READ_BITS:
- return put_user((s->fmt & ((file->f_mode & FMODE_READ) ?
- (TRIDENT_FMT_16BIT << TRIDENT_ADC_SHIFT) :
- (TRIDENT_FMT_16BIT << TRIDENT_DAC_SHIFT))) ? 16 : 8, (int *)arg);
-
- case SOUND_PCM_WRITE_FILTER:
+ if (file->f_mode & FMODE_WRITE)
+ return put_user((state->dma_dac.fmt & TRIDENT_FMT_16BIT) ?
+ AFMT_S16_LE : AFMT_U8, (int *)arg);
+ else
+ return put_user((state->dma_adc.fmt & TRIDENT_FMT_16BIT) ?
+ AFMT_S16_LE : AFMT_U8, (int *)arg);
+ case SNDCTL_DSP_MAPINBUF:
+ case SNDCTL_DSP_MAPOUTBUF:
case SNDCTL_DSP_SETSYNCRO:
+ case SOUND_PCM_WRITE_FILTER:
case SOUND_PCM_READ_FILTER:
return -EINVAL;
@@ -2681,13 +1720,12 @@ static int trident_open(struct inode *inode, struct file *file)
int minor = MINOR(inode->i_rdev);
struct trident_card *card = devs;
struct trident_state *state = NULL;
- unsigned char fmtm = ~0, fmts = 0;
/* find an avaiable virtual channel (instance of /dev/dsp) */
while (card != NULL) {
- for (i = 0; i < NR_DSPS; i++) {
- if (card->channels[i] == NULL) {
- state = card->channels[i] = (struct trident_state *)
+ for (i = 0; i < NR_HW_CH; i++) {
+ if (card->states[i] == NULL) {
+ state = card->states[i] = (struct trident_state *)
kmalloc(sizeof(struct trident_state), GFP_KERNEL);
if (state == NULL)
return -ENOMEM;
@@ -2704,18 +1742,18 @@ static int trident_open(struct inode *inode, struct file *file)
found_virt:
/* found a free virtual channel, allocate hardware channels */
if (file->f_mode & FMODE_READ)
- if ((state->dma_adc.chan = trident_alloc_pcm_channel(card)) == -1) {
- kfree (card->channels[i]);
- card->channels[i] = NULL;;
+ if ((state->dma_adc.channel = trident_alloc_pcm_channel(card)) == NULL) {
+ kfree (card->states[i]);
+ card->states[i] = NULL;;
return -ENODEV;
}
if (file->f_mode & FMODE_WRITE)
- if ((state->dma_dac.chan = trident_alloc_pcm_channel(card)) == -1) {
- kfree (card->channels[i]);
- card->channels[i] = NULL;
+ if ((state->dma_dac.channel = trident_alloc_pcm_channel(card)) == NULL) {
+ kfree (card->states[i]);
+ card->states[i] = NULL;
if (file->f_mode & FMODE_READ)
/* free previously allocated hardware channel */
- trident_free_pcm_channel(card, state->dma_adc.chan);
+ trident_free_pcm_channel(card, state->dma_adc.channel->num);
return -ENODEV;
}
@@ -2732,30 +1770,27 @@ static int trident_open(struct inode *inode, struct file *file)
/* set default sample format, Refer to OSS Programmer's Guide */
if (file->f_mode & FMODE_READ) {
- /* fmtm &= ~((TRIDENT_FMT_STEREO | TRIDENT_FMT_16BIT) << TRIDENT_ADC_SHIFT);
- if ((minor & 0xf) == SND_DEV_DSP16)
- fmts |= TRIDENT_FMT_16BIT << TRIDENT_ADC_SHIFT; */
- fmtm = (TRIDENT_FMT_STEREO|TRIDENT_FMT_16BIT) << TRIDENT_ADC_SHIFT;
+ /* FIXME: Trident 4d can only record in singed 16-bits stereo, 48kHz sample */
+ state->dma_adc.fmt = TRIDENT_FMT_STEREO|TRIDENT_FMT_16BIT;
state->dma_adc.ossfragshift = 0;
state->dma_adc.ossmaxfrags = 0;
state->dma_adc.subdivision = 0;
- trident_set_adc_rate(state, 8000, 0);
+ trident_set_adc_rate(state, 48000);
}
/* according to OSS document, /dev/dsp should be default to unsigned 8-bits,
mono, with sample rate 8kHz and /dev/dspW will accept 16-bits sample */
if (file->f_mode & FMODE_WRITE) {
- fmtm &= ~((TRIDENT_FMT_STEREO | TRIDENT_FMT_16BIT) << TRIDENT_DAC_SHIFT);
+ state->dma_dac.fmt &= ~TRIDENT_FMT_MASK;
if ((minor & 0xf) == SND_DEV_DSP16)
- fmts |= TRIDENT_FMT_16BIT << TRIDENT_DAC_SHIFT;
+ state->dma_dac.fmt |= TRIDENT_FMT_16BIT;
state->dma_dac.ossfragshift = 0;
state->dma_dac.ossmaxfrags = 0;
state->dma_dac.subdivision = 0;
- trident_set_dac_rate(state, 8000, 1);
+ trident_set_dac_rate(state, 8000);
}
- set_fmt(state, fmtm, fmts);
- state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
+ state->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
up(&state->open_sem);
//FIXME put back in
@@ -2768,8 +1803,12 @@ static int trident_release(struct inode *inode, struct file *file)
struct trident_state *state = (struct trident_state *)file->private_data;
VALIDATE_STATE(state);
- if (file->f_mode & FMODE_WRITE)
+
+
+ if (file->f_mode & FMODE_WRITE) {
+ trident_clear_tail(state);
drain_dac(state, file->f_flags & O_NONBLOCK);
+ }
/* stop DMA state machine and free DMA buffers/channels */
down(&state->open_sem);
@@ -2777,16 +1816,16 @@ static int trident_release(struct inode *inode, struct file *file)
if (file->f_mode & FMODE_WRITE) {
stop_dac(state);
dealloc_dmabuf(&state->dma_dac);
- trident_free_pcm_channel(state->card, state->dma_dac.chan);
+ trident_free_pcm_channel(state->card, state->dma_dac.channel->num);
}
if (file->f_mode & FMODE_READ) {
stop_adc(state);
dealloc_dmabuf(&state->dma_adc);
- trident_free_pcm_channel(state->card, state->dma_adc.chan);
+ trident_free_pcm_channel(state->card, state->dma_adc.channel->num);
}
- kfree(state->card->channels[state->virt]);
- state->card->channels[state->virt] = NULL;
+ kfree(state->card->states[state->virt]);
+ state->card->states[state->virt] = NULL;
state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
/* we're covered by the open_sem */
@@ -2796,6 +1835,7 @@ static int trident_release(struct inode *inode, struct file *file)
//MOD_DEC_USE_COUNT;
return 0;
}
+
static /*const*/ struct file_operations trident_audio_fops = {
&trident_llseek,
&trident_read,
@@ -2803,7 +1843,7 @@ static /*const*/ struct file_operations trident_audio_fops = {
NULL, /* readdir */
&trident_poll,
&trident_ioctl,
- NULL, /* XXX &trident_mmap, */
+ &trident_mmap,
&trident_open,
NULL, /* flush */
&trident_release,
@@ -2812,15 +1852,238 @@ static /*const*/ struct file_operations trident_audio_fops = {
NULL, /* lock */
};
-/* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered
- untill open time */
-static int trident_install(struct pci_dev *pcidev, struct pci_audio_info *pci_info)
+/* trident specific AC97 functions */
+/* Write AC97 mixer registers */
+static void trident_ac97_set(struct ac97_codec *codec, u8 reg, u16 val)
+{
+ struct trident_card *card = (struct trident_card *)codec->private_data;
+ unsigned int address, mask, busy;
+ unsigned short count = 0xffff;
+ unsigned long flags;
+ u32 data;
+
+ data = ((u32) val) << 16;
+
+ switch (card->pci_id)
+ {
+ default:
+ case PCI_DEVICE_ID_SI_7018:
+ address = SI_AC97_WRITE;
+ mask = SI_AC97_BUSY_WRITE | SI_AC97_AUDIO_BUSY;
+ if (codec->id)
+ mask |= SI_AC97_SECONDARY;
+ busy = SI_AC97_BUSY_WRITE;
+ break;
+ case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
+ address = DX_ACR0_AC97_W;
+ mask = busy = DX_AC97_BUSY_WRITE;
+ break;
+ case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
+ address = NX_ACR1_AC97_W;
+ mask = NX_AC97_BUSY_WRITE;
+ if (codec->id)
+ mask |= NX_AC97_WRITE_SECONDARY;
+ busy = NX_AC97_BUSY_WRITE;
+ break;
+ }
+
+ spin_lock_irqsave(&card->lock, flags);
+ do {
+ if ((inw(TRID_REG(card, address)) & busy) == 0)
+ break;
+ } while (count--);
+
+
+ data |= (mask | (reg & AC97_REG_ADDR));
+
+ if (count == 0) {
+ printk(KERN_ERR "trident: AC97 CODEC write timed out.\n");
+ spin_unlock_irqrestore(&card->lock, flags);
+ return;
+ }
+
+ outl(data, TRID_REG(card, address));
+ spin_unlock_irqrestore(&card->lock, flags);
+}
+
+/* Read AC97 codec registers */
+static u16 trident_ac97_get(struct ac97_codec *codec, u8 reg)
+{
+ struct trident_card *card = (struct trident_card *)codec->private_data;
+ unsigned int address, mask, busy;
+ unsigned short count = 0xffff;
+ unsigned long flags;
+ u32 data;
+
+ switch (card->pci_id)
+ {
+ default:
+ case PCI_DEVICE_ID_SI_7018:
+ address = SI_AC97_READ;
+ mask = SI_AC97_BUSY_READ | SI_AC97_AUDIO_BUSY;
+ if (codec->id)
+ mask |= SI_AC97_SECONDARY;
+ busy = SI_AC97_BUSY_READ;
+ break;
+ case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
+ address = DX_ACR1_AC97_R;
+ mask = busy = DX_AC97_BUSY_READ;
+ break;
+ case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
+ if (codec->id)
+ address = NX_ACR3_AC97_R_SECONDARY;
+ else
+ address = NX_ACR2_AC97_R_PRIMARY;
+ mask = NX_AC97_BUSY_READ;
+ busy = 0x0c00;
+ break;
+ }
+
+ data = (mask | (reg & AC97_REG_ADDR));
+
+ spin_lock_irqsave(&card->lock, flags);
+ outl(data, TRID_REG(card, address));
+ do {
+ data = inl(TRID_REG(card, address));
+ if ((data & busy) == 0)
+ break;
+ } while (count--);
+ spin_unlock_irqrestore(&card->lock, flags);
+
+ if (count == 0) {
+ printk(KERN_ERR "trident: AC97 CODEC read timed out.\n");
+ data = 0;
+ }
+ return ((u16) (data >> 16));
+}
+
+/* OSS /dev/mixer file operation methods */
+static int trident_open_mixdev(struct inode *inode, struct file *file)
{
int i;
+ int minor = MINOR(inode->i_rdev);
+ struct trident_card *card = devs;
+
+ for (card = devs; card != NULL; card = card->next)
+ for (i = 0; i < NR_AC97; i++)
+ if (card->ac97_codec[i] != NULL &&
+ card->ac97_codec[i]->dev_mixer == minor)
+ goto match;
+
+ if (!card)
+ return -ENODEV;
+
+ match:
+ file->private_data = card->ac97_codec[i];
+
+ //FIXME put back in
+ //MOD_INC_USE_COUNT;
+ return 0;
+}
+
+static int trident_release_mixdev(struct inode *inode, struct file *file)
+{
+ //struct ac97_codec *codec = (struct ac97_codec *)file->private_data;
+
+ //FIXME put back in
+ //MOD_DEC_USE_COUNT;
+ return 0;
+}
+
+static int trident_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct ac97_codec *codec = (struct ac97_codec *)file->private_data;
+
+ return codec->mixer_ioctl(codec, cmd, arg);
+}
+
+static /*const*/ struct file_operations trident_mixer_fops = {
+ &trident_llseek,
+ NULL, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* poll */
+ &trident_ioctl_mixdev,
+ NULL, /* mmap */
+ &trident_open_mixdev,
+ NULL, /* flush */
+ &trident_release_mixdev,
+ NULL, /* fsync */
+ NULL, /* fasync */
+ NULL, /* lock */
+};
+
+/* AC97 codec initialisation. */
+static int __init trident_ac97_init(struct trident_card *card)
+{
+ int num_ac97 = 0;
+ int ready_2nd = 0;
+ struct ac97_codec *codec;
+
+ /* initialize controller side of AC link, and find out if secondary codes
+ really exist */
+ switch (card->pci_id)
+ {
+ case PCI_DEVICE_ID_SI_7018:
+ /* disable AC97 GPIO interrupt */
+ outl(0x00, TRID_REG(card, SI_AC97_GPIO));
+ /* stop AC97 cold reset process */
+ outl(PCMOUT|SECONDARY_ID, TRID_REG(card, SI_SERIAL_INTF_CTRL));
+ ready_2nd = inl(TRID_REG(card, SI_SERIAL_INTF_CTRL));
+ ready_2nd &= SI_AC97_SECONDARY_READY;
+ break;
+ case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
+ /* playback on */
+ outl(DX_AC97_PLAYBACK, TRID_REG(card, DX_ACR2_AC97_COM_STAT));
+ break;
+ case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
+ /* enable AC97 Output Slot 3,4 (PCM Left/Right Playback) */
+ outl(NX_AC97_PCM_OUTPUT, TRID_REG(card, NX_ACR0_AC97_COM_STAT));
+ ready_2nd = inl(TRID_REG(card, NX_ACR0_AC97_COM_STAT));
+ ready_2nd &= NX_AC97_SECONDARY_READY;
+ break;
+ }
+
+ for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
+ if ((codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL)) == NULL)
+ return -1;
+ memset(codec, 0, sizeof(struct ac97_codec));
+
+ /* initialize some basic codec information, other fields will be filled
+ in ac97_probe_codec */
+ codec->private_data = card;
+ codec->id = num_ac97;
+ /* controller specific low level AC97 access function */
+ codec->codec_read = trident_ac97_get;
+ codec->codec_write = trident_ac97_set;
+
+ if (ac97_probe_codec(codec) == 0)
+ break;
+
+ if ((codec->dev_mixer = register_sound_mixer(&trident_mixer_fops, -1)) < 0) {
+ printk(KERN_ERR "trident: couldn't register mixer!\n");
+ kfree(codec);
+ break;
+ }
+
+ card->ac97_codec[num_ac97] = codec;
+
+ /* if there is no secondary codec at all, don't probe any more */
+ if (!ready_2nd)
+ return num_ac97+1;
+ }
+
+ return num_ac97;
+}
+
+/* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered
+ untill "ACCESS" time (in prog_dmabuf calles by open/read/write/ioctl/mmap) */
+static int __init trident_install(struct pci_dev *pcidev, struct pci_audio_info *pci_info)
+{
u16 w;
unsigned long iobase;
struct trident_card *card;
- u32 ChanDwordCount;
iobase = pcidev->resource[0].start;
if (check_region(iobase, 256)) {
@@ -2847,30 +2110,12 @@ static int trident_install(struct pci_dev *pcidev, struct pci_audio_info *pci_in
card->irq = pcidev->irq;
card->next = devs;
card->magic = TRIDENT_CARD_MAGIC;
+ card->banks[BANK_A].addresses = &bank_a_addrs;
+ card->banks[BANK_A].bitmap = 0UL;
+ card->banks[BANK_B].addresses = &bank_b_addrs;
+ card->banks[BANK_B].bitmap = 0UL;
spin_lock_init(&card->lock);
- devs = card;
-
- /* ungly stupid thing, remove ASAP */
- ChanDwordCount = card->ChanDwordCount = 2;
- card->ChRegs.lpChStart = card->ChRegs.data;
- card->ChRegs.lpChStop = card->ChRegs.lpChStart + ChanDwordCount;
- card->ChRegs.lpChAint = card->ChRegs.lpChStop + ChanDwordCount;
- card->ChRegs.lpChAinten = card->ChRegs.lpChAint + ChanDwordCount;
- card->ChRegs.lpAChStart = card->ChRegs.lpChAinten + ChanDwordCount;
- card->ChRegs.lpAChStop = card->ChRegs.lpAChStart + ChanDwordCount;
- card->ChRegs.lpAChAint = card->ChRegs.lpAChStop + ChanDwordCount;
- card->ChRegs.lpAChAinten = card->ChRegs.lpAChAint + ChanDwordCount;
- // Assign Bank A addresses.
- card->ChRegs.lpAChStart[0] = T4D_START_A;
- card->ChRegs.lpAChStop[0] = T4D_STOP_A;
- card->ChRegs.lpAChAint[0] = T4D_AINT_A;
- card->ChRegs.lpAChAinten[0] = T4D_AINTEN_A;
- /* Assign Bank B addresses */
- card->ChRegs.lpAChStart[1] = T4D_START_B;
- card->ChRegs.lpAChStop[1] = T4D_STOP_B;
- card->ChRegs.lpAChAint[1] = T4D_AINT_B;
- card->ChRegs.lpAChAinten[1] = T4D_AINTEN_B;
-
+ devs = card;
printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n",
card->pci_info->name, card->iobase, card->irq);
@@ -2883,11 +2128,6 @@ static int trident_install(struct pci_dev *pcidev, struct pci_audio_info *pci_in
kfree(card);
return 0;
}
-
- /* initilize AC97 codec */
- trident_ac97_init(card);
- outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL));
-
/* register /dev/dsp */
if ((card->dev_audio = register_sound_dsp(&trident_audio_fops, -1)) < 0) {
printk(KERN_ERR "trident: coundn't register DSP device!\n");
@@ -2896,29 +2136,18 @@ static int trident_install(struct pci_dev *pcidev, struct pci_audio_info *pci_in
kfree(card);
return 0;
}
- /* register /dev/mixer */
- if ((card->dev_mixer = register_sound_mixer(&trident_mixer_fops, -1)) < 0) {
- printk(KERN_ERR "trident: couldn't register mixer!\n");
+ /* initilize AC97 codec and register /dev/mixer */
+ if (trident_ac97_init(card) <= 0) {
unregister_sound_dsp(card->dev_audio);
release_region(iobase, 256);
free_irq(card->irq, card);
kfree(card);
return 0;
- } else {
- /* initilize mixer channels */
- for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
- struct mixer_defaults *md = &mixer_defaults[i];
- if (md->mixer == -1)
- break;
- if (!supported_mixer(card, md->mixer))
- continue;
- set_mixer(card, md->mixer, md->value);
- }
}
+ outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL));
/* Enable Address Engine Interrupts */
- trident_enable_end_interrupts(card);
- trident_enable_middle_interrupts(card);
+ trident_enable_loop_interrupts(card);
return 1;
}
@@ -2952,23 +2181,23 @@ static int __init init_trident(void)
MODULE_AUTHOR("Alan Cox, Aaron Holtzman, Ollie Lho");
MODULE_DESCRIPTION("Trident 4DWave/SiS 7018 PCI Audio Driver");
-#ifdef DEBUG
-MODULE_PARM(debug,"i");
-#endif
-
static void __exit cleanup_trident(void)
{
while (devs != NULL) {
+ int i;
/* Kill interrupts, and SP/DIF */
- trident_disable_end_interrupts(devs);
- trident_enable_middle_interrupts(devs);
+ trident_disable_loop_interrupts(devs);
/* free hardware resources */
free_irq(devs->irq, devs);
release_region(devs->iobase, 256);
/* unregister audio devices */
- unregister_sound_mixer(devs->dev_mixer);
+ for (i = 0; i < NR_AC97; i++)
+ if (devs->ac97_codec[i] != NULL) {
+ unregister_sound_mixer(devs->ac97_codec[i]->dev_mixer);
+ kfree (devs->ac97_codec[i]);
+ }
unregister_sound_dsp(devs->dev_audio);
kfree(devs);
@@ -2978,5 +2207,3 @@ static void __exit cleanup_trident(void)
module_init(init_trident);
module_exit(cleanup_trident);
-
-
diff --git a/drivers/sound/trident.h b/drivers/sound/trident.h
index a22e60650..4504cb303 100644
--- a/drivers/sound/trident.h
+++ b/drivers/sound/trident.h
@@ -23,6 +23,7 @@
*
*/
+/* PCI vendor and device ID */
#ifndef PCI_VENDOR_ID_TRIDENT
#define PCI_VENDOR_ID_TRIDENT 0x1023
#endif
@@ -43,118 +44,101 @@
#define PCI_DEVICE_ID_SI_7018 0x7018
#endif
-/*
- * Direct registers
- */
-
#ifndef FALSE
-#define FALSE 0
-#define TRUE 1
+#define FALSE 0
+#define TRUE 1
#endif
-#define TRID_REG( trident, x ) ( (trident) -> iobase + (x) )
-
#define CHANNEL_REGS 5
#define CHANNEL_START 0xe0 // The first bytes of the contiguous register space.
-#define BANK_A 0
-#define BANK_B 1
-#define NUM_BANKS 2
-
-#define ID_4DWAVE_DX 0x2000
-#define ID_4DWAVE_NX 0x2001
-#define ID_SI_7018 0x7018
-
-// Register definitions
-
-// Global registers
-
-// T2 legacy dma control registers.
-#define LEGACY_DMAR0 0x00 // ADR0
-#define LEGACY_DMAR4 0x04 // CNT0
-#define LEGACY_DMAR11 0x0b // MOD
-#define LEGACY_DMAR15 0x0f // MMR
-
-#define T4D_START_A 0x80
-#define T4D_STOP_A 0x84
-#define T4D_DLY_A 0x88
-#define T4D_SIGN_CSO_A 0x8c
-#define T4D_CSPF_A 0x90
-#define T4D_CEBC_A 0x94
-#define T4D_AINT_A 0x98
-#define T4D_EINT_A 0x9c
-#define T4D_LFO_GC_CIR 0xa0
-#define T4D_AINTEN_A 0xa4
-#define T4D_MUSICVOL_WAVEVOL 0xa8
-#define T4D_SBDELTA_DELTA_R 0xac
-#define T4D_MISCINT 0xb0
-#define T4D_START_B 0xb4
-#define T4D_STOP_B 0xb8
-#define T4D_CSPF_B 0xbc
-#define T4D_SBBL_SBCL 0xc0
-#define T4D_SBCTRL_SBE2R_SBDD 0xc4
-#define T4D_STIMER 0xc8
-#define T4D_LFO_B_I2S_DELTA 0xcc
-#define T4D_AINT_B 0xd8
-#define T4D_AINTEN_B 0xdc
-
-// MPU-401 UART
-#define T4D_MPU401_BASE 0x20
-#define T4D_MPUR0 0x20
-#define T4D_MPUR1 0x21
-#define T4D_MPUR2 0x22
-#define T4D_MPUR3 0x23
-
-// S/PDIF Registers
-#define NX_SPCTRL_SPCSO 0x24
-#define NX_SPLBA 0x28
-#define NX_SPESO 0x2c
-#define NX_SPCSTATUS 0x64
-
-// Channel Registers
-
-#define CH_DX_CSO_ALPHA_FMS 0xe0
-#define CH_DX_ESO_DELTA 0xe8
-#define CH_DX_FMC_RVOL_CVOL 0xec
-
-#define CH_NX_DELTA_CSO 0xe0
-#define CH_NX_DELTA_ESO 0xe8
-#define CH_NX_ALPHA_FMS_FMC_RVOL_CVOL 0xec
-
-#define CH_LBA 0xe4
-#define CH_GVSEL_PAN_VOL_CTRL_EC 0xf0
-
-// AC-97 Registers
-
-#define DX_ACR0_AC97_W 0x40
-#define DX_ACR1_AC97_R 0x44
-#define DX_ACR2_AC97_COM_STAT 0x48
-
-#define NX_ACR0_AC97_COM_STAT 0x40
-#define NX_ACR1_AC97_W 0x44
-#define NX_ACR2_AC97_R_PRIMARY 0x48
-#define NX_ACR3_AC97_R_SECONDARY 0x4c
-
-#define SI_AC97_WRITE 0x40
-#define SI_AC97_READ 0x44
-#define SI_SERIAL_INTF_CTRL 0x48
-#define SI_AC97_GPIO 0x4c
+#define BANK_A 0
+#define BANK_B 1
+#define NR_BANKS 2
+
+#define TRIDENT_FMT_STEREO 0x01
+#define TRIDENT_FMT_16BIT 0x02
+#define TRIDENT_FMT_MASK 0x03
+
+#define DMA_ENABLE 0x01
+#define DMA_RUNNING 0x02
+
+/* Register Addresses */
+
+/* operational registers common to DX, NX, 7018 */
+enum trident_op_registers {
+ T4D_START_A = 0x80, T4D_STOP_A = 0x84,
+ T4D_DLY_A = 0x88, T4D_SIGN_CSO_A = 0x8c,
+ T4D_CSPF_A = 0x90, T4D_CEBC_A = 0x94,
+ T4D_AINT_A = 0x98, T4D_EINT_A = 0x9c,
+ T4D_LFO_GC_CIR = 0xa0, T4D_AINTEN_A = 0xa4,
+ T4D_MUSICVOL_WAVEVOL = 0xa8, T4D_SBDELTA_DELTA_R = 0xac,
+ T4D_MISCINT = 0xb0, T4D_START_B = 0xb4,
+ T4D_STOP_B = 0xb8, T4D_CSPF_B = 0xbc,
+ T4D_SBBL_SBCL = 0xc0, T4D_SBCTRL_SBE2R_SBDD = 0xc4,
+ T4D_STIMER = 0xc8, T4D_LFO_B_I2S_DELTA = 0xcc,
+ T4D_AINT_B = 0xd8, T4D_AINTEN_B = 0xdc
+};
-#define AC97_SIGMATEL_DAC2INVERT 0x6E
-#define AC97_SIGMATEL_BIAS1 0x70
-#define AC97_SIGMATEL_BIAS2 0x72
-#define AC97_SIGMATEL_CIC1 0x76
-#define AC97_SIGMATEL_CIC2 0x78
+/* S/PDIF Operational Registers for 4D-NX */
+enum nx_spdif_registers {
+ NX_SPCTRL_SPCSO = 0x24, NX_SPLBA = 0x28,
+ NX_SPESO = 0x2c, NX_SPCSTATUS = 0x64
+};
+
+/* OP registers to access each hardware channel */
+enum channel_registers {
+ CH_DX_CSO_ALPHA_FMS = 0xe0, CH_DX_ESO_DELTA = 0xe8,
+ CH_DX_FMC_RVOL_CVOL = 0xec,
+ CH_NX_DELTA_CSO = 0xe0, CH_NX_DELTA_ESO = 0xe8,
+ CH_NX_ALPHA_FMS_FMC_RVOL_CVOL = 0xec,
+ CH_LBA = 0xe4,
+ CH_GVSEL_PAN_VOL_CTRL_EC = 0xf0
+};
+
+/* registers to read/write/control AC97 codec */
+enum dx_ac97_registers {
+ DX_ACR0_AC97_W = 0x40, DX_ACR1_AC97_R = 0x44,
+ DX_ACR2_AC97_COM_STAT = 0x48
+};
-#define SI_AC97_BUSY_WRITE 0x8000
-#define SI_AC97_AUDIO_BUSY 0x4000
-#define DX_AC97_BUSY_WRITE 0x8000
-#define NX_AC97_BUSY_WRITE 0x0800
-#define SI_AC97_BUSY_READ 0x8000
-#define DX_AC97_BUSY_READ 0x8000
-#define NX_AC97_BUSY_READ 0x0800
+enum nx_ac97_registers {
+ NX_ACR0_AC97_COM_STAT = 0x40, NX_ACR1_AC97_W = 0x44,
+ NX_ACR2_AC97_R_PRIMARY = 0x48, NX_ACR3_AC97_R_SECONDARY = 0x4c
+};
+
+enum si_ac97_registers {
+ SI_AC97_WRITE = 0x40, SI_AC97_READ = 0x44,
+ SI_SERIAL_INTF_CTRL = 0x48, SI_AC97_GPIO = 0x4c
+};
+
+/* Bit mask for operational registers */
#define AC97_REG_ADDR 0x000000ff
+enum sis7018_ac97_bits {
+ SI_AC97_BUSY_WRITE = 0x8000, SI_AC97_BUSY_READ = 0x8000,
+ SI_AC97_AUDIO_BUSY = 0x4000, SI_AC97_MODEM_BUSY = 0x2000,
+ SI_AC97_SECONDARY = 0x0080
+};
+
+enum trident_dx_ac97_bits {
+ DX_AC97_BUSY_WRITE = 0x8000, DX_AC97_BUSY_READ = 0x8000,
+ DX_AC97_READY = 0x0010, DX_AC97_RECORD = 0x0008,
+ DX_AC97_PLAYBACK = 0x0002
+};
+
+enum trident_nx_ac97_bits {
+ /* ACR1-3 */
+ NX_AC97_BUSY_WRITE = 0x0800, NX_AC97_BUSY_READ = 0x0800,
+ NX_AC97_WRITE_SECONDARY = 0x0100,
+ /* ACR0 */
+ NX_AC97_SECONDARY_READY = 0x0040, NX_AC97_SECONDARY_RECORD = 0x0020,
+ NX_AC97_SURROUND_OUTPUT = 0x0010,
+ NX_AC97_PRIMARY_READY = 0x0008, NX_AC97_PRIMARY_RECORD = 0x0004,
+ NX_AC97_PCM_OUTPUT = 0x0002,
+ NX_AC97_WARM_RESET = 0x0001
+};
+
enum serial_intf_ctrl_bits {
WARM_REST = 0x00000001, COLD_RESET = 0x00000002,
I2S_CLOCK = 0x00000004, PCM_SEC_AC97= 0x00000008,
@@ -162,6 +146,16 @@ enum serial_intf_ctrl_bits {
I2S_OUTPUT_EN = 0x00000040, I2S_INPUT_EN = 0x00000080,
PCMIN = 0x00000100, LINE1IN = 0x00000200,
MICIN = 0x00000400, LINE2IN = 0x00000800,
+ HEAD_SET_IN = 0x00001000, GPIOIN = 0x00002000,
+ /* 7018 spec says id = 01 but the demo board routed to 10
+ SECONDARY_ID= 0x00008000, */
+ SECONDARY_ID= 0x00004000,
+ PCMOUT = 0x00010000, SURROUT = 0x00020000,
+ CENTEROUT = 0x00040000, LFEOUT = 0x00080000,
+ LINE1OUT = 0x00100000, LINE2OUT = 0x00200000,
+ GPIOOUT = 0x00400000,
+ SI_AC97_PRIMARY_READY = 0x01000000,
+ SI_AC97_SECONDARY_READY = 0x02000000,
};
enum global_control_bits {
@@ -173,6 +167,18 @@ enum global_control_bits {
EDROP_IE = 0x00008000, BANK_B_EN = 0x00010000
};
+enum channel_control_bits {
+ CHANNEL_LOOP = 0x00001000, CHANNEL_SIGNED = 0x00002000,
+ CHANNEL_STEREO = 0x00004000, CHANNEL_16BITS = 0x00008000,
+};
+
+enum channel_attribute {
+ MODEM_LINE1, MODEM_LINE2, PCM_LR, HSET,
+ I2SLR, CENTER_LFE, SURR_LR, SPDIF_LR,
+ CHANNEL_PB = 0x00000000, CHANNEL_SPC_PB = 0x40000000,
+ CHANNEL_REC = 0x80000000, CHANNEL_REC_PB = 0xc0000000
+};
+
enum miscint_bits {
PB_UNDERRUN_IRO = 0x00000001, REC_OVERRUN_IRQ = 0x00000002,
SB_IRQ = 0x00000004, MPU401_IRQ = 0x00000008,
@@ -184,31 +190,13 @@ enum miscint_bits {
ST_IRQ_EN = 0x00800000, ACGPIO_IRQ = 0x01000000
};
-#define IWriteAinten( x ) \
- {int i; \
- for( i= 0; i < ChanDwordCount; i++) \
- outl((x)->lpChAinten[i], TRID_REG(trident, (x)->lpAChAinten[i]));}
-
-#define IReadAinten( x ) \
- {int i; \
- for( i= 0; i < ChanDwordCount; i++) \
- (x)->lpChAinten[i] = inl(TRID_REG(trident, (x)->lpAChAinten[i]));}
-
-#define ReadAint( x ) \
- IReadAint( x )
-
-#define WriteAint( x ) \
- IWriteAint( x )
-
-#define IWriteAint( x ) \
- {int i; \
- for( i= 0; i < ChanDwordCount; i++) \
- outl((x)->lpChAint[i], TRID_REG(trident, (x)->lpAChAint[i]));}
+#define AC97_SIGMATEL_DAC2INVERT 0x6E
+#define AC97_SIGMATEL_BIAS1 0x70
+#define AC97_SIGMATEL_BIAS2 0x72
+#define AC97_SIGMATEL_CIC1 0x76
+#define AC97_SIGMATEL_CIC2 0x78
-#define IReadAint( x ) \
- {int i; \
- for( i= 0; i < ChanDwordCount; i++) \
- (x)->lpChAint[i] = inl(TRID_REG(trident, (x)->lpAChAint[i]));}
+#define TRID_REG( trident, x ) ( (trident) -> iobase + (x) )
#define VALIDATE_MAGIC(FOO,MAG) \
({ \
@@ -221,5 +209,31 @@ enum miscint_bits {
#define VALIDATE_STATE(a) VALIDATE_MAGIC(a,TRIDENT_STATE_MAGIC)
#define VALIDATE_CARD(a) VALIDATE_MAGIC(a,TRIDENT_CARD_MAGIC)
+
+extern __inline__ unsigned ld2(unsigned int x)
+{
+ unsigned r = 0;
+
+ if (x >= 0x10000) {
+ x >>= 16;
+ r += 16;
+ }
+ if (x >= 0x100) {
+ x >>= 8;
+ r += 8;
+ }
+ if (x >= 0x10) {
+ x >>= 4;
+ r += 4;
+ }
+ if (x >= 4) {
+ x >>= 2;
+ r += 2;
+ }
+ if (x >= 2)
+ r++;
+ return r;
+}
+
#endif /* __TRID4DWAVE_H */
diff --git a/drivers/usb/Config.in b/drivers/usb/Config.in
index aa8c6adb2..bb812ea90 100644
--- a/drivers/usb/Config.in
+++ b/drivers/usb/Config.in
@@ -9,6 +9,7 @@ if [ ! "$CONFIG_USB" = "n" ]; then
comment 'USB Controllers'
dep_tristate ' UHCI (Intel PIIX4, VIA, ...) support' CONFIG_USB_UHCI $CONFIG_USB
+ dep_tristate ' UHCI Alternate Driver (JE) support' CONFIG_USB_UHCI_ALT $CONFIG_USB
dep_tristate ' OHCI (Compaq, iMacs, OPTi, SiS, ALi, ...) support' CONFIG_USB_OHCI $CONFIG_USB
comment 'Miscellaneous USB options'
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index ee2cee37a..c43a41a31 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -45,6 +45,7 @@ obj- :=
obj-$(CONFIG_USB) += usbcore.o
obj-$(CONFIG_USB_UHCI) += usb-uhci.o
+obj-$(CONFIG_USB_UHCI_ALT) += uhci.o
obj-$(CONFIG_USB_OHCI) += usb-ohci.o
obj-$(CONFIG_USB_MOUSE) += usbmouse.o input.o
@@ -107,3 +108,4 @@ usbcore.o: $(usbcore-objs)
usb-storage.o: $(usb-storage-objs)
$(LD) -r -o $@ $(usb-storage-objs)
+
diff --git a/drivers/usb/acm.c b/drivers/usb/acm.c
index 154d5cd22..1459f1d10 100644
--- a/drivers/usb/acm.c
+++ b/drivers/usb/acm.c
@@ -1,5 +1,5 @@
/*
- * acm.c Version 0.14
+ * acm.c Version 0.15
*
* Copyright (c) 1999 Armin Fuerst <fuerst@in.tum.de>
* Copyright (c) 1999 Pavel Machek <pavel@suse.cz>
@@ -17,6 +17,7 @@
* v0.12 - added TIOCM ioctls, added break handling, made struct acm kmalloced
* v0.13 - added termios, added hangup
* v0.14 - sized down struct acm
+ * v0.15 - fixed flow control again - characters could be lost
*/
/*
@@ -137,6 +138,7 @@ struct acm {
unsigned int writesize; /* max packet size for the output bulk endpoint */
unsigned int used; /* someone has this acm's device open */
unsigned int minor; /* acm minor number */
+ unsigned char throttle; /* throttled by tty layer */
unsigned char clocal; /* termios CLOCAL */
};
@@ -210,8 +212,6 @@ static void acm_ctrl_irq(struct urb *urb)
dr->request, dr->index, dr->length, data[0], data[1]);
return;
}
-
- return;
}
static void acm_read_bulk(struct urb *urb)
@@ -219,24 +219,25 @@ static void acm_read_bulk(struct urb *urb)
struct acm *acm = urb->context;
struct tty_struct *tty = acm->tty;
unsigned char *data = urb->transfer_buffer;
- int i;
+ int i = 0;
if (!ACM_READY(acm)) return;
- if (!urb->status) {
-
- for (i = 0; i < urb->actual_length; i++)
+ if (!urb->status & !acm->throttle) {
+ for (i = 0; i < urb->actual_length && !acm->throttle; i++)
tty_insert_flip_char(tty, data[i], 0);
-
tty_flip_buffer_push(tty);
-
} else
dbg("nonzero read bulk status received: %d", urb->status);
- if (usb_submit_urb(urb))
- dbg("failed resubmitting read urb");
-
- return;
+ if (!acm->throttle) {
+ urb->actual_length = 0;
+ if (usb_submit_urb(urb))
+ dbg("failed resubmitting read urb");
+ } else {
+ memmove(data, data + i, urb->actual_length - i);
+ urb->actual_length -= i;
+ }
}
static void acm_write_bulk(struct urb *urb)
@@ -253,8 +254,6 @@ static void acm_write_bulk(struct urb *urb)
(tty->ldisc.write_wakeup)(tty);
wake_up_interruptible(&tty->write_wait);
-
- return;
}
/*
@@ -347,15 +346,16 @@ static void acm_tty_throttle(struct tty_struct *tty)
{
struct acm *acm = tty->driver_data;
if (!ACM_READY(acm)) return;
- usb_unlink_urb(&acm->readurb);
+ acm->throttle = 1;
}
static void acm_tty_unthrottle(struct tty_struct *tty)
{
struct acm *acm = tty->driver_data;
if (!ACM_READY(acm)) return;
- if (usb_submit_urb(&acm->readurb))
- dbg("usb_submit_urb(read bulk) in unthrottle() failed");
+ acm->throttle = 0;
+ if (acm->readurb.status != -EINPROGRESS)
+ acm_read_bulk(&acm->readurb);
}
static void acm_tty_break_ctl(struct tty_struct *tty, int state)
diff --git a/drivers/usb/ov511.c b/drivers/usb/ov511.c
index 6ec72d502..6dacc46b4 100644
--- a/drivers/usb/ov511.c
+++ b/drivers/usb/ov511.c
@@ -931,7 +931,7 @@ static int ov511_init_isoc(struct usb_ov511 *ov511)
err("ov511_init_isoc: usb_run_isoc(0) ret %d", err);
err = usb_submit_urb(ov511->sbuf[1].urb);
if (err)
- err("ov511_init_isoc: usb_run_isoc(1) ret %d\n", err);
+ err("ov511_init_isoc: usb_run_isoc(1) ret %d", err);
ov511->streaming = 1;
diff --git a/drivers/usb/printer.c b/drivers/usb/printer.c
index 370ed6dd6..a00a9f037 100644
--- a/drivers/usb/printer.c
+++ b/drivers/usb/printer.c
@@ -125,15 +125,15 @@ static int usblp_check_status(struct usblp *usblp)
if (status & LP_PERRORP) {
if (status & LP_POUTPA) {
- printk(KERN_INFO "usblp%d: out of paper", usblp->minor);
+ info("usblp%d: out of paper", usblp->minor);
return -ENOSPC;
}
if (~status & LP_PSELECD) {
- printk(KERN_INFO "usblp%d: off-line", usblp->minor);
+ info("usblp%d: off-line", usblp->minor);
return -EIO;
}
if (~status & LP_PERRORP) {
- printk(KERN_INFO "usblp%d: on fire", usblp->minor);
+ info("usblp%d: on fire", usblp->minor);
return -EIO;
}
}
@@ -229,18 +229,19 @@ static ssize_t usblp_write(struct file *file, const char *buffer, size_t count,
if (usblp->writeurb.status == -EINPROGRESS) {
usb_unlink_urb(&usblp->writeurb);
- printk(KERN_ERR "usblp%d: timed out\n", usblp->minor);
+ err("usblp%d: timed out", usblp->minor);
return -EIO;
}
if (!usblp->dev)
return -ENODEV;
- if (!usblp->writeurb.status)
+ if (!usblp->writeurb.status) {
writecount += usblp->writeurb.transfer_buffer_length;
- else {
+ usblp->writeurb.transfer_buffer_length = 0;
+ } else {
if (!(retval = usblp_check_status(usblp))) {
- printk(KERN_ERR "usblp%d: error %d writing to printer\n",
+ err("usblp%d: error %d writing to printer",
usblp->minor, usblp->writeurb.status);
return -EIO;
}
@@ -287,7 +288,7 @@ static ssize_t usblp_read(struct file *file, char *buffer, size_t count, loff_t
return -ENODEV;
if (usblp->readurb.status) {
- printk(KERN_ERR "usblp%d: error %d reading from printer\n",
+ err("usblp%d: error %d reading from printer",
usblp->minor, usblp->readurb.status);
usb_submit_urb(&usblp->readurb);
return -EIO;
@@ -389,7 +390,7 @@ static void *usblp_probe(struct usb_device *dev, unsigned int ifnum)
buf + USBLP_BUF_SIZE, USBLP_BUF_SIZE, usblp_bulk, usblp);
}
- printk(KERN_INFO "usblp%d: USB %sdirectional printer dev %d if %d alt %d\n",
+ info("usblp%d: USB %sdirectional printer dev %d if %d alt %d",
minor, bidir ? "Bi" : "Uni", dev->devnum, ifnum, alts);
return usblp_table[minor] = usblp;
diff --git a/drivers/usb/scanner.c b/drivers/usb/scanner.c
index ec45a6fb9..e707d23e8 100644
--- a/drivers/usb/scanner.c
+++ b/drivers/usb/scanner.c
@@ -331,7 +331,6 @@ probe_scanner(struct usb_device *dev, unsigned int ifnum)
int ep_cnt;
- char *ident;
char valid_device = 0;
char have_bulk_in, have_bulk_out, have_intr;
diff --git a/drivers/usb/uhci-debug.h b/drivers/usb/uhci-debug.h
index 73d16937a..9d715d4d8 100644
--- a/drivers/usb/uhci-debug.h
+++ b/drivers/usb/uhci-debug.h
@@ -1,195 +1,260 @@
-#ifdef DEBUG
+/*
+ * UHCI-specific debugging code. Invaluable when something
+ * goes wrong, but don't get in my face.
+ *
+ * Kernel visible pointers are surrounded in []'s and bus
+ * visible pointers are surrounded in ()'s
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ * (C) Copyright 1999 Johannes Erdfelt
+ */
-static void uhci_show_qh (puhci_desc_t qh)
+#include <linux/kernel.h>
+#include <asm/io.h>
+
+#include "uhci.h"
+
+void uhci_show_td(struct uhci_td * td)
{
- if (qh->type != QH_TYPE) {
- dbg("qh has not QH_TYPE");
- return;
- }
- dbg("uhci_show_qh %p (%08lX):", qh, virt_to_bus (qh));
+ char *spid;
- if (qh->hw.qh.head & UHCI_PTR_TERM)
- dbg("Head Terminate");
- else {
- if (qh->hw.qh.head & UHCI_PTR_QH)
- dbg("Head points to QH");
- else
- dbg("Head points to TD");
+ printk("%08x ", td->link);
+ printk("e%d %s%s%s%s%s%s%s%s%s%sLength=%x ",
+ ((td->status >> 27) & 3),
+ (td->status & TD_CTRL_SPD) ? "SPD " : "",
+ (td->status & TD_CTRL_LS) ? "LS " : "",
+ (td->status & TD_CTRL_IOC) ? "IOC " : "",
+ (td->status & TD_CTRL_ACTIVE) ? "Active " : "",
+ (td->status & TD_CTRL_STALLED) ? "Stalled " : "",
+ (td->status & TD_CTRL_DBUFERR) ? "DataBufErr " : "",
+ (td->status & TD_CTRL_BABBLE) ? "Babble " : "",
+ (td->status & TD_CTRL_NAK) ? "NAK " : "",
+ (td->status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "",
+ (td->status & TD_CTRL_BITSTUFF) ? "BitStuff " : "",
+ td->status & 0x7ff);
- dbg("head: %08X", qh->hw.qh.head & ~UHCI_PTR_BITS);
- }
- if (qh->hw.qh.element & UHCI_PTR_TERM)
- dbg("Element Terminate");
- else {
-
- if (qh->hw.qh.element & UHCI_PTR_QH)
- dbg("Element points to QH");
- else
- dbg("Element points to TD");
- dbg("element: %08X", qh->hw.qh.element & ~UHCI_PTR_BITS);
+ switch (td->info & 0xff) {
+ case USB_PID_SETUP:
+ spid = "SETUP";
+ break;
+ case USB_PID_OUT:
+ spid = "OUT";
+ break;
+ case USB_PID_IN:
+ spid = "IN";
+ break;
+ default:
+ spid = "?";
+ break;
}
+
+ printk("MaxLen=%x DT%d EndPt=%x Dev=%x, PID=%x(%s) ",
+ td->info >> 21,
+ ((td->info >> 19) & 1),
+ (td->info >> 15) & 15,
+ (td->info >> 8) & 127,
+ (td->info & 0xff),
+ spid);
+ printk("(buf=%08x)\n", td->buffer);
}
-#endif
-static void uhci_show_td (puhci_desc_t td)
+static void uhci_show_sc(int port, unsigned short status)
{
- char *spid;
- warn("uhci_show_td %p (%08lX) ", td, virt_to_bus (td));
-
- switch (td->hw.td.info & 0xff) {
- case USB_PID_SETUP:
- spid = "SETUP";
- break;
- case USB_PID_OUT:
- spid = " OUT ";
- break;
- case USB_PID_IN:
- spid = " IN ";
- break;
- default:
- spid = " ? ";
- break;
- }
+ printk(" stat%d = %04x %s%s%s%s%s%s%s%s\n",
+ port,
+ status,
+ (status & USBPORTSC_SUSP) ? "PortSuspend " : "",
+ (status & USBPORTSC_PR) ? "PortReset " : "",
+ (status & USBPORTSC_LSDA) ? "LowSpeed " : "",
+ (status & USBPORTSC_RD) ? "ResumeDetect " : "",
+ (status & USBPORTSC_PEC) ? "EnableChange " : "",
+ (status & USBPORTSC_PE) ? "PortEnabled " : "",
+ (status & USBPORTSC_CSC) ? "ConnectChange " : "",
+ (status & USBPORTSC_CCS) ? "PortConnected " : "");
+}
- warn("MaxLen=%02x DT%d EndPt=%x Dev=%x, PID=%x(%s) (buf=%08x)",
- td->hw.td.info >> 21,
- ((td->hw.td.info >> 19) & 1),
- (td->hw.td.info >> 15) & 15,
- (td->hw.td.info >> 8) & 127,
- (td->hw.td.info & 0xff),
- spid,
- td->hw.td.buffer);
-
- warn("Len=%02x e%d %s%s%s%s%s%s%s%s%s%s",
- td->hw.td.status & 0x7ff,
- ((td->hw.td.status >> 27) & 3),
- (td->hw.td.status & TD_CTRL_SPD) ? "SPD " : "",
- (td->hw.td.status & TD_CTRL_LS) ? "LS " : "",
- (td->hw.td.status & TD_CTRL_IOC) ? "IOC " : "",
- (td->hw.td.status & TD_CTRL_ACTIVE) ? "Active " : "",
- (td->hw.td.status & TD_CTRL_STALLED) ? "Stalled " : "",
- (td->hw.td.status & TD_CTRL_DBUFERR) ? "DataBufErr " : "",
- (td->hw.td.status & TD_CTRL_BABBLE) ? "Babble " : "",
- (td->hw.td.status & TD_CTRL_NAK) ? "NAK " : "",
- (td->hw.td.status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "",
- (td->hw.td.status & TD_CTRL_BITSTUFF) ? "BitStuff " : ""
- );
-#if 1
- if (td->hw.td.link & UHCI_PTR_TERM)
- warn("Link Terminate");
- else {
- if (td->hw.td.link & UHCI_PTR_QH)
- warn("%s, link points to QH @ %08x",
- (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : " Breadth first"),
- td->hw.td.link & ~UHCI_PTR_BITS);
- else
- warn("%s, link points to TD @ %08x",
- (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : " Breadth first"),
- td->hw.td.link & ~UHCI_PTR_BITS);
- }
-#endif
+void uhci_show_status(struct uhci *uhci)
+{
+ unsigned int io_addr = uhci->io_addr;
+ unsigned short usbcmd, usbstat, usbint, usbfrnum;
+ unsigned int flbaseadd;
+ unsigned char sof;
+ unsigned short portsc1, portsc2;
+
+ usbcmd = inw(io_addr + 0);
+ usbstat = inw(io_addr + 2);
+ usbint = inw(io_addr + 4);
+ usbfrnum = inw(io_addr + 6);
+ flbaseadd = inl(io_addr + 8);
+ sof = inb(io_addr + 12);
+ portsc1 = inw(io_addr + 16);
+ portsc2 = inw(io_addr + 18);
+
+ printk(" usbcmd = %04x %s%s%s%s%s%s%s%s\n",
+ usbcmd,
+ (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ",
+ (usbcmd & USBCMD_CF) ? "CF " : "",
+ (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "",
+ (usbcmd & USBCMD_FGR) ? "FGR " : "",
+ (usbcmd & USBCMD_EGSM) ? "EGSM " : "",
+ (usbcmd & USBCMD_GRESET) ? "GRESET " : "",
+ (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
+ (usbcmd & USBCMD_RS) ? "RS " : "");
+
+ printk(" usbstat = %04x %s%s%s%s%s%s\n",
+ usbstat,
+ (usbstat & USBSTS_HCH) ? "HCHalted " : "",
+ (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "",
+ (usbstat & USBSTS_HSE) ? "HostSystemError " : "",
+ (usbstat & USBSTS_RD) ? "ResumeDetect " : "",
+ (usbstat & USBSTS_ERROR) ? "USBError " : "",
+ (usbstat & USBSTS_USBINT) ? "USBINT " : "");
+
+ printk(" usbint = %04x\n", usbint);
+ printk(" usbfrnum = (%d)%03x\n", (usbfrnum >> 10) & 1,
+ 0xfff & (4*(unsigned int)usbfrnum));
+ printk(" flbaseadd = %08x\n", flbaseadd);
+ printk(" sof = %02x\n", sof);
+ uhci_show_sc(1, portsc1);
+ uhci_show_sc(2, portsc2);
}
-#ifdef DEBUG
-static void uhci_show_td_queue (puhci_desc_t td)
+
+#define uhci_link_to_qh(x) ((struct uhci_qh *) uhci_link_to_td(x))
+
+struct uhci_td *uhci_link_to_td(unsigned int link)
{
- dbg("uhci_show_td_queue %p (%08lX):", td, virt_to_bus (td));
- while (1) {
- uhci_show_td (td);
- if (td->hw.td.link & UHCI_PTR_TERM)
- break;
- //if(!(td->hw.td.link&UHCI_PTR_DEPTH))
- // break;
- if (td != bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS))
- td = bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS);
- else {
- dbg("td points to itself!");
- break;
- }
-// schedule();
- }
+ if (link & UHCI_PTR_TERM)
+ return NULL;
+
+ return bus_to_virt(link & ~UHCI_PTR_BITS);
}
-static void uhci_show_queue (puhci_desc_t qh)
+void uhci_show_queue(struct uhci_qh *qh)
{
- dbg("uhci_show_queue %p:", qh);
- while (1) {
- uhci_show_qh (qh);
+ struct uhci_td *td, *first;
+ int i = 0, count = 1000;
- if (qh->hw.qh.element & UHCI_PTR_QH)
- dbg("Warning: qh->element points to qh!");
- else if (!(qh->hw.qh.element & UHCI_PTR_TERM))
- uhci_show_td_queue (bus_to_virt (qh->hw.qh.element & ~UHCI_PTR_BITS));
+ if (qh->element & UHCI_PTR_QH)
+ printk(" Element points to QH (bug?)\n");
- if (qh->hw.qh.head & UHCI_PTR_TERM)
- break;
+ if (qh->element & UHCI_PTR_DEPTH)
+ printk(" Depth traverse\n");
- if (qh != bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS))
- qh = bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS);
- else {
- dbg("qh points to itself!");
+ if (qh->element & UHCI_PTR_TERM)
+ printk(" Terminate\n");
+
+ if (!(qh->element & ~UHCI_PTR_BITS)) {
+ printk(" td 0: [NULL]\n");
+ return;
+ }
+
+ first = uhci_link_to_td(qh->element);
+
+ /* Make sure it doesn't runaway */
+ for (td = first; td && count > 0;
+ td = uhci_link_to_td(td->link), --count) {
+ printk(" td %d: [%p]\n", i++, td);
+ printk(" ");
+ uhci_show_td(td);
+
+ if (td == uhci_link_to_td(td->link)) {
+ printk(KERN_ERR "td links to itself!\n");
break;
}
}
}
-static void uhci_show_sc (int port, unsigned short status)
+static int uhci_is_skeleton_td(struct uhci *uhci, struct uhci_td *td)
{
- dbg(" stat%d = %04x %s%s%s%s%s%s%s%s",
- port,
- status,
- (status & USBPORTSC_SUSP) ? "PortSuspend " : "",
- (status & USBPORTSC_PR) ? "PortReset " : "",
- (status & USBPORTSC_LSDA) ? "LowSpeed " : "",
- (status & USBPORTSC_RD) ? "ResumeDetect " : "",
- (status & USBPORTSC_PEC) ? "EnableChange " : "",
- (status & USBPORTSC_PE) ? "PortEnabled " : "",
- (status & USBPORTSC_CSC) ? "ConnectChange " : "",
- (status & USBPORTSC_CCS) ? "PortConnected " : "");
+ int j;
+
+ for (j = 0; j < UHCI_NUM_SKELTD; j++)
+ if (td == uhci->skeltd + j)
+ return 1;
+
+ return 0;
}
-void uhci_show_status (puhci_t s)
+static int uhci_is_skeleton_qh(struct uhci *uhci, struct uhci_qh *qh)
{
- unsigned int io_addr = s->io_addr;
- unsigned short usbcmd, usbstat, usbint, usbfrnum;
- unsigned int flbaseadd;
- unsigned char sof;
- unsigned short portsc1, portsc2;
+ int j;
+
+ for (j = 0; j < UHCI_NUM_SKELQH; j++)
+ if (qh == uhci->skelqh + j)
+ return 1;
- usbcmd = inw (io_addr + 0);
- usbstat = inw (io_addr + 2);
- usbint = inw (io_addr + 4);
- usbfrnum = inw (io_addr + 6);
- flbaseadd = inl (io_addr + 8);
- sof = inb (io_addr + 12);
- portsc1 = inw (io_addr + 16);
- portsc2 = inw (io_addr + 18);
-
- dbg(" usbcmd = %04x %s%s%s%s%s%s%s%s",
- usbcmd,
- (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ",
- (usbcmd & USBCMD_CF) ? "CF " : "",
- (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "",
- (usbcmd & USBCMD_FGR) ? "FGR " : "",
- (usbcmd & USBCMD_EGSM) ? "EGSM " : "",
- (usbcmd & USBCMD_GRESET) ? "GRESET " : "",
- (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
- (usbcmd & USBCMD_RS) ? "RS " : "");
-
- dbg(" usbstat = %04x %s%s%s%s%s%s",
- usbstat,
- (usbstat & USBSTS_HCH) ? "HCHalted " : "",
- (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "",
- (usbstat & USBSTS_HSE) ? "HostSystemError " : "",
- (usbstat & USBSTS_RD) ? "ResumeDetect " : "",
- (usbstat & USBSTS_ERROR) ? "USBError " : "",
- (usbstat & USBSTS_USBINT) ? "USBINT " : "");
-
- dbg(" usbint = %04x", usbint);
- dbg(" usbfrnum = (%d)%03x", (usbfrnum >> 10) & 1,
- 0xfff & (4 * (unsigned int) usbfrnum));
- dbg(" flbaseadd = %08x", flbaseadd);
- dbg(" sof = %02x", sof);
- uhci_show_sc (1, portsc1);
- uhci_show_sc (2, portsc2);
+ return 0;
}
-#endif
+
+static const char *td_names[] = {"interrupt1", "interrupt2", "interrupt4",
+ "interrupt8", "interrupt16", "interrupt32",
+ "interrupt64", "interrupt128", "interrupt256" };
+static const char *qh_names[] = { "control", "bulk" };
+
+void uhci_show_queues(struct uhci *uhci)
+{
+ int i, isqh;
+ struct uhci_qh *qh;
+ struct uhci_td *td;
+
+ for (i = 0; i < UHCI_NUMFRAMES; ++i) {
+ int shown = 0;
+
+ td = uhci_link_to_td(uhci->fl->frame[i]);
+ if (td)
+ isqh = uhci->fl->frame[i] & UHCI_PTR_QH;
+ while (td && !isqh) {
+ if (uhci_is_skeleton_td(uhci, td))
+ break;
+
+ if (!shown) {
+ printk(" Frame %d\n", i);
+ shown = 1;
+ }
+
+ printk("[%p] ", td);
+
+ uhci_show_td(td);
+ td = uhci_link_to_td(td->link);
+ if (td)
+ isqh = td->link & UHCI_PTR_QH;
+ }
+ }
+ for (i = 0; i < UHCI_NUM_SKELTD; ++i) {
+ printk(" %s: [%p] (%08x)\n", td_names[i],
+ &uhci->skeltd[i],
+ uhci->skeltd[i].link);
+
+ td = uhci_link_to_td(uhci->skeltd[i].link);
+ if (td)
+ isqh = uhci->skeltd[i].link & UHCI_PTR_QH;
+ while (td && !isqh) {
+ if (uhci_is_skeleton_td(uhci, td))
+ break;
+
+ printk("[%p] ", td);
+
+ uhci_show_td(td);
+ td = uhci_link_to_td(td->link);
+ if (td)
+ isqh = td->link & UHCI_PTR_QH;
+ }
+ }
+ for (i = 0; i < UHCI_NUM_SKELQH; ++i) {
+ printk(" %s: [%p] (%08x) (%08x)\n", qh_names[i],
+ &uhci->skelqh[i],
+ uhci->skelqh[i].link, uhci->skelqh[i].element);
+
+ qh = uhci_link_to_qh(uhci->skelqh[i].link);
+ for (; qh; qh = uhci_link_to_qh(qh->link)) {
+ if (uhci_is_skeleton_qh(uhci, qh))
+ break;
+
+ printk(" [%p] (%08x) (%08x)\n",
+ qh, qh->link, qh->element);
+
+ uhci_show_queue(qh);
+ }
+ }
+}
+
diff --git a/drivers/usb/uhci.c b/drivers/usb/uhci.c
new file mode 100644
index 000000000..d18fc30cb
--- /dev/null
+++ b/drivers/usb/uhci.c
@@ -0,0 +1,2214 @@
+/*
+ * Universal Host Controller Interface driver for USB.
+ *
+ * (C) Copyright 1999 Linus Torvalds
+ * (C) Copyright 1999-2000 Johannes Erdfelt, jerdfelt@sventech.com
+ * (C) Copyright 1999 Randy Dunlap
+ * (C) Copyright 1999 Georg Acher, acher@in.tum.de
+ * (C) Copyright 1999 Deti Fliegl, deti@fliegl.de
+ * (C) Copyright 1999 Thomas Sailer, sailer@ife.ee.ethz.ch
+ * (C) Copyright 1999 Roman Weissgaerber, weissg@vienna.at
+ *
+ * Intel documents this fairly well, and as far as I know there
+ * are no royalties or anything like that, but even so there are
+ * people who decided that they want to do the same thing in a
+ * completely different way.
+ *
+ * WARNING! The USB documentation is downright evil. Most of it
+ * is just crap, written by a committee. You're better off ignoring
+ * most of it, the important stuff is:
+ * - the low-level protocol (fairly simple but lots of small details)
+ * - working around the horridness of the rest
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/malloc.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+
+#define DEBUG
+#include "usb.h"
+
+#include "uhci.h"
+#include "uhci-debug.h"
+
+#ifdef CONFIG_APM
+#include <linux/apm_bios.h>
+static int handle_apm_event(apm_event_t event);
+#endif
+
+static int debug = 1;
+MODULE_PARM(debug, "i");
+
+static kmem_cache_t *uhci_td_cachep;
+static kmem_cache_t *uhci_qh_cachep;
+
+static LIST_HEAD(uhci_list);
+
+static int rh_submit_urb(urb_t *urb);
+static int rh_unlink_urb(urb_t *urb);
+static int uhci_get_current_frame_number(struct usb_device *usb_dev);
+
+#define min(a,b) (((a)<(b))?(a):(b))
+
+/*
+ * Only the USB core should call uhci_alloc_dev and uhci_free_dev
+ */
+static int uhci_alloc_dev(struct usb_device *usb_dev)
+{
+ struct uhci_device *dev;
+
+ /* Allocate the UHCI device private data */
+ dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -1;
+
+ /* Initialize "dev" */
+ memset(dev, 0, sizeof(*dev));
+
+ usb_dev->hcpriv = dev;
+ dev->usb = usb_dev;
+ atomic_set(&dev->refcnt, 1);
+
+ if (usb_dev->parent)
+ dev->uhci = usb_to_uhci(usb_dev->parent)->uhci;
+
+ return 0;
+}
+
+static int uhci_free_dev(struct usb_device *usb_dev)
+{
+ struct uhci_device *dev = usb_to_uhci(usb_dev);
+
+ if (atomic_dec_and_test(&dev->refcnt))
+ kfree(dev);
+
+ return 0;
+}
+
+static void uhci_inc_dev_use(struct uhci_device *dev)
+{
+ atomic_inc(&dev->refcnt);
+}
+
+static void uhci_dec_dev_use(struct uhci_device *dev)
+{
+ uhci_free_dev(dev->usb);
+}
+
+/*
+ * UHCI interrupt list operations..
+ */
+static void uhci_add_irq_list(struct uhci *uhci, struct uhci_td *td)
+{
+ unsigned long flags;
+
+ nested_lock(&uhci->irqlist_lock, flags);
+ list_add(&td->irq_list, &uhci->interrupt_list);
+ nested_unlock(&uhci->irqlist_lock, flags);
+}
+
+static void uhci_remove_irq_list(struct uhci *uhci, struct uhci_td *td)
+{
+ unsigned long flags;
+
+ nested_lock(&uhci->irqlist_lock, flags);
+ if (td->irq_list.next != &td->irq_list) {
+ list_del(&td->irq_list);
+ INIT_LIST_HEAD(&td->irq_list);
+ }
+ nested_unlock(&uhci->irqlist_lock, flags);
+}
+
+static void uhci_add_urb_list(struct uhci *uhci, struct urb *urb)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&uhci->urblist_lock, flags);
+ list_add(&urb->urb_list, &uhci->urb_list);
+ spin_unlock_irqrestore(&uhci->urblist_lock, flags);
+}
+
+static void uhci_remove_urb_list(struct uhci *uhci, struct urb *urb)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&uhci->urblist_lock, flags);
+ if (urb->urb_list.next != &urb->urb_list) {
+ list_del(&urb->urb_list);
+ INIT_LIST_HEAD(&urb->urb_list);
+ }
+ spin_unlock_irqrestore(&uhci->urblist_lock, flags);
+}
+
+/*
+ * We insert Isochronous transfers directly into the frame list at the
+ * beginning
+ * The layout looks as follows:
+ * frame list pointer -> iso td's (if any) ->
+ * periodic interrupt td (if frame 0) -> irq td's -> control qh -> bulk qh
+ */
+
+static void uhci_insert_td_frame_list(struct uhci *uhci, struct uhci_td *td, unsigned framenum)
+{
+ unsigned long flags;
+ struct uhci_td *nexttd;
+
+ framenum %= UHCI_NUMFRAMES;
+
+ spin_lock_irqsave(&uhci->framelist_lock, flags);
+ td->frameptr = &uhci->fl->frame[framenum];
+ td->link = uhci->fl->frame[framenum];
+ if (!(td->link & (UHCI_PTR_TERM | UHCI_PTR_QH))) {
+ nexttd = (struct uhci_td *)uhci_ptr_to_virt(td->link);
+ td->nexttd = nexttd;
+ nexttd->prevtd = td;
+ nexttd->frameptr = NULL;
+ }
+ uhci->fl->frame[framenum] = virt_to_bus(td);
+ spin_unlock_irqrestore(&uhci->framelist_lock, flags);
+}
+
+static void uhci_remove_td(struct uhci *uhci, struct uhci_td *td)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&uhci->framelist_lock, flags);
+ if (td->frameptr) {
+ *(td->frameptr) = td->link;
+ if (td->nexttd) {
+ td->nexttd->frameptr = td->frameptr;
+ td->nexttd->prevtd = NULL;
+ td->nexttd = NULL;
+ }
+ td->frameptr = NULL;
+ } else {
+ if (td->prevtd) {
+ td->prevtd->nexttd = td->nexttd;
+ td->prevtd->link = td->link;
+ }
+ if (td->nexttd)
+ td->nexttd->prevtd = td->prevtd;
+ td->prevtd = td->nexttd = NULL;
+ }
+ td->link = UHCI_PTR_TERM;
+ spin_unlock_irqrestore(&uhci->framelist_lock, flags);
+}
+
+static void uhci_insert_td(struct uhci *uhci, struct uhci_td *skeltd, struct uhci_td *td)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&uhci->framelist_lock, flags);
+
+ /* Fix the linked list pointers */
+ td->nexttd = skeltd->nexttd;
+ td->prevtd = skeltd;
+ if (skeltd->nexttd)
+ skeltd->nexttd->prevtd = td;
+ skeltd->nexttd = td;
+
+ td->link = skeltd->link;
+ skeltd->link = virt_to_bus(td);
+
+ spin_unlock_irqrestore(&uhci->framelist_lock, flags);
+}
+
+/*
+ * Inserts a td into qh list at the top.
+ */
+static void uhci_insert_tds_in_qh(struct uhci_qh *qh, struct uhci_td *begin)
+{
+ struct uhci_td *td, *prevtd;
+
+ if (!begin) /* Nothing to do */
+ return;
+
+ /* Grab the first TD and add it to the QH */
+ td = begin;
+ qh->element = virt_to_bus(td) | UHCI_PTR_DEPTH;
+
+ /* Go through the rest of the TD's, link them together */
+ prevtd = td;
+ td = td->next;
+ while (td) {
+ prevtd->link = virt_to_bus(td) | UHCI_PTR_DEPTH;
+
+ prevtd = td;
+ td = td->next;
+ }
+
+ prevtd->link = UHCI_PTR_TERM;
+}
+
+static struct uhci_td *uhci_td_alloc(struct uhci_device *dev)
+{
+ struct uhci_td *td;
+
+ td = kmem_cache_alloc(uhci_td_cachep, in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL);
+ if (!td)
+ return NULL;
+
+ td->link = UHCI_PTR_TERM;
+ td->buffer = 0;
+
+ td->frameptr = NULL;
+ td->nexttd = td->prevtd = NULL;
+ td->next = NULL;
+ td->dev = dev;
+ INIT_LIST_HEAD(&td->irq_list);
+ INIT_LIST_HEAD(&td->list);
+
+ uhci_inc_dev_use(dev);
+
+ return td;
+}
+
+static void uhci_td_free(struct uhci_td *td)
+{
+ kmem_cache_free(uhci_td_cachep, td);
+
+ if (td->dev)
+ uhci_dec_dev_use(td->dev);
+}
+
+static void uhci_schedule_delete_td(struct uhci *uhci, struct uhci_td *td)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&uhci->freelist_lock, flags);
+ list_add(&td->list, &uhci->td_free_list);
+ if (td->dev) {
+ uhci_dec_dev_use(td->dev);
+ td->dev = NULL;
+ }
+ spin_unlock_irqrestore(&uhci->freelist_lock, flags);
+}
+
+static struct uhci_qh *uhci_qh_alloc(struct uhci_device *dev)
+{
+ struct uhci_qh *qh;
+
+ qh = kmem_cache_alloc(uhci_qh_cachep, in_interrupt() ? SLAB_ATOMIC : SLAB_KERNEL);
+ if (!qh)
+ return NULL;
+
+ qh->element = UHCI_PTR_TERM;
+ qh->link = UHCI_PTR_TERM;
+
+ qh->dev = dev;
+ qh->prevqh = qh->nextqh = NULL;
+
+ INIT_LIST_HEAD(&qh->list);
+
+ uhci_inc_dev_use(dev);
+
+ return qh;
+}
+
+static void uhci_qh_free(struct uhci_qh *qh)
+{
+ kmem_cache_free(uhci_qh_cachep, qh);
+
+ if (qh->dev)
+ uhci_dec_dev_use(qh->dev);
+}
+
+static void uhci_schedule_delete_qh(struct uhci *uhci, struct uhci_qh *qh)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&uhci->freelist_lock, flags);
+ list_add(&qh->list, &uhci->qh_free_list);
+ if (qh->dev) {
+ uhci_dec_dev_use(qh->dev);
+ qh->dev = NULL;
+ }
+ spin_unlock_irqrestore(&uhci->freelist_lock, flags);
+}
+
+static void uhci_insert_qh(struct uhci *uhci, struct uhci_qh *skelqh, struct uhci_qh *qh)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&uhci->framelist_lock, flags);
+
+ /* Fix the linked list pointers */
+ qh->nextqh = skelqh->nextqh;
+ qh->prevqh = skelqh;
+ if (skelqh->nextqh)
+ skelqh->nextqh->prevqh = qh;
+ skelqh->nextqh = qh;
+
+ qh->link = skelqh->link;
+ skelqh->link = virt_to_bus(qh) | UHCI_PTR_QH;
+
+ spin_unlock_irqrestore(&uhci->framelist_lock, flags);
+}
+
+static void uhci_remove_qh(struct uhci *uhci, struct uhci_qh *qh)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&uhci->framelist_lock, flags);
+ if (qh->prevqh) {
+ qh->prevqh->nextqh = qh->nextqh;
+ qh->prevqh->link = qh->link;
+ }
+ if (qh->nextqh)
+ qh->nextqh->prevqh = qh->prevqh;
+ qh->prevqh = qh->nextqh = NULL;
+ spin_unlock_irqrestore(&uhci->framelist_lock, flags);
+}
+
+static void inline uhci_fill_td(struct uhci_td *td, __u32 status,
+ __u32 info, __u32 buffer)
+{
+ td->status = status;
+ td->info = info;
+ td->buffer = buffer;
+}
+
+static void uhci_add_td_to_urb(urb_t *urb, struct uhci_td *td)
+{
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+
+ td->urb = urb;
+
+ if (urbp->end)
+ urbp->end->next = td;
+
+ urbp->end = td;
+
+ if (!urbp->begin)
+ urbp->begin = td;
+}
+
+/*
+ * Map status to standard result codes
+ *
+ * <status> is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)]
+ * <dir_out> is True for output TDs and False for input TDs.
+ */
+static int uhci_map_status(int status, int dir_out)
+{
+ if (!status)
+ return 0;
+ if (status & TD_CTRL_BITSTUFF) /* Bitstuff error */
+ return -EPROTO;
+ if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */
+ if (dir_out)
+ return -ETIMEDOUT;
+ else
+ return -EILSEQ;
+ }
+ if (status & TD_CTRL_NAK) /* NAK */
+ return -ETIMEDOUT;
+ if (status & TD_CTRL_BABBLE) /* Babble */
+ return -EPIPE;
+ if (status & TD_CTRL_DBUFERR) /* Buffer error */
+ return -ENOSR;
+ if (status & TD_CTRL_STALLED) /* Stalled */
+ return -EPIPE;
+ if (status & TD_CTRL_ACTIVE) /* Active */
+ return 0;
+
+ return -EINVAL;
+}
+
+/*
+ * Control transfers
+ */
+static int uhci_submit_control(urb_t *urb)
+{
+ struct uhci_td *td;
+ struct uhci_qh *qh;
+ unsigned long destination, status;
+ struct uhci_device *dev = usb_to_uhci(urb->dev);
+ struct uhci *uhci = dev->uhci;
+ int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
+ int len = urb->transfer_buffer_length;
+ unsigned char *data = urb->transfer_buffer;
+ struct urb_priv *urbp;
+
+ /* The "pipe" thing contains the destination in bits 8--18 */
+ destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
+
+ /* 3 errors */
+ status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27);
+
+ urbp = kmalloc(sizeof(*urbp), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+ if (!urbp)
+ return -ENOMEM;
+
+ urbp->begin = urbp->end = NULL;
+
+ urb->hcpriv = urbp;
+
+ /*
+ * Build the TD for the control request
+ */
+ td = uhci_td_alloc(dev);
+ if (!td)
+ return -ENOMEM;
+
+ uhci_add_td_to_urb(urb, td);
+ uhci_fill_td(td, status, destination | (7 << 21),
+ virt_to_bus(urb->setup_packet));
+
+ /*
+ * If direction is "send", change the frame from SETUP (0x2D)
+ * to OUT (0xE1). Else change it from SETUP to IN (0x69).
+ */
+ destination ^= (USB_PID_SETUP ^ usb_packetid(urb->pipe));
+
+ if (!(urb->transfer_flags & USB_DISABLE_SPD))
+ status |= TD_CTRL_SPD;
+
+ /*
+ * Build the DATA TD's
+ */
+ td = uhci_td_alloc(dev);
+ if (!td) {
+ /* FIXME: Free the TD's */
+ return -ENOMEM;
+ }
+
+ while (len > 0) {
+ int pktsze = len;
+
+ if (pktsze > maxsze)
+ pktsze = maxsze;
+
+ /* Alternate Data0/1 (start with Data1) */
+ destination ^= 1 << TD_TOKEN_TOGGLE;
+
+ uhci_add_td_to_urb(urb, td);
+ uhci_fill_td(td, status, destination | ((pktsze - 1) << 21),
+ virt_to_bus(data));
+
+ data += pktsze;
+ len -= pktsze;
+
+ td = uhci_td_alloc(dev);
+ if (!td)
+ /* FIXME: Free all of the previously allocated td's */
+ return -ENOMEM;
+ }
+
+ /*
+ * Build the final TD for control status
+ *
+ * It's IN if the pipe is an output pipe or we're not expecting
+ * data back.
+ */
+ destination &= ~TD_PID;
+ if (usb_pipeout(urb->pipe) || !urb->transfer_buffer_length)
+ destination |= USB_PID_IN;
+ else
+ destination |= USB_PID_OUT;
+
+ destination |= 1 << TD_TOKEN_TOGGLE; /* End in Data1 */
+
+ status &= ~TD_CTRL_SPD;
+
+ uhci_add_td_to_urb(urb, td);
+ uhci_fill_td(td, status | TD_CTRL_IOC,
+ destination | (UHCI_NULL_DATA_SIZE << 21), 0);
+
+ uhci_add_irq_list(uhci, td);
+
+ qh = uhci_qh_alloc(dev);
+ if (!qh) {
+ /* FIXME: Free all of the TD's */
+ return -ENOMEM;
+ }
+ uhci_insert_tds_in_qh(qh, urbp->begin);
+
+ uhci_insert_qh(uhci, &uhci->skel_control_qh, qh);
+ urbp->qh = qh;
+
+ uhci_add_urb_list(uhci, urb);
+
+ usb_inc_dev_use(urb->dev);
+
+ return -EINPROGRESS;
+}
+
+static int uhci_unlink_control(urb_t *urb)
+{
+ struct urb_priv *urbp = urb->hcpriv;
+ struct uhci_td *td;
+ struct uhci_device *dev = usb_to_uhci(urb->dev);
+ struct uhci *uhci = dev->uhci;
+
+ if (!urbp)
+ return -EINVAL;
+
+ uhci_remove_qh(uhci, urbp->qh);
+ uhci_schedule_delete_qh(uhci, urbp->qh);
+
+ /* Go through the rest of the TD's, deleting them, then scheduling */
+ /* their deletion */
+ td = urbp->begin;
+ while (td) {
+ struct uhci_td *next = td->next;
+
+ if (td->status & TD_CTRL_IOC)
+ uhci_remove_irq_list(uhci, td);
+
+ uhci_schedule_delete_td(uhci, td);
+
+ td = next;
+ }
+
+ kfree(urbp);
+ urb->hcpriv = NULL;
+
+ uhci_remove_urb_list(uhci, urb);
+
+ return 0;
+}
+
+static int uhci_result_control(urb_t *urb)
+{
+ struct urb_priv *urbp = urb->hcpriv;
+ struct uhci_td *td;
+ unsigned int status;
+ int ret;
+
+ td = urbp->begin;
+ if (!td) /* Nothing to do */
+ return -EINVAL;
+
+ /* The first TD is the SETUP phase, check the status, but skip */
+ /* the count */
+ status = uhci_status_bits(td->status);
+ if (status & TD_CTRL_ACTIVE)
+ return -EINPROGRESS;
+
+ if (status)
+ goto td_error;
+
+ urb->actual_length = 0;
+
+ /* The rest of the TD's (but the last) are data */
+ td = td->next;
+ while (td && td->next) {
+ status = uhci_status_bits(td->status);
+ if (status & TD_CTRL_ACTIVE)
+ return -EINPROGRESS;
+
+ urb->actual_length += uhci_actual_length(td->status);
+
+ /* If SPD is set then we received a short packet */
+ /* There will be no status phase at the end */
+ if (td->status & TD_CTRL_SPD && (uhci_actual_length(td->status) < uhci_expected_length(td->info)))
+ goto td_success;
+
+ if (status)
+ goto td_error;
+
+ td = td->next;
+ }
+
+ /* Control status phase */
+ status = uhci_status_bits(td->status);
+
+ /* APC BackUPS Pro kludge */
+ /* It tries to send all of the descriptor instead of */
+ /* the amount we requested */
+ if (td->status & TD_CTRL_IOC &&
+ status & TD_CTRL_ACTIVE &&
+ status & TD_CTRL_NAK)
+ goto td_success;
+
+ if (status & TD_CTRL_ACTIVE)
+ return -EINPROGRESS;
+
+ if (status)
+ goto td_error;
+
+td_success:
+ uhci_unlink_control(urb);
+
+ return 0;
+
+td_error:
+ /* Some debugging code */
+ if (debug) {
+ dbg("uhci_result_control() failed with status %x",
+ status);
+
+ /* Print the chain for debugging purposes */
+ uhci_show_queue(urbp->qh);
+ }
+
+ if (status & TD_CTRL_STALLED) {
+ /* endpoint has stalled - mark it halted */
+ usb_endpoint_halt(urb->dev, uhci_endpoint(td->info),
+ uhci_packetout(td->info));
+ uhci_unlink_control(urb);
+
+ return -EPIPE;
+ }
+
+ ret = uhci_map_status(status, uhci_packetout(td->info));
+
+ uhci_unlink_control(urb);
+
+ return ret;
+}
+
+/*
+ * Interrupt transfers
+ */
+static int uhci_submit_interrupt(urb_t *urb)
+{
+ struct uhci_td *td;
+ unsigned long destination, status;
+ struct uhci_device *dev = usb_to_uhci(urb->dev);
+ struct uhci *uhci = dev->uhci;
+ struct urb_priv *urbp;
+
+ if (urb->transfer_buffer_length > usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))
+ return -EINVAL;
+
+ /* The "pipe" thing contains the destination in bits 8--18 */
+ destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
+
+ status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | TD_CTRL_SPD |
+ TD_CTRL_IOC;
+
+ urbp = kmalloc(sizeof(*urbp), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+ if (!urbp)
+ return -ENOMEM;
+
+ urbp->begin = urbp->end = NULL;
+
+ urb->hcpriv = urbp;
+
+ td = uhci_td_alloc(dev);
+ if (!td)
+ return -ENOMEM;
+
+ destination |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE);
+ destination |= ((urb->transfer_buffer_length - 1) << 21);
+
+ uhci_add_td_to_urb(urb, td);
+ uhci_fill_td(td, status, destination,
+ virt_to_bus(urb->transfer_buffer));
+
+ uhci_add_irq_list(uhci, td);
+
+ uhci_insert_td(uhci, &uhci->skeltd[__interval_to_skel(urb->interval)], td);
+
+ uhci_add_urb_list(uhci, urb);
+
+ usb_inc_dev_use(urb->dev);
+
+ return -EINPROGRESS;
+}
+
+static int uhci_unlink_interrupt(urb_t *urb)
+{
+ struct urb_priv *urbp = urb->hcpriv;
+ struct uhci_td *td;
+ struct uhci_device *dev = usb_to_uhci(urb->dev);
+ struct uhci *uhci = dev->uhci;
+
+ if (!urbp)
+ return -EINVAL;
+
+ td = urbp->begin;
+ uhci_remove_td(uhci, td);
+ if (td->status & TD_CTRL_IOC)
+ uhci_remove_irq_list(uhci, td);
+ uhci_schedule_delete_td(uhci, td);
+
+ kfree(urbp);
+ urb->hcpriv = NULL;
+
+ uhci_remove_urb_list(uhci, urb);
+
+ return 0;
+}
+
+static int uhci_result_interrupt(urb_t *urb)
+{
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ struct uhci_td *td;
+ int status;
+
+ if (!urbp)
+ return -EINVAL;
+
+ td = urbp->begin;
+ if (!td)
+ return -EINVAL;
+
+ status = uhci_status_bits(td->status);
+ if (status & TD_CTRL_ACTIVE)
+ return -EINPROGRESS;
+
+ if (status)
+ return uhci_map_status(status, uhci_packetout(td->info));
+
+ urb->actual_length += uhci_actual_length(td->status);
+
+ return 0;
+}
+
+static void uhci_reset_interrupt(urb_t *urb)
+{
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ struct uhci_td *td;
+
+ if (urb->interval) {
+ td = urbp->begin;
+
+ usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
+ td->status = (td->status & 0x2F000000) | TD_CTRL_ACTIVE | TD_CTRL_IOC;
+ td->info &= ~(1 << TD_TOKEN_TOGGLE);
+ td->info |= (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE);
+
+ urb->status = -EINPROGRESS;
+ } else
+ uhci_unlink_interrupt(urb);
+}
+
+/*
+ * Bulk transfers
+ */
+static int uhci_submit_bulk(urb_t *urb)
+{
+ struct uhci_td *td;
+ struct uhci_qh *qh;
+ unsigned long destination, status;
+ struct uhci_device *dev = usb_to_uhci(urb->dev);
+ struct uhci *uhci = dev->uhci;
+ int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
+ int len = urb->transfer_buffer_length;
+ unsigned char *data = urb->transfer_buffer;
+ struct urb_priv *urbp;
+
+ if (len < 0)
+ return -EINVAL;
+
+ /* The "pipe" thing contains the destination in bits 8--18 */
+ destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
+
+ /* 3 errors */
+ status = (urb->pipe & TD_CTRL_LS) | TD_CTRL_ACTIVE | (3 << 27);
+ if (!(urb->transfer_flags & USB_DISABLE_SPD))
+ status |= TD_CTRL_SPD;
+
+ urbp = kmalloc(sizeof(*urbp), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+ if (!urbp)
+ return -ENOMEM;
+
+ urbp->begin = urbp->end = NULL;
+
+ urb->hcpriv = urbp;
+
+ /*
+ * Build the DATA TD's
+ */
+ while (len > 0) {
+ int pktsze = len;
+
+ if (pktsze > maxsze)
+ pktsze = maxsze;
+
+ td = uhci_td_alloc(dev);
+ if (!td) {
+ /* FIXME: Free the TD's */
+ return -ENOMEM;
+ }
+
+ uhci_add_td_to_urb(urb, td);
+ uhci_fill_td(td, status, destination | ((pktsze - 1) << 21) |
+ (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ usb_pipeout(urb->pipe)) << TD_TOKEN_TOGGLE),
+ virt_to_bus(data));
+
+ data += pktsze;
+ len -= maxsze;
+
+ if (len <= 0) {
+ td->status |= TD_CTRL_IOC;
+ uhci_add_irq_list(uhci, td);
+ }
+
+ usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe),
+ usb_pipeout(urb->pipe));
+ }
+
+ qh = uhci_qh_alloc(dev);
+ if (!qh) {
+ /* FIXME: Free all of the TD's */
+ return -ENOMEM;
+ }
+ uhci_insert_tds_in_qh(qh, urbp->begin);
+
+ uhci_insert_qh(dev->uhci, &dev->uhci->skel_bulk_qh, qh);
+ urbp->qh = qh;
+
+ uhci_add_urb_list(uhci, urb);
+
+ usb_inc_dev_use(urb->dev);
+
+ return -EINPROGRESS;
+}
+
+/* We can use the control unlink since they're identical */
+#define uhci_unlink_bulk uhci_unlink_control
+
+static int uhci_result_bulk(urb_t *urb)
+{
+ struct urb_priv *urbp = urb->hcpriv;
+ struct uhci_td *td;
+ unsigned int status;
+
+ urb->actual_length = 0;
+
+ /* The rest of the TD's (but the last) are data */
+ for (td = urbp->begin; td; td = td->next) {
+ status = uhci_status_bits(td->status);
+ if (status & TD_CTRL_ACTIVE)
+ return -EINPROGRESS;
+
+ urb->actual_length += uhci_actual_length(td->status);
+
+ /* If SPD is set then we received a short packet */
+ if (td->status & TD_CTRL_SPD && (uhci_actual_length(td->status) < uhci_expected_length(td->info))) {
+ usb_settoggle(urb->dev, uhci_endpoint(td->info),
+ uhci_packetout(td->info),
+ uhci_toggle(td->info) ^ 1);
+
+ goto td_success;
+ }
+
+ if (status)
+ goto td_error;
+ }
+
+td_success:
+ uhci_unlink_bulk(urb);
+
+ return 0;
+
+td_error:
+ /* Some debugging code */
+ if (debug) {
+ dbg("uhci_result_bulk() failed with status %x",
+ status);
+
+ /* Print the chain for debugging purposes */
+ uhci_show_queue(urbp->qh);
+ }
+
+ if (status & TD_CTRL_STALLED) {
+ /* endpoint has stalled - mark it halted */
+ usb_endpoint_halt(urb->dev, uhci_endpoint(td->info),
+ uhci_packetout(td->info));
+ return -EPIPE;
+ }
+
+ return uhci_map_status(status, uhci_packetout(td->info));
+}
+
+/*
+ * Isochronous transfers
+ */
+static int isochronous_find_limits(urb_t *urb, unsigned int *start, unsigned int *end)
+{
+ urb_t *u, *last_urb = NULL;
+ struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+ struct list_head *tmp, *head = &uhci->urb_list;
+ unsigned long flags;
+
+ spin_lock_irqsave(&uhci->urblist_lock, flags);
+ tmp = head->next;
+ while (tmp != head) {
+ u = list_entry(tmp, urb_t, urb_list);
+
+ /* look for pending URB's with identical pipe handle */
+ if ((urb->pipe == u->pipe) && (urb->dev == u->dev) &&
+ (u->status == -EINPROGRESS) && (u != urb)) {
+ if (!last_urb)
+ *start = u->start_frame;
+ last_urb = u;
+ }
+ tmp = tmp->next;
+ }
+ spin_unlock_irqrestore(&uhci->urblist_lock, flags);
+
+ if (last_urb) {
+ *end = (last_urb->start_frame + last_urb->number_of_packets) & 1023;
+ return 0;
+ } else
+ return -1; // no previous urb found
+
+}
+
+static int isochronous_find_start(urb_t *urb)
+{
+ int limits;
+ unsigned int start = 0, end = 0;
+
+ if (urb->number_of_packets > 900) /* 900? Why? */
+ return -EFBIG;
+
+ limits = isochronous_find_limits(urb, &start, &end);
+
+ if (urb->transfer_flags & USB_ISO_ASAP) {
+ if (limits) {
+ int curframe;
+
+ curframe = uhci_get_current_frame_number(urb->dev) % UHCI_NUMFRAMES;
+ urb->start_frame = (curframe + 10) % UHCI_NUMFRAMES;
+ } else
+ urb->start_frame = end;
+ } else {
+ urb->start_frame %= UHCI_NUMFRAMES;
+ /* FIXME: Sanity check */
+ }
+
+ return 0;
+}
+
+static int uhci_submit_isochronous(urb_t *urb)
+{
+ struct uhci_td *td;
+ struct uhci_device *dev = usb_to_uhci(urb->dev);
+ struct uhci *uhci = dev->uhci;
+ struct urb_priv *urbp;
+ int i, ret, framenum;
+ int status, destination;
+
+ status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
+ destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
+
+ ret = isochronous_find_start(urb);
+ if (ret)
+ return ret;
+
+ urbp = kmalloc(sizeof(*urbp), in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+ if (!urbp)
+ return -ENOMEM;
+
+ urbp->begin = urbp->end = NULL;
+
+ urb->hcpriv = urbp;
+
+ framenum = urb->start_frame;
+ for (i = 0; i < urb->number_of_packets; i++, framenum++) {
+ if (!urb->iso_frame_desc[i].length)
+ continue;
+
+ td = uhci_td_alloc(dev);
+ if (!td) {
+ /* FIXME: Free the TD's */
+ return -ENOMEM;
+ }
+
+ uhci_add_td_to_urb(urb, td);
+ uhci_fill_td(td, status, destination | ((urb->iso_frame_desc[i].length - 1) << 21),
+ virt_to_bus(urb->transfer_buffer + urb->iso_frame_desc[i].offset));
+
+ if (i + 1 >= urb->number_of_packets) {
+ td->status |= TD_CTRL_IOC;
+ uhci_add_irq_list(uhci, td);
+ }
+
+ uhci_insert_td_frame_list(uhci, td, framenum);
+ }
+
+ uhci_add_urb_list(uhci, urb);
+
+ usb_inc_dev_use(urb->dev);
+
+ return -EINPROGRESS;
+}
+
+static int uhci_unlink_isochronous(urb_t *urb)
+{
+ struct urb_priv *urbp = urb->hcpriv;
+ struct uhci_td *td;
+ struct uhci_device *dev = usb_to_uhci(urb->dev);
+ struct uhci *uhci = dev->uhci;
+
+ if (!urbp)
+ return -EINVAL;
+
+ /* Go through the rest of the TD's, deleting them, then scheduling */
+ /* their deletion */
+ td = urbp->begin;
+ while (td) {
+ struct uhci_td *next = td->next;
+
+ uhci_remove_td(uhci, td);
+
+ if (td->status & TD_CTRL_IOC)
+ uhci_remove_irq_list(uhci, td);
+ uhci_schedule_delete_td(uhci, td);
+
+ td = next;
+ }
+
+ kfree(urbp);
+ urb->hcpriv = NULL;
+
+ uhci_remove_urb_list(uhci, urb);
+
+ return 0;
+}
+
+static int uhci_result_isochronous(urb_t *urb)
+{
+ struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
+ struct uhci_td *td;
+ int status;
+ int i, ret = 0;
+
+ td = urbp->end;
+ if (!td) /* Nothing to do */
+ return -EINVAL;
+
+ status = uhci_status_bits(td->status);
+ if (status & TD_CTRL_ACTIVE)
+ return -EINPROGRESS;
+
+ /* Assume no errors, we'll overwrite this if not */
+ urb->status = 0;
+
+ urb->actual_length = 0;
+ for (i = 0, td = urbp->begin; td; i++, td = td->next) {
+ int actlength;
+
+ actlength = uhci_actual_length(td->status);
+ urb->iso_frame_desc[i].actual_length = actlength;
+ urb->actual_length += actlength;
+
+ status = uhci_map_status(uhci_status_bits(td->status), usb_pipeout(urb->pipe));
+ urb->iso_frame_desc[i].status = status;
+ if (status != 0) {
+ urb->error_count++;
+ ret = status;
+ }
+ }
+
+ uhci_unlink_isochronous(urb);
+
+ return status;
+}
+
+static int uhci_submit_urb(urb_t *urb)
+{
+ int ret = -EINVAL;
+ struct uhci *uhci;
+
+ if (!urb)
+ return -EINVAL;
+
+ if (!urb->dev || !urb->dev->bus)
+ return -ENODEV;
+
+ uhci = (struct uhci *)urb->dev->bus->hcpriv;
+
+ if (usb_pipedevice(urb->pipe) == uhci->rh.devnum)
+ return rh_submit_urb(urb); /* Virtual root hub */
+
+ switch (usb_pipetype(urb->pipe)) {
+ case PIPE_CONTROL:
+ ret = uhci_submit_control(urb);
+ break;
+ case PIPE_INTERRUPT:
+ ret = uhci_submit_interrupt(urb);
+ break;
+ case PIPE_BULK:
+ ret = uhci_submit_bulk(urb);
+ break;
+ case PIPE_ISOCHRONOUS:
+ ret = uhci_submit_isochronous(urb);
+ break;
+ }
+
+ urb->status = ret;
+ if (ret == -EINPROGRESS) {
+ usb_inc_dev_use(urb->dev);
+
+ return 0;
+ }
+
+ return ret;
+}
+
+/*
+ * Return the result of a transfer
+ */
+static void uhci_transfer_result(urb_t *urb)
+{
+ urb_t *turb;
+ int proceed = 0, is_ring = 0;
+ int ret = -EINVAL;
+
+ switch (usb_pipetype(urb->pipe)) {
+ case PIPE_CONTROL:
+ ret = uhci_result_control(urb);
+ break;
+ case PIPE_INTERRUPT:
+ /* Interrupts are an exception */
+ urb->status = uhci_result_interrupt(urb);
+ if (urb->status != -EINPROGRESS) {
+ urb->complete(urb);
+ uhci_reset_interrupt(urb);
+ }
+ return;
+ case PIPE_BULK:
+ ret = uhci_result_bulk(urb);
+ break;
+ case PIPE_ISOCHRONOUS:
+ ret = uhci_result_isochronous(urb);
+ break;
+ }
+
+ urb->status = ret;
+ if (urb->status == -EINPROGRESS)
+ return;
+
+ if (urb->next) {
+ turb = urb->next;
+ do {
+ if (turb->status != -EINPROGRESS) {
+ proceed = 1;
+ break;
+ }
+
+ turb = turb->next;
+ } while (turb && turb != urb && turb != urb->next);
+
+ if (turb == urb || turb == urb->next)
+ is_ring = 1;
+ }
+
+ if (urb->complete && (!proceed || (urb->transfer_flags & USB_URB_EARLY_COMPLETE))) {
+ urb->complete(urb);
+ if (!proceed && is_ring)
+ uhci_submit_urb(urb);
+ }
+
+ if (proceed && urb->next) {
+ turb = urb->next;
+ do {
+ if (turb->status != -EINPROGRESS &&
+ uhci_submit_urb(turb) != 0)
+
+ turb = turb->next;
+ } while (turb && turb != urb->next);
+
+ if (urb->complete && !(urb->transfer_flags & USB_URB_EARLY_COMPLETE))
+ urb->complete(urb);
+ }
+
+ usb_dec_dev_use(urb->dev);
+}
+
+static int uhci_unlink_urb(urb_t *urb)
+{
+ struct uhci *uhci;
+ int ret = 0;
+
+ if (!urb)
+ return -EINVAL;
+
+ uhci = (struct uhci *)urb->dev->bus->hcpriv;
+
+ if (usb_pipedevice(urb->pipe) == uhci->rh.devnum)
+ return rh_unlink_urb(urb);
+
+ if (urb->status == -EINPROGRESS) {
+ switch (usb_pipetype(urb->pipe)) {
+ case PIPE_CONTROL:
+ ret = uhci_unlink_control(urb);
+ break;
+ case PIPE_INTERRUPT:
+ ret = uhci_unlink_interrupt(urb);
+ break;
+ case PIPE_BULK:
+ ret = uhci_unlink_bulk(urb);
+ break;
+ case PIPE_ISOCHRONOUS:
+ ret = uhci_unlink_isochronous(urb);
+ break;
+ }
+
+ if (urb->complete)
+ urb->complete(urb);
+
+ if (in_interrupt()) { /* wait at least 1 frame */
+ int errorcount = 10;
+
+ if (errorcount--)
+ dbg("uhci_unlink_urb called from interrupt for urb %p", urb);
+ udelay(1000);
+ } else
+ schedule_timeout(1+1*HZ/1000);
+
+ usb_dec_dev_use(urb->dev);
+ }
+
+ urb->status = -ENOENT;
+
+ return ret;
+}
+
+/*
+ * uhci_get_current_frame_number()
+ *
+ * returns the current frame number for a USB bus/controller.
+ */
+static int uhci_get_current_frame_number(struct usb_device *usb_dev)
+{
+ struct uhci_device *dev = (struct uhci_device *)usb_dev->hcpriv;
+
+ return inw(dev->uhci->io_addr + USBFRNUM);
+}
+
+struct usb_operations uhci_device_operations = {
+ uhci_alloc_dev,
+ uhci_free_dev,
+ uhci_get_current_frame_number,
+ uhci_submit_urb,
+ uhci_unlink_urb
+};
+
+/* -------------------------------------------------------------------
+ Virtual Root Hub
+ ------------------------------------------------------------------- */
+
+static __u8 root_hub_dev_des[] =
+{
+ 0x12, /* __u8 bLength; */
+ 0x01, /* __u8 bDescriptorType; Device */
+ 0x00, /* __u16 bcdUSB; v1.0 */
+ 0x01,
+ 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 bDeviceSubClass; */
+ 0x00, /* __u8 bDeviceProtocol; */
+ 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */
+ 0x00, /* __u16 idVendor; */
+ 0x00,
+ 0x00, /* __u16 idProduct; */
+ 0x00,
+ 0x00, /* __u16 bcdDevice; */
+ 0x00,
+ 0x00, /* __u8 iManufacturer; */
+ 0x00, /* __u8 iProduct; */
+ 0x00, /* __u8 iSerialNumber; */
+ 0x01 /* __u8 bNumConfigurations; */
+};
+
+
+/* Configuration descriptor */
+static __u8 root_hub_config_des[] =
+{
+ 0x09, /* __u8 bLength; */
+ 0x02, /* __u8 bDescriptorType; Configuration */
+ 0x19, /* __u16 wTotalLength; */
+ 0x00,
+ 0x01, /* __u8 bNumInterfaces; */
+ 0x01, /* __u8 bConfigurationValue; */
+ 0x00, /* __u8 iConfiguration; */
+ 0x40, /* __u8 bmAttributes;
+ Bit 7: Bus-powered, 6: Self-powered,
+ Bit 5 Remote-wakeup, 4..0: resvd */
+ 0x00, /* __u8 MaxPower; */
+
+ /* interface */
+ 0x09, /* __u8 if_bLength; */
+ 0x04, /* __u8 if_bDescriptorType; Interface */
+ 0x00, /* __u8 if_bInterfaceNumber; */
+ 0x00, /* __u8 if_bAlternateSetting; */
+ 0x01, /* __u8 if_bNumEndpoints; */
+ 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */
+ 0x00, /* __u8 if_bInterfaceSubClass; */
+ 0x00, /* __u8 if_bInterfaceProtocol; */
+ 0x00, /* __u8 if_iInterface; */
+
+ /* endpoint */
+ 0x07, /* __u8 ep_bLength; */
+ 0x05, /* __u8 ep_bDescriptorType; Endpoint */
+ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
+ 0x03, /* __u8 ep_bmAttributes; Interrupt */
+ 0x08, /* __u16 ep_wMaxPacketSize; 8 Bytes */
+ 0x00,
+ 0xff /* __u8 ep_bInterval; 255 ms */
+};
+
+static __u8 root_hub_hub_des[] =
+{
+ 0x09, /* __u8 bLength; */
+ 0x29, /* __u8 bDescriptorType; Hub-descriptor */
+ 0x02, /* __u8 bNbrPorts; */
+ 0x00, /* __u16 wHubCharacteristics; */
+ 0x00,
+ 0x01, /* __u8 bPwrOn2pwrGood; 2ms */
+ 0x00, /* __u8 bHubContrCurrent; 0 mA */
+ 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */
+ 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */
+};
+
+/*-------------------------------------------------------------------------*/
+/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */
+static int rh_send_irq(urb_t *urb)
+{
+ int i, len = 1;
+ struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+ unsigned int io_addr = uhci->io_addr;
+ __u16 data = 0;
+
+ for (i = 0; i < uhci->rh.numports; i++) {
+ data |= ((inw(io_addr + USBPORTSC1 + i * 2) & 0xa) > 0 ? (1 << (i + 1)) : 0);
+ len = (i + 1) / 8 + 1;
+ }
+
+ *(__u16 *) urb->transfer_buffer = cpu_to_le16(data);
+ urb->actual_length = len;
+ urb->status = USB_ST_NOERROR;
+
+ if ((data > 0) && (uhci->rh.send != 0)) {
+#ifdef DEBUG /* JE */
+static int foo=5;
+if (foo--)
+#endif
+ dbg("root-hub INT complete: port1: %x port2: %x data: %x",
+ inw(io_addr + USBPORTSC1), inw(io_addr + USBPORTSC2), data);
+ urb->complete(urb);
+ }
+
+ return USB_ST_NOERROR;
+}
+
+/*-------------------------------------------------------------------------*/
+/* Virtual Root Hub INTs are polled by this timer every "interval" ms */
+static int rh_init_int_timer(urb_t *urb);
+
+static void rh_int_timer_do(unsigned long ptr)
+{
+ int len;
+ urb_t *urb = (urb_t *)ptr;
+ struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+
+ if (uhci->rh.send) {
+ len = rh_send_irq(urb);
+ if (len > 0) {
+ urb->actual_length = len;
+ if (urb->complete)
+ urb->complete(urb);
+ }
+ }
+
+ rh_init_int_timer(urb);
+}
+
+/*-------------------------------------------------------------------------*/
+/* Root Hub INTs are polled by this timer */
+static int rh_init_int_timer(urb_t *urb)
+{
+ struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+
+ uhci->rh.interval = urb->interval;
+ init_timer(&uhci->rh.rh_int_timer);
+ uhci->rh.rh_int_timer.function = rh_int_timer_do;
+ uhci->rh.rh_int_timer.data = (unsigned long)urb;
+ uhci->rh.rh_int_timer.expires = jiffies + (HZ * (urb->interval < 30 ? 30 : urb->interval)) / 1000;
+ add_timer(&uhci->rh.rh_int_timer);
+
+ return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+#define OK(x) len = (x); break
+
+#define CLR_RH_PORTSTAT(x) \
+ status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \
+ status = (status & 0xfff5) & ~(x); \
+ outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1))
+
+#define SET_RH_PORTSTAT(x) \
+ status = inw(io_addr + USBPORTSC1 + 2 * (wIndex-1)); \
+ status = (status & 0xfff5) | (x); \
+ outw(status, io_addr + USBPORTSC1 + 2 * (wIndex-1))
+
+
+/*-------------------------------------------------------------------------*/
+/*************************
+ ** Root Hub Control Pipe
+ *************************/
+
+static int rh_submit_urb(urb_t *urb)
+{
+ struct usb_device *usb_dev = urb->dev;
+ struct uhci *uhci = (struct uhci *)usb_dev->bus->hcpriv;
+ unsigned int pipe = urb->pipe;
+ devrequest *cmd = (devrequest *)urb->setup_packet;
+ void *data = urb->transfer_buffer;
+ int leni = urb->transfer_buffer_length;
+ int len = 0;
+ int status = 0;
+ int stat = USB_ST_NOERROR;
+ int i;
+ unsigned int io_addr = uhci->io_addr;
+ __u16 cstatus;
+ __u16 bmRType_bReq;
+ __u16 wValue;
+ __u16 wIndex;
+ __u16 wLength;
+
+ if (usb_pipetype(pipe) == PIPE_INTERRUPT) {
+ uhci->rh.urb = urb;
+ uhci->rh.send = 1;
+ uhci->rh.interval = urb->interval;
+ rh_init_int_timer(urb);
+
+ return USB_ST_NOERROR;
+ }
+
+ bmRType_bReq = cmd->requesttype | cmd->request << 8;
+ wValue = le16_to_cpu(cmd->value);
+ wIndex = le16_to_cpu(cmd->index);
+ wLength = le16_to_cpu(cmd->length);
+
+ for (i = 0; i < 8; i++)
+ uhci->rh.c_p_r[i] = 0;
+
+ switch (bmRType_bReq) {
+ /* Request Destination:
+ without flags: Device,
+ RH_INTERFACE: interface,
+ RH_ENDPOINT: endpoint,
+ RH_CLASS means HUB here,
+ RH_OTHER | RH_CLASS almost ever means HUB_PORT here
+ */
+
+ case RH_GET_STATUS:
+ *(__u16 *)data = cpu_to_le16(1);
+ OK(2);
+ case RH_GET_STATUS | RH_INTERFACE:
+ *(__u16 *)data = cpu_to_le16(0);
+ OK(2);
+ case RH_GET_STATUS | RH_ENDPOINT:
+ *(__u16 *)data = cpu_to_le16(0);
+ OK(2);
+ case RH_GET_STATUS | RH_CLASS:
+ *(__u32 *)data = cpu_to_le32(0);
+ OK(4); /* hub power */
+ case RH_GET_STATUS | RH_OTHER | RH_CLASS:
+ status = inw(io_addr + USBPORTSC1 + 2 * (wIndex - 1));
+ cstatus = ((status & USBPORTSC_CSC) >> (1 - 0)) |
+ ((status & USBPORTSC_PEC) >> (3 - 1)) |
+ (uhci->rh.c_p_r[wIndex - 1] << (0 + 4));
+ status = (status & USBPORTSC_CCS) |
+ ((status & USBPORTSC_PE) >> (2 - 1)) |
+ ((status & USBPORTSC_SUSP) >> (12 - 2)) |
+ ((status & USBPORTSC_PR) >> (9 - 4)) |
+ (1 << 8) | /* power on */
+ ((status & USBPORTSC_LSDA) << (-8 + 9));
+
+ *(__u16 *)data = cpu_to_le16(status);
+ *(__u16 *)(data + 2) = cpu_to_le16(cstatus);
+ OK(4);
+ case RH_CLEAR_FEATURE | RH_ENDPOINT:
+ switch (wValue) {
+ case RH_ENDPOINT_STALL:
+ OK(0);
+ }
+ break;
+ case RH_CLEAR_FEATURE | RH_CLASS:
+ switch (wValue) {
+ case RH_C_HUB_OVER_CURRENT:
+ OK(0); /* hub power over current */
+ }
+ break;
+ case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case RH_PORT_ENABLE:
+ CLR_RH_PORTSTAT(USBPORTSC_PE);
+ OK(0);
+ case RH_PORT_SUSPEND:
+ CLR_RH_PORTSTAT(USBPORTSC_SUSP);
+ OK(0);
+ case RH_PORT_POWER:
+ OK(0); /* port power */
+ case RH_C_PORT_CONNECTION:
+ SET_RH_PORTSTAT(USBPORTSC_CSC);
+ OK(0);
+ case RH_C_PORT_ENABLE:
+ SET_RH_PORTSTAT(USBPORTSC_PEC);
+ OK(0);
+ case RH_C_PORT_SUSPEND:
+ /*** WR_RH_PORTSTAT(RH_PS_PSSC); */
+ OK(0);
+ case RH_C_PORT_OVER_CURRENT:
+ OK(0); /* port power over current */
+ case RH_C_PORT_RESET:
+ uhci->rh.c_p_r[wIndex - 1] = 0;
+ OK(0);
+ }
+ break;
+ case RH_SET_FEATURE | RH_OTHER | RH_CLASS:
+ switch (wValue) {
+ case RH_PORT_SUSPEND:
+ SET_RH_PORTSTAT(USBPORTSC_SUSP);
+ OK(0);
+ case RH_PORT_RESET:
+ SET_RH_PORTSTAT(USBPORTSC_PR);
+ wait_ms(10);
+ uhci->rh.c_p_r[wIndex - 1] = 1;
+ CLR_RH_PORTSTAT(USBPORTSC_PR);
+ udelay(10);
+ SET_RH_PORTSTAT(USBPORTSC_PE);
+ wait_ms(10);
+ SET_RH_PORTSTAT(0xa);
+ OK(0);
+ case RH_PORT_POWER:
+ OK(0); /* port power ** */
+ case RH_PORT_ENABLE:
+ SET_RH_PORTSTAT (USBPORTSC_PE);
+ OK(0);
+ }
+ break;
+ case RH_SET_ADDRESS:
+ uhci->rh.devnum = wValue;
+ OK(0);
+ case RH_GET_DESCRIPTOR:
+ switch ((wValue & 0xff00) >> 8) {
+ case 0x01: /* device descriptor */
+ len = min(leni, min(sizeof(root_hub_dev_des), wLength));
+ memcpy(data, root_hub_dev_des, len);
+ OK(len);
+ case 0x02: /* configuration descriptor */
+ len = min(leni, min(sizeof(root_hub_config_des), wLength));
+ memcpy (data, root_hub_config_des, len);
+ OK(len);
+ case 0x03: /* string descriptors */
+ stat = -EPIPE;
+ }
+ break;
+ case RH_GET_DESCRIPTOR | RH_CLASS:
+ root_hub_hub_des[2] = uhci->rh.numports;
+ len = min(leni, min(sizeof(root_hub_hub_des), wLength));
+ memcpy(data, root_hub_hub_des, len);
+ OK(len);
+ case RH_GET_CONFIGURATION:
+ *(__u8 *)data = 0x01;
+ OK(1);
+ case RH_SET_CONFIGURATION:
+ OK(0);
+ default:
+ stat = -EPIPE;
+ }
+
+ urb->actual_length = len;
+ urb->status = stat;
+ if (urb->complete)
+ urb->complete(urb);
+
+ return USB_ST_NOERROR;
+}
+/*-------------------------------------------------------------------------*/
+
+static int rh_unlink_urb(urb_t *urb)
+{
+ struct uhci *uhci = (struct uhci *)urb->dev->bus->hcpriv;
+
+ uhci->rh.send = 0;
+ del_timer(&uhci->rh.rh_int_timer);
+
+ return 0;
+}
+/*-------------------------------------------------------------------*/
+
+/*
+ * This is just incredibly fragile. The timings must be just
+ * right, and they aren't really documented very well.
+ *
+ * Note the short delay between disabling reset and enabling
+ * the port..
+ */
+static void uhci_reset_port(unsigned int port)
+{
+ unsigned short status;
+
+ status = inw(port);
+ outw(status | USBPORTSC_PR, port); /* reset port */
+ wait_ms(10);
+ outw(status & ~USBPORTSC_PR, port);
+ udelay(50);
+
+ status = inw(port);
+ outw(status | USBPORTSC_PE, port); /* enable port */
+ wait_ms(10);
+
+ status = inw(port);
+ if (!(status & USBPORTSC_PE)) {
+ outw(status | USBPORTSC_PE, port); /* one more try at enabling port */
+ wait_ms(50);
+ }
+
+}
+
+void uhci_free_pending(struct uhci *uhci)
+{
+ struct list_head *tmp, *head;
+
+ /* Free all of the pending QH's and TD's */
+ head = &uhci->td_free_list;
+ tmp = head->next;
+ while (tmp != head) {
+ struct uhci_td *td = list_entry(tmp, struct uhci_td, list);
+
+ tmp = tmp->next;
+
+ list_del(&td->list);
+ INIT_LIST_HEAD(&td->list);
+
+ uhci_td_free(td);
+ }
+
+ head = &uhci->qh_free_list;
+ tmp = head->next;
+ while (tmp != head) {
+ struct uhci_qh *qh = list_entry(tmp, struct uhci_qh, list);
+
+ tmp = tmp->next;
+
+ list_del(&qh->list);
+ INIT_LIST_HEAD(&qh->list);
+
+ uhci_qh_free(qh);
+ }
+}
+
+static void uhci_interrupt(int irq, void *__uhci, struct pt_regs *regs)
+{
+ struct uhci *uhci = __uhci;
+ unsigned int io_addr = uhci->io_addr;
+ unsigned short status;
+ unsigned long flags;
+ struct list_head *tmp, *head;
+ urb_t *urb;
+
+ /*
+ * Read the interrupt status, and write it back to clear the
+ * interrupt cause
+ */
+ status = inw(io_addr + USBSTS);
+ if (!status) /* shared interrupt, not mine */
+ return;
+ outw(status, io_addr + USBSTS);
+
+ if (status & ~(USBSTS_USBINT | USBSTS_ERROR)) {
+ if (status & USBSTS_RD)
+ printk(KERN_INFO "uhci: resume detected, not implemented\n");
+ if (status & USBSTS_HSE)
+ printk(KERN_ERR "uhci: host system error, PCI problems?\n");
+ if (status & USBSTS_HCPE)
+ printk(KERN_ERR "uhci: host controller process error. something bad happened\n");
+ if (status & USBSTS_HCH) {
+ printk(KERN_ERR "uhci: host controller halted. very bad\n");
+ /* FIXME: Reset the controller, fix the offending TD */
+ }
+ }
+
+ /* Free all of the pending QH's and TD's */
+ spin_lock(&uhci->freelist_lock);
+ uhci_free_pending(uhci);
+ spin_unlock(&uhci->freelist_lock);
+
+ /* Walk the list of pending TD's to see which ones completed.. */
+ nested_lock(&uhci->irqlist_lock, flags);
+ head = &uhci->interrupt_list;
+ tmp = head->next;
+ while (tmp != head) {
+ struct uhci_td *td = list_entry(tmp, struct uhci_td, irq_list);
+
+ urb = td->urb;
+
+ tmp = tmp->next;
+
+ /* Checks the status and does all of the magic necessary */
+ uhci_transfer_result(urb);
+ }
+ nested_unlock(&uhci->irqlist_lock, flags);
+}
+
+static void reset_hc(struct uhci *uhci)
+{
+ unsigned int io_addr = uhci->io_addr;
+
+ /* Global reset for 50ms */
+ outw(USBCMD_GRESET, io_addr + USBCMD);
+ wait_ms(50);
+ outw(0, io_addr + USBCMD);
+ wait_ms(10);
+}
+
+static void start_hc(struct uhci *uhci)
+{
+ unsigned int io_addr = uhci->io_addr;
+ int timeout = 1000;
+
+ /*
+ * Reset the HC - this will force us to get a
+ * new notification of any already connected
+ * ports due to the virtual disconnect that it
+ * implies.
+ */
+ outw(USBCMD_HCRESET, io_addr + USBCMD);
+ while (inw(io_addr + USBCMD) & USBCMD_HCRESET) {
+ if (!--timeout) {
+ printk(KERN_ERR "uhci: USBCMD_HCRESET timed out!\n");
+ break;
+ }
+ }
+
+ /* Turn on all interrupts */
+ outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC | USBINTR_SP,
+ io_addr + USBINTR);
+
+ /* Start at frame 0 */
+ outw(0, io_addr + USBFRNUM);
+ outl(virt_to_bus(uhci->fl), io_addr + USBFLBASEADD);
+
+ /* Run and mark it configured with a 64-byte max packet */
+ outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, io_addr + USBCMD);
+}
+
+/*
+ * Allocate a frame list, and then setup the skeleton
+ *
+ * The hardware doesn't really know any difference
+ * in the queues, but the order does matter for the
+ * protocols higher up. The order is:
+ *
+ * - any isochronous events handled before any
+ * of the queues. We don't do that here, because
+ * we'll create the actual TD entries on demand.
+ * - The first queue is the "interrupt queue".
+ * - The second queue is the "control queue".
+ * - The third queue is "bulk data".
+ */
+static struct uhci *alloc_uhci(unsigned int io_addr, unsigned int io_size)
+{
+ int i, port;
+ struct uhci *uhci;
+ struct usb_bus *bus;
+
+ uhci = kmalloc(sizeof(*uhci), GFP_KERNEL);
+ if (!uhci)
+ return NULL;
+
+ memset(uhci, 0, sizeof(*uhci));
+
+ uhci->irq = -1;
+ uhci->io_addr = io_addr;
+ uhci->io_size = io_size;
+
+ INIT_LIST_HEAD(&uhci->interrupt_list);
+ INIT_LIST_HEAD(&uhci->urb_list);
+ INIT_LIST_HEAD(&uhci->td_free_list);
+ INIT_LIST_HEAD(&uhci->qh_free_list);
+
+ spin_lock_init(&uhci->urblist_lock);
+ spin_lock_init(&uhci->framelist_lock);
+ spin_lock_init(&uhci->freelist_lock);
+ nested_init(&uhci->irqlist_lock);
+
+ /* We need exactly one page (per UHCI specs), how convenient */
+ /* We assume that one page is atleast 4k (1024 frames * 4 bytes) */
+ uhci->fl = (void *)__get_free_page(GFP_KERNEL);
+ if (!uhci->fl)
+ goto au_free_uhci;
+
+ bus = usb_alloc_bus(&uhci_device_operations);
+ if (!bus)
+ goto au_free_fl;
+
+ uhci->bus = bus;
+ bus->hcpriv = uhci;
+
+ /* Initialize the root hub */
+
+ /* UHCI specs says devices must have 2 ports, but goes on to say */
+ /* they may have more but give no way to determine how many they */
+ /* have. However, according to the UHCI spec, Bit 7 is always set */
+ /* to 1. So we try to use this to our advantage */
+ for (port = 0; port < (io_size - 0x10) / 2; port++) {
+ unsigned int portstatus;
+
+ portstatus = inw(io_addr + 0x10 + (port * 2));
+ if (!(portstatus & 0x0080))
+ break;
+ }
+ if (debug)
+ info("detected %d ports", port);
+
+ /* This is experimental so anything less than 2 or greater than 8 is */
+ /* something weird and we'll ignore it */
+ if (port < 2 || port > 8) {
+ info("port count misdetected? forcing to 2 ports");
+ port = 2;
+ }
+
+ uhci->rh.numports = port;
+
+ /*
+ * 9 Interrupt queues; link int2 to int1, int4 to int2, etc
+ * then link int1 to control and control to bulk
+ */
+ for (i = 1; i < 9; i++) {
+ struct uhci_td *td = &uhci->skeltd[i];
+
+ uhci_fill_td(td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0);
+ td->link = virt_to_bus(&uhci->skeltd[i - 1]);
+ }
+
+
+ uhci_fill_td(&uhci->skel_int1_td, 0, (UHCI_NULL_DATA_SIZE << 21) | (0x7f << 8) | USB_PID_IN, 0);
+ uhci->skel_int1_td.link = virt_to_bus(&uhci->skel_control_qh) | UHCI_PTR_QH;
+
+ uhci->skel_control_qh.link = virt_to_bus(&uhci->skel_bulk_qh) | UHCI_PTR_QH;
+ uhci->skel_control_qh.element = UHCI_PTR_TERM;
+
+ uhci->skel_bulk_qh.link = UHCI_PTR_TERM;
+ uhci->skel_bulk_qh.element = UHCI_PTR_TERM;
+
+ /*
+ * Fill the frame list: make all entries point to
+ * the proper interrupt queue.
+ *
+ * This is probably silly, but it's a simple way to
+ * scatter the interrupt queues in a way that gives
+ * us a reasonable dynamic range for irq latencies.
+ */
+ for (i = 0; i < 1024; i++) {
+ struct uhci_td *irq = &uhci->skel_int2_td;
+
+ if (i & 1) {
+ irq++;
+ if (i & 2) {
+ irq++;
+ if (i & 4) {
+ irq++;
+ if (i & 8) {
+ irq++;
+ if (i & 16) {
+ irq++;
+ if (i & 32) {
+ irq++;
+ if (i & 64)
+ irq++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /* Only place we don't use the frame list routines */
+ uhci->fl->frame[i] = virt_to_bus(irq);
+ }
+
+ return uhci;
+
+/*
+ * error exits:
+ */
+au_free_fl:
+ free_page((unsigned long)uhci->fl);
+au_free_uhci:
+ kfree(uhci);
+
+ return NULL;
+}
+
+/*
+ * De-allocate all resources..
+ */
+static void release_uhci(struct uhci *uhci)
+{
+ if (uhci->irq >= 0) {
+ free_irq(uhci->irq, uhci);
+ uhci->irq = -1;
+ }
+
+ if (uhci->fl) {
+ free_page((unsigned long)uhci->fl);
+ uhci->fl = NULL;
+ }
+
+ usb_free_bus(uhci->bus);
+ kfree(uhci);
+}
+
+int uhci_start_root_hub(struct uhci *uhci)
+{
+ struct usb_device *usb_dev;
+
+ usb_dev = usb_alloc_dev(NULL, uhci->bus);
+ if (!usb_dev)
+ return -1;
+
+ usb_to_uhci(usb_dev)->uhci = uhci;
+
+ uhci->bus->root_hub = usb_dev;
+ usb_connect(usb_dev);
+
+ if (usb_new_device(usb_dev) != 0) {
+ usb_free_dev(usb_dev);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * If we've successfully found a UHCI, now is the time to increment the
+ * module usage count, and return success..
+ */
+static int setup_uhci(int irq, unsigned int io_addr, unsigned int io_size)
+{
+ int retval;
+ struct uhci *uhci;
+
+ uhci = alloc_uhci(io_addr, io_size);
+ if (!uhci)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&uhci->uhci_list);
+ list_add(&uhci->uhci_list, &uhci_list);
+
+ request_region(uhci->io_addr, io_size, "usb-uhci");
+
+ reset_hc(uhci);
+
+ usb_register_bus(uhci->bus);
+ start_hc(uhci);
+
+ retval = -EBUSY;
+ if (request_irq(irq, uhci_interrupt, SA_SHIRQ, "usb-uhci", uhci) == 0) {
+ uhci->irq = irq;
+
+ if (!uhci_start_root_hub(uhci))
+ return 0;
+ }
+
+ /* Couldn't allocate IRQ if we got here */
+ list_del(&uhci->uhci_list);
+ INIT_LIST_HEAD(&uhci->uhci_list);
+
+ reset_hc(uhci);
+ release_region(uhci->io_addr, uhci->io_size);
+ release_uhci(uhci);
+
+ return retval;
+}
+
+static int found_uhci(struct pci_dev *dev)
+{
+ int i;
+
+ /* Search for the IO base address.. */
+ for (i = 0; i < 6; i++) {
+ unsigned int io_addr = dev->resource[i].start;
+ unsigned int io_size =
+ dev->resource[i].end - dev->resource[i].start + 1;
+
+ /* IO address? */
+ if (!(dev->resource[i].flags & 1))
+ continue;
+
+ /* Is it already in use? */
+ if (check_region(io_addr, io_size))
+ break;
+
+ /* disable legacy emulation */
+ pci_write_config_word(dev, USBLEGSUP, USBLEGSUP_DEFAULT);
+
+ pci_enable_device(dev);
+
+ if (!dev->irq) {
+ err("found UHCI device with no IRQ assigned. check BIOS settings!");
+ continue;
+ }
+
+ return setup_uhci(dev->irq, io_addr, io_size);
+ }
+
+ return -1;
+}
+
+#ifdef CONFIG_APM
+static int handle_apm_event(apm_event_t event)
+{
+ static int down = 0;
+
+ switch (event) {
+ case APM_SYS_SUSPEND:
+ case APM_USER_SUSPEND:
+ if (down) {
+ dbg("received extra suspend event");
+ break;
+ }
+ down = 1;
+ break;
+ case APM_NORMAL_RESUME:
+ case APM_CRITICAL_RESUME:
+ if (!down) {
+ dbg("received bogus resume event");
+ break;
+ }
+ down = 0;
+ break;
+ }
+ return 0;
+}
+#endif
+
+int uhci_init(void)
+{
+ int retval;
+ struct pci_dev *dev;
+ u8 type;
+
+ retval = -ENOMEM;
+
+ /* We throw all of the TD's and QH's into a kmem cache */
+ /* TD's and QH's need to be 16 byte aligned and SLAB_HWCACHE_ALIGN */
+ /* does this for us */
+ uhci_td_cachep = kmem_cache_create("uhci_td",
+ sizeof(struct uhci_td), 0,
+ SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+ if (!uhci_td_cachep)
+ goto td_failed;
+
+ uhci_qh_cachep = kmem_cache_create("uhci_qh",
+ sizeof(struct uhci_qh), 0,
+ SLAB_HWCACHE_ALIGN, NULL, NULL);
+
+ if (!uhci_qh_cachep)
+ goto qh_failed;
+
+ retval = -ENODEV;
+ dev = NULL;
+ for (;;) {
+ dev = pci_find_class(PCI_CLASS_SERIAL_USB << 8, dev);
+ if (!dev)
+ break;
+
+ /* Is it the UHCI programming interface? */
+ pci_read_config_byte(dev, PCI_CLASS_PROG, &type);
+ if (type != 0)
+ continue;
+
+ /* Ok set it up */
+ retval = found_uhci(dev);
+ }
+
+ /* We only want to return an error code if ther was an error */
+ /* and we didn't find a UHCI controller */
+ if (retval && uhci_list.next == &uhci_list)
+ goto init_failed;
+
+#ifdef CONFIG_APM
+ apm_register_callback(&handle_apm_event);
+#endif
+
+ return 0;
+
+init_failed:
+ if (kmem_cache_destroy(uhci_qh_cachep))
+ printk(KERN_INFO "uhci: not all QH's were freed\n");
+
+qh_failed:
+ if (kmem_cache_destroy(uhci_td_cachep))
+ printk(KERN_INFO "uhci: not all TD's were freed\n");
+
+td_failed:
+ return retval;
+}
+
+void uhci_cleanup(void)
+{
+ struct list_head *next, *tmp, *head = &uhci_list;
+ int i;
+ unsigned long flags;
+
+ tmp = head->next;
+ while (tmp != head) {
+ struct uhci *uhci = list_entry(tmp, struct uhci, uhci_list);
+
+ next = tmp->next;
+
+ list_del(&uhci->uhci_list);
+ INIT_LIST_HEAD(&uhci->uhci_list);
+
+ if (uhci->bus->root_hub)
+ usb_disconnect(&uhci->bus->root_hub);
+
+ usb_deregister_bus(uhci->bus);
+
+ reset_hc(uhci);
+ release_region(uhci->io_addr, uhci->io_size);
+
+ /* Free any outstanding TD's and QH's */
+ spin_lock_irqsave(&uhci->freelist_lock, flags);
+ uhci_free_pending(uhci);
+ spin_unlock_irqrestore(&uhci->freelist_lock, flags);
+
+ release_uhci(uhci);
+
+ tmp = next;
+ }
+
+ if (kmem_cache_destroy(uhci_qh_cachep))
+ printk(KERN_INFO "uhci: not all QH's were freed\n");
+
+ if (kmem_cache_destroy(uhci_td_cachep))
+ printk(KERN_INFO "uhci: not all TD's were freed\n");
+}
+
+#ifdef MODULE
+int init_module(void)
+{
+ return uhci_init();
+}
+
+void cleanup_module(void)
+{
+#ifdef CONFIG_APM
+ apm_unregister_callback(&handle_apm_event);
+#endif
+ uhci_cleanup();
+}
+#endif //MODULE
+
diff --git a/drivers/usb/uhci.h b/drivers/usb/uhci.h
new file mode 100644
index 000000000..65c597861
--- /dev/null
+++ b/drivers/usb/uhci.h
@@ -0,0 +1,425 @@
+#ifndef __LINUX_UHCI_H
+#define __LINUX_UHCI_H
+
+#include <linux/list.h>
+
+#include "usb.h"
+
+/*
+ * This nested spinlock code is courtesy of Davide Libenzi <dlibenzi@maticad.it>
+ */
+struct s_nested_lock {
+ spinlock_t lock;
+ void *uniq;
+ short int count;
+};
+
+#define nested_init(snl) \
+ spin_lock_init(&(snl)->lock); \
+ (snl)->uniq = NULL; \
+ (snl)->count = 0;
+
+#define nested_lock(snl, flags) \
+ if ((snl)->uniq == current) { \
+ (snl)->count++; \
+ flags = 0; /* No warnings */ \
+ } else { \
+ spin_lock_irqsave(&(snl)->lock, flags); \
+ (snl)->count++; \
+ (snl)->uniq = current; \
+ }
+
+#define nested_unlock(snl, flags) \
+ if (!--(snl)->count) { \
+ (snl)->uniq = NULL; \
+ spin_unlock_irqrestore(&(snl)->lock, flags); \
+ }
+
+/*
+ * Universal Host Controller Interface data structures and defines
+ */
+
+/* Command register */
+#define USBCMD 0
+#define USBCMD_RS 0x0001 /* Run/Stop */
+#define USBCMD_HCRESET 0x0002 /* Host reset */
+#define USBCMD_GRESET 0x0004 /* Global reset */
+#define USBCMD_EGSM 0x0008 /* Global Suspend Mode */
+#define USBCMD_FGR 0x0010 /* Force Global Resume */
+#define USBCMD_SWDBG 0x0020 /* SW Debug mode */
+#define USBCMD_CF 0x0040 /* Config Flag (sw only) */
+#define USBCMD_MAXP 0x0080 /* Max Packet (0 = 32, 1 = 64) */
+
+/* Status register */
+#define USBSTS 2
+#define USBSTS_USBINT 0x0001 /* Interrupt due to IOC */
+#define USBSTS_ERROR 0x0002 /* Interrupt due to error */
+#define USBSTS_RD 0x0004 /* Resume Detect */
+#define USBSTS_HSE 0x0008 /* Host System Error - basically PCI problems */
+#define USBSTS_HCPE 0x0010 /* Host Controller Process Error - the scripts were buggy */
+#define USBSTS_HCH 0x0020 /* HC Halted */
+
+/* Interrupt enable register */
+#define USBINTR 4
+#define USBINTR_TIMEOUT 0x0001 /* Timeout/CRC error enable */
+#define USBINTR_RESUME 0x0002 /* Resume interrupt enable */
+#define USBINTR_IOC 0x0004 /* Interrupt On Complete enable */
+#define USBINTR_SP 0x0008 /* Short packet interrupt enable */
+
+#define USBFRNUM 6
+#define USBFLBASEADD 8
+#define USBSOF 12
+
+/* USB port status and control registers */
+#define USBPORTSC1 16
+#define USBPORTSC2 18
+#define USBPORTSC_CCS 0x0001 /* Current Connect Status ("device present") */
+#define USBPORTSC_CSC 0x0002 /* Connect Status Change */
+#define USBPORTSC_PE 0x0004 /* Port Enable */
+#define USBPORTSC_PEC 0x0008 /* Port Enable Change */
+#define USBPORTSC_LS 0x0030 /* Line Status */
+#define USBPORTSC_RD 0x0040 /* Resume Detect */
+#define USBPORTSC_LSDA 0x0100 /* Low Speed Device Attached */
+#define USBPORTSC_PR 0x0200 /* Port Reset */
+#define USBPORTSC_SUSP 0x1000 /* Suspend */
+
+/* Legacy support register */
+#define USBLEGSUP 0xc0
+#define USBLEGSUP_DEFAULT 0x2000 /* only PIRQ enable set */
+
+#define UHCI_NULL_DATA_SIZE 0x7FF /* for UHCI controller TD */
+
+#define UHCI_PTR_BITS 0x000F
+#define UHCI_PTR_TERM 0x0001
+#define UHCI_PTR_QH 0x0002
+#define UHCI_PTR_DEPTH 0x0004
+
+#define UHCI_NUMFRAMES 1024 /* in the frame list [array] */
+#define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */
+#define CAN_SCHEDULE_FRAMES 1000 /* how far future frames can be scheduled */
+
+struct uhci_td;
+
+struct uhci_qh {
+ /* Hardware fields */
+ __u32 link; /* Next queue */
+ __u32 element; /* Queue element pointer */
+
+ /* Software fields */
+ struct uhci_qh *prevqh, *nextqh; /* Previous and next TD in queue */
+
+ struct uhci_device *dev; /* The owning device */
+
+ struct list_head list;
+} __attribute__((aligned(16)));
+
+struct uhci_framelist {
+ __u32 frame[UHCI_NUMFRAMES];
+} __attribute__((aligned(4096)));
+
+/*
+ * for TD <status>:
+ */
+#define TD_CTRL_SPD (1 << 29) /* Short Packet Detect */
+#define TD_CTRL_C_ERR_MASK (3 << 27) /* Error Counter bits */
+#define TD_CTRL_LS (1 << 26) /* Low Speed Device */
+#define TD_CTRL_IOS (1 << 25) /* Isochronous Select */
+#define TD_CTRL_IOC (1 << 24) /* Interrupt on Complete */
+#define TD_CTRL_ACTIVE (1 << 23) /* TD Active */
+#define TD_CTRL_STALLED (1 << 22) /* TD Stalled */
+#define TD_CTRL_DBUFERR (1 << 21) /* Data Buffer Error */
+#define TD_CTRL_BABBLE (1 << 20) /* Babble Detected */
+#define TD_CTRL_NAK (1 << 19) /* NAK Received */
+#define TD_CTRL_CRCTIMEO (1 << 18) /* CRC/Time Out Error */
+#define TD_CTRL_BITSTUFF (1 << 17) /* Bit Stuff Error */
+#define TD_CTRL_ACTLEN_MASK 0x7FF /* actual length, encoded as n - 1 */
+
+#define TD_CTRL_ANY_ERROR (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \
+ TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF)
+
+#define uhci_status_bits(ctrl_sts) (ctrl_sts & 0xFE0000)
+#define uhci_actual_length(ctrl_sts) ((ctrl_sts + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
+
+#define uhci_ptr_to_virt(x) bus_to_virt(x & ~UHCI_PTR_BITS)
+
+/*
+ * for TD <info>: (a.k.a. Token)
+ */
+#define TD_TOKEN_TOGGLE 19
+#define TD_PID 0xFF
+
+#define uhci_maxlen(token) ((token) >> 21)
+#define uhci_expected_length(info) (((info >> 21) + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
+#define uhci_toggle(token) (((token) >> TD_TOKEN_TOGGLE) & 1)
+#define uhci_endpoint(token) (((token) >> 15) & 0xf)
+#define uhci_devaddr(token) (((token) >> 8) & 0x7f)
+#define uhci_devep(token) (((token) >> 8) & 0x7ff)
+#define uhci_packetid(token) ((token) & 0xff)
+#define uhci_packetout(token) (uhci_packetid(token) != USB_PID_IN)
+#define uhci_packetin(token) (uhci_packetid(token) == USB_PID_IN)
+
+/*
+ * The documentation says "4 words for hardware, 4 words for software".
+ *
+ * That's silly, the hardware doesn't care. The hardware only cares that
+ * the hardware words are 16-byte aligned, and we can have any amount of
+ * sw space after the TD entry as far as I can tell.
+ *
+ * But let's just go with the documentation, at least for 32-bit machines.
+ * On 64-bit machines we probably want to take advantage of the fact that
+ * hw doesn't really care about the size of the sw-only area.
+ *
+ * Alas, not anymore, we have more than 4 words for software, woops
+ */
+struct uhci_td {
+ /* Hardware fields */
+ __u32 link;
+ __u32 status;
+ __u32 info;
+ __u32 buffer;
+
+ /* Software fields */
+ unsigned int *frameptr; /* Frame list pointer */
+ struct uhci_td *prevtd, *nexttd; /* Previous and next TD in queue */
+
+ struct uhci_device *dev;
+ struct urb *urb; /* URB this TD belongs to */
+ struct uhci_td *next; /* List of chained TD's for an URB */
+
+ struct list_head irq_list; /* Active interrupt list.. */
+ struct list_head list;
+} __attribute__((aligned(16)));
+
+/*
+ * Note the alignment requirements of the entries
+ *
+ * Each UHCI device has pre-allocated QH and TD entries.
+ * You can use more than the pre-allocated ones, but I
+ * don't see you usually needing to.
+ */
+struct uhci;
+
+struct uhci_device {
+ struct usb_device *usb;
+
+ atomic_t refcnt;
+
+ struct uhci *uhci; /* HC this device is connected to */
+};
+
+#define uhci_to_usb(uhci) ((uhci)->usb)
+#define usb_to_uhci(usb) ((struct uhci_device *)(usb)->hcpriv)
+
+/*
+ * There are various standard queues. We set up several different
+ * queues for each of the three basic queue types: interrupt,
+ * control, and bulk.
+ *
+ * - There are various different interrupt latencies: ranging from
+ * every other USB frame (2 ms apart) to every 256 USB frames (ie
+ * 256 ms apart). Make your choice according to how obnoxious you
+ * want to be on the wire, vs how critical latency is for you.
+ * - The control list is done every frame.
+ * - There are 4 bulk lists, so that up to four devices can have a
+ * bulk list of their own and when run concurrently all four lists
+ * will be be serviced.
+ *
+ * This is a bit misleading, there are various interrupt latencies, but they
+ * vary a bit, interrupt2 isn't exactly 2ms, it can vary up to 4ms since the
+ * other queues can "override" it. interrupt4 can vary up to 8ms, etc. Minor
+ * problem
+ *
+ * In the case of the root hub, these QH's are just head's of qh's. Don't
+ * be scared, it kinda makes sense. Look at this wonderful picture care of
+ * Linus:
+ *
+ * generic- -> dev1- -> generic- -> dev1- -> control- -> bulk- -> ...
+ * iso-QH iso-QH irq-QH irq-QH QH QH
+ * | | | | | |
+ * End dev1-iso-TD1 End dev1-irq-TD1 ... ...
+ * |
+ * dev1-iso-TD2
+ * |
+ * ....
+ *
+ * This may vary a bit (the UHCI docs don't explicitly say you can put iso
+ * transfers in QH's and all of their pictures don't have that either) but
+ * other than that, that is what we're doing now
+ *
+ * And now we don't put Iso transfers in QH's, so we don't waste one on it
+ * --jerdfelt
+ *
+ * To keep with Linus' nomenclature, this is called the QH skeleton. These
+ * labels (below) are only signficant to the root hub's QH's
+ */
+
+#define UHCI_NUM_SKELTD 9
+#define skel_int1_td skeltd[0]
+#define skel_int2_td skeltd[1]
+#define skel_int4_td skeltd[2]
+#define skel_int8_td skeltd[3]
+#define skel_int16_td skeltd[4]
+#define skel_int32_td skeltd[5]
+#define skel_int64_td skeltd[6]
+#define skel_int128_td skeltd[7]
+#define skel_int256_td skeltd[8]
+
+#define UHCI_NUM_SKELQH 2
+#define skel_control_qh skelqh[0]
+#define skel_bulk_qh skelqh[1]
+
+/*
+ * Search tree for determining where <interval> fits in the
+ * skelqh[] skeleton.
+ *
+ * An interrupt request should be placed into the slowest skelqh[]
+ * which meets the interval/period/frequency requirement.
+ * An interrupt request is allowed to be faster than <interval> but not slower.
+ *
+ * For a given <interval>, this function returns the appropriate/matching
+ * skelqh[] index value.
+ *
+ * NOTE: For UHCI, we don't really need int256_qh since the maximum interval
+ * is 255 ms. However, we do need an int1_qh since 1 is a valid interval
+ * and we should meet that frequency when requested to do so.
+ * This will require some change(s) to the UHCI skeleton.
+ */
+static inline int __interval_to_skel(int interval)
+{
+ if (interval < 16) {
+ if (interval < 4) {
+ if (interval < 2)
+ return 0; /* int1 for 0-1 ms */
+ return 1; /* int2 for 2-3 ms */
+ }
+ if (interval < 8)
+ return 2; /* int4 for 4-7 ms */
+ return 3; /* int8 for 8-15 ms */
+ }
+ if (interval < 64) {
+ if (interval < 32)
+ return 4; /* int16 for 16-31 ms */
+ return 5; /* int32 for 32-63 ms */
+ }
+ if (interval < 128)
+ return 6; /* int64 for 64-127 ms */
+ return 7; /* int128 for 128-255 ms (Max.) */
+}
+
+struct virt_root_hub {
+ int devnum; /* Address of Root Hub endpoint */
+ void *urb;
+ void *int_addr;
+ int send;
+ int interval;
+ int numports;
+ int c_p_r[8];
+ struct timer_list rh_int_timer;
+};
+
+/*
+ * This describes the full uhci information.
+ *
+ * Note how the "proper" USB information is just
+ * a subset of what the full implementation needs.
+ */
+struct uhci {
+ int irq;
+ unsigned int io_addr;
+ unsigned int io_size;
+
+ struct list_head uhci_list;
+
+ struct usb_bus *bus;
+
+ struct uhci_td skeltd[UHCI_NUM_SKELTD]; /* Skeleton TD's */
+ struct uhci_qh skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */
+
+ struct uhci_framelist *fl; /* Frame list */
+
+ struct s_nested_lock irqlist_lock;
+ struct list_head interrupt_list; /* List of interrupt-active TD's for this uhci */
+
+ spinlock_t urblist_lock;
+ struct list_head urb_list;
+
+ spinlock_t framelist_lock;
+
+ spinlock_t freelist_lock;
+ struct list_head td_free_list;
+ struct list_head qh_free_list;
+
+ struct virt_root_hub rh; /* private data of the virtual root hub */
+};
+
+struct urb_priv {
+ struct uhci_qh *qh; /* QH for this URB */
+ struct uhci_td *begin;
+ struct uhci_td *end;
+};
+
+/* -------------------------------------------------------------------------
+ Virtual Root HUB
+ ------------------------------------------------------------------------- */
+/* destination of request */
+#define RH_INTERFACE 0x01
+#define RH_ENDPOINT 0x02
+#define RH_OTHER 0x03
+
+#define RH_CLASS 0x20
+#define RH_VENDOR 0x40
+
+/* Requests: bRequest << 8 | bmRequestType */
+#define RH_GET_STATUS 0x0080
+#define RH_CLEAR_FEATURE 0x0100
+#define RH_SET_FEATURE 0x0300
+#define RH_SET_ADDRESS 0x0500
+#define RH_GET_DESCRIPTOR 0x0680
+#define RH_SET_DESCRIPTOR 0x0700
+#define RH_GET_CONFIGURATION 0x0880
+#define RH_SET_CONFIGURATION 0x0900
+#define RH_GET_STATE 0x0280
+#define RH_GET_INTERFACE 0x0A80
+#define RH_SET_INTERFACE 0x0B00
+#define RH_SYNC_FRAME 0x0C80
+/* Our Vendor Specific Request */
+#define RH_SET_EP 0x2000
+
+/* Hub port features */
+#define RH_PORT_CONNECTION 0x00
+#define RH_PORT_ENABLE 0x01
+#define RH_PORT_SUSPEND 0x02
+#define RH_PORT_OVER_CURRENT 0x03
+#define RH_PORT_RESET 0x04
+#define RH_PORT_POWER 0x08
+#define RH_PORT_LOW_SPEED 0x09
+#define RH_C_PORT_CONNECTION 0x10
+#define RH_C_PORT_ENABLE 0x11
+#define RH_C_PORT_SUSPEND 0x12
+#define RH_C_PORT_OVER_CURRENT 0x13
+#define RH_C_PORT_RESET 0x14
+
+/* Hub features */
+#define RH_C_HUB_LOCAL_POWER 0x00
+#define RH_C_HUB_OVER_CURRENT 0x01
+#define RH_DEVICE_REMOTE_WAKEUP 0x00
+#define RH_ENDPOINT_STALL 0x01
+
+/* Our Vendor Specific feature */
+#define RH_REMOVE_EP 0x00
+
+#define RH_ACK 0x01
+#define RH_REQ_ERR -1
+#define RH_NACK 0x00
+
+/* needed for the debugging code */
+struct uhci_td *uhci_link_to_td(unsigned int element);
+
+/* Debugging code */
+void uhci_show_td(struct uhci_td *td);
+void uhci_show_status(struct uhci *uhci);
+void uhci_show_queue(struct uhci_qh *qh);
+void uhci_show_queues(struct uhci *uhci);
+
+#endif
+
diff --git a/drivers/usb/usb-core.c b/drivers/usb/usb-core.c
index 68927a086..9e7557e8f 100644
--- a/drivers/usb/usb-core.c
+++ b/drivers/usb/usb-core.c
@@ -132,6 +132,9 @@ int usb_init(void)
#ifdef CONFIG_USB_UHCI
uhci_init();
#endif
+#ifdef CONFIG_USB_UHCI_ALT
+ uhci_init();
+#endif
#ifdef CONFIG_USB_OHCI
ohci_hcd_init();
#endif
diff --git a/drivers/usb/usb-serial.c b/drivers/usb/usb-serial.c
index 9f37fcc9e..f30057d9c 100644
--- a/drivers/usb/usb-serial.c
+++ b/drivers/usb/usb-serial.c
@@ -996,7 +996,7 @@ static int whiteheat_writememory (struct usb_serial *serial, int address, unsign
// dbg("whiteheat_writememory %x, %d", address, length);
if (!transfer_buffer) {
- err("whiteheat_writememory: kmalloc(%d) failed.\n", length);
+ err("whiteheat_writememory: kmalloc(%d) failed.", length);
return -ENOMEM;
}
memcpy (transfer_buffer, data, length);
@@ -1078,7 +1078,7 @@ static int whiteheat_startup (struct usb_serial *serial)
response = whiteheat_writememory (serial, record->address,
(unsigned char *)record->data, record->data_size, 0xa0);
if (response < 0) {
- err("whiteheat_writememory failed for second firmware step (%d %04X %p %d)\n",
+ err("whiteheat_writememory failed for second firmware step (%d %04X %p %d)",
response, record->address, record->data, record->data_size);
break;
}
@@ -1127,7 +1127,7 @@ static void visor_serial_close(struct tty_struct *tty, struct file * filp)
dbg("visor_serial_close port %d", port);
if (!transfer_buffer) {
- err("visor_serial_close: kmalloc(%d) failed.\n", 0x12);
+ err("visor_serial_close: kmalloc(%d) failed.", 0x12);
} else {
/* send a shutdown message to the device */
usb_control_msg (serial->dev, usb_rcvctrlpipe(serial->dev, 0), VISOR_CLOSE_NOTIFICATION,
@@ -1175,7 +1175,7 @@ static int visor_startup (struct usb_serial *serial)
unsigned char *transfer_buffer = kmalloc (256, GFP_KERNEL);
if (!transfer_buffer) {
- err("visor_startup: kmalloc(%d) failed.\n", 256);
+ err("visor_startup: kmalloc(%d) failed.", 256);
return -ENOMEM;
}
diff --git a/drivers/usb/usb-uhci-debug.h b/drivers/usb/usb-uhci-debug.h
new file mode 100644
index 000000000..73d16937a
--- /dev/null
+++ b/drivers/usb/usb-uhci-debug.h
@@ -0,0 +1,195 @@
+#ifdef DEBUG
+
+static void uhci_show_qh (puhci_desc_t qh)
+{
+ if (qh->type != QH_TYPE) {
+ dbg("qh has not QH_TYPE");
+ return;
+ }
+ dbg("uhci_show_qh %p (%08lX):", qh, virt_to_bus (qh));
+
+ if (qh->hw.qh.head & UHCI_PTR_TERM)
+ dbg("Head Terminate");
+ else {
+ if (qh->hw.qh.head & UHCI_PTR_QH)
+ dbg("Head points to QH");
+ else
+ dbg("Head points to TD");
+
+ dbg("head: %08X", qh->hw.qh.head & ~UHCI_PTR_BITS);
+ }
+ if (qh->hw.qh.element & UHCI_PTR_TERM)
+ dbg("Element Terminate");
+ else {
+
+ if (qh->hw.qh.element & UHCI_PTR_QH)
+ dbg("Element points to QH");
+ else
+ dbg("Element points to TD");
+ dbg("element: %08X", qh->hw.qh.element & ~UHCI_PTR_BITS);
+ }
+}
+#endif
+
+static void uhci_show_td (puhci_desc_t td)
+{
+ char *spid;
+ warn("uhci_show_td %p (%08lX) ", td, virt_to_bus (td));
+
+ switch (td->hw.td.info & 0xff) {
+ case USB_PID_SETUP:
+ spid = "SETUP";
+ break;
+ case USB_PID_OUT:
+ spid = " OUT ";
+ break;
+ case USB_PID_IN:
+ spid = " IN ";
+ break;
+ default:
+ spid = " ? ";
+ break;
+ }
+
+ warn("MaxLen=%02x DT%d EndPt=%x Dev=%x, PID=%x(%s) (buf=%08x)",
+ td->hw.td.info >> 21,
+ ((td->hw.td.info >> 19) & 1),
+ (td->hw.td.info >> 15) & 15,
+ (td->hw.td.info >> 8) & 127,
+ (td->hw.td.info & 0xff),
+ spid,
+ td->hw.td.buffer);
+
+ warn("Len=%02x e%d %s%s%s%s%s%s%s%s%s%s",
+ td->hw.td.status & 0x7ff,
+ ((td->hw.td.status >> 27) & 3),
+ (td->hw.td.status & TD_CTRL_SPD) ? "SPD " : "",
+ (td->hw.td.status & TD_CTRL_LS) ? "LS " : "",
+ (td->hw.td.status & TD_CTRL_IOC) ? "IOC " : "",
+ (td->hw.td.status & TD_CTRL_ACTIVE) ? "Active " : "",
+ (td->hw.td.status & TD_CTRL_STALLED) ? "Stalled " : "",
+ (td->hw.td.status & TD_CTRL_DBUFERR) ? "DataBufErr " : "",
+ (td->hw.td.status & TD_CTRL_BABBLE) ? "Babble " : "",
+ (td->hw.td.status & TD_CTRL_NAK) ? "NAK " : "",
+ (td->hw.td.status & TD_CTRL_CRCTIMEO) ? "CRC/Timeo " : "",
+ (td->hw.td.status & TD_CTRL_BITSTUFF) ? "BitStuff " : ""
+ );
+#if 1
+ if (td->hw.td.link & UHCI_PTR_TERM)
+ warn("Link Terminate");
+ else {
+ if (td->hw.td.link & UHCI_PTR_QH)
+ warn("%s, link points to QH @ %08x",
+ (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : " Breadth first"),
+ td->hw.td.link & ~UHCI_PTR_BITS);
+ else
+ warn("%s, link points to TD @ %08x",
+ (td->hw.td.link & UHCI_PTR_DEPTH ? "Depth first" : " Breadth first"),
+ td->hw.td.link & ~UHCI_PTR_BITS);
+ }
+#endif
+}
+#ifdef DEBUG
+static void uhci_show_td_queue (puhci_desc_t td)
+{
+ dbg("uhci_show_td_queue %p (%08lX):", td, virt_to_bus (td));
+ while (1) {
+ uhci_show_td (td);
+ if (td->hw.td.link & UHCI_PTR_TERM)
+ break;
+ //if(!(td->hw.td.link&UHCI_PTR_DEPTH))
+ // break;
+ if (td != bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS))
+ td = bus_to_virt (td->hw.td.link & ~UHCI_PTR_BITS);
+ else {
+ dbg("td points to itself!");
+ break;
+ }
+// schedule();
+ }
+}
+
+static void uhci_show_queue (puhci_desc_t qh)
+{
+ dbg("uhci_show_queue %p:", qh);
+ while (1) {
+ uhci_show_qh (qh);
+
+ if (qh->hw.qh.element & UHCI_PTR_QH)
+ dbg("Warning: qh->element points to qh!");
+ else if (!(qh->hw.qh.element & UHCI_PTR_TERM))
+ uhci_show_td_queue (bus_to_virt (qh->hw.qh.element & ~UHCI_PTR_BITS));
+
+ if (qh->hw.qh.head & UHCI_PTR_TERM)
+ break;
+
+ if (qh != bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS))
+ qh = bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS);
+ else {
+ dbg("qh points to itself!");
+ break;
+ }
+ }
+}
+
+static void uhci_show_sc (int port, unsigned short status)
+{
+ dbg(" stat%d = %04x %s%s%s%s%s%s%s%s",
+ port,
+ status,
+ (status & USBPORTSC_SUSP) ? "PortSuspend " : "",
+ (status & USBPORTSC_PR) ? "PortReset " : "",
+ (status & USBPORTSC_LSDA) ? "LowSpeed " : "",
+ (status & USBPORTSC_RD) ? "ResumeDetect " : "",
+ (status & USBPORTSC_PEC) ? "EnableChange " : "",
+ (status & USBPORTSC_PE) ? "PortEnabled " : "",
+ (status & USBPORTSC_CSC) ? "ConnectChange " : "",
+ (status & USBPORTSC_CCS) ? "PortConnected " : "");
+}
+
+void uhci_show_status (puhci_t s)
+{
+ unsigned int io_addr = s->io_addr;
+ unsigned short usbcmd, usbstat, usbint, usbfrnum;
+ unsigned int flbaseadd;
+ unsigned char sof;
+ unsigned short portsc1, portsc2;
+
+ usbcmd = inw (io_addr + 0);
+ usbstat = inw (io_addr + 2);
+ usbint = inw (io_addr + 4);
+ usbfrnum = inw (io_addr + 6);
+ flbaseadd = inl (io_addr + 8);
+ sof = inb (io_addr + 12);
+ portsc1 = inw (io_addr + 16);
+ portsc2 = inw (io_addr + 18);
+
+ dbg(" usbcmd = %04x %s%s%s%s%s%s%s%s",
+ usbcmd,
+ (usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ",
+ (usbcmd & USBCMD_CF) ? "CF " : "",
+ (usbcmd & USBCMD_SWDBG) ? "SWDBG " : "",
+ (usbcmd & USBCMD_FGR) ? "FGR " : "",
+ (usbcmd & USBCMD_EGSM) ? "EGSM " : "",
+ (usbcmd & USBCMD_GRESET) ? "GRESET " : "",
+ (usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
+ (usbcmd & USBCMD_RS) ? "RS " : "");
+
+ dbg(" usbstat = %04x %s%s%s%s%s%s",
+ usbstat,
+ (usbstat & USBSTS_HCH) ? "HCHalted " : "",
+ (usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "",
+ (usbstat & USBSTS_HSE) ? "HostSystemError " : "",
+ (usbstat & USBSTS_RD) ? "ResumeDetect " : "",
+ (usbstat & USBSTS_ERROR) ? "USBError " : "",
+ (usbstat & USBSTS_USBINT) ? "USBINT " : "");
+
+ dbg(" usbint = %04x", usbint);
+ dbg(" usbfrnum = (%d)%03x", (usbfrnum >> 10) & 1,
+ 0xfff & (4 * (unsigned int) usbfrnum));
+ dbg(" flbaseadd = %08x", flbaseadd);
+ dbg(" sof = %02x", sof);
+ uhci_show_sc (1, portsc1);
+ uhci_show_sc (2, portsc2);
+}
+#endif
diff --git a/drivers/usb/usb-uhci.c b/drivers/usb/usb-uhci.c
index 3fe469699..a85dfab5a 100644
--- a/drivers/usb/usb-uhci.c
+++ b/drivers/usb/usb-uhci.c
@@ -43,7 +43,7 @@
#include "usb.h"
#include "usb-uhci.h"
-#include "uhci-debug.h"
+#include "usb-uhci-debug.h"
#ifdef CONFIG_APM
#include <linux/apm_bios.h>
diff --git a/drivers/usb/usb.c b/drivers/usb/usb.c
index 213f69036..32d6e519e 100644
--- a/drivers/usb/usb.c
+++ b/drivers/usb/usb.c
@@ -1595,17 +1595,34 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
tbuf = kmalloc(256, GFP_KERNEL);
if (!tbuf)
return -ENOMEM;
+
+ /* get langid for strings if it's not yet known */
+ if (!dev->have_langid) {
+ err = usb_get_string(dev, 0, 0, tbuf, 4);
+ if (err < 0) {
+ err("error getting string descriptor 0 (error=%d)", err);
+ goto errout;
+ } else if (tbuf[0] < 4) {
+ err("string descriptor 0 too short");
+ err = -EINVAL;
+ goto errout;
+ } else {
+ dev->have_langid = -1;
+ dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
+ /* always use the first langid listed */
+ info("USB device number %d default language ID 0x%x",
+ dev->devnum, dev->string_langid);
+ }
+ }
+
/*
- * is this two step process necessary? can't we just
- * ask for a maximum length string and then take the length
- * that was returned?
+ * Just ask for a maximum length string and then take the length
+ * that was returned.
*/
- err = usb_get_string(dev, dev->string_langid, index, tbuf, 4);
- if (err < 0)
- goto errout;
- err = usb_get_string(dev, dev->string_langid, index, tbuf, tbuf[0]);
+ err = usb_get_string(dev, dev->string_langid, index, tbuf, 255);
if (err < 0)
goto errout;
+ info("actual string desc. length = %d", err);
size--; /* leave room for trailing NULL char in output buffer */
for (idx = 0, u = 2; u < err; u += 2) {
@@ -1633,7 +1650,6 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
*/
int usb_new_device(struct usb_device *dev)
{
- unsigned char *buf;
int addr, err;
int tmp;
@@ -1709,21 +1725,6 @@ int usb_new_device(struct usb_device *dev)
err("failed to set default configuration");
return -1;
}
- /* get langid for strings */
- buf = kmalloc(256, GFP_KERNEL);
- if (!buf) {
- err("out of memory\n");
- } else {
- err = usb_get_string(dev, 0, 0, buf, 4);
- if (err < 0) {
- err("error getting string descriptor 0 (error=%d)\n", err);
- } else if (buf[0] < 4) {
- err("string descriptpr 0 too short\n");
- } else
- dev->string_langid = buf[2] | (buf[3]<< 8);
- kfree(buf);
- info("USB device number %d default language ID 0x%x", dev->devnum, dev->string_langid);
- }
if (dev->descriptor.iManufacturer)
usb_show_string(dev, "Manufacturer", dev->descriptor.iManufacturer);
diff --git a/drivers/usb/usb.h b/drivers/usb/usb.h
index ec2754b1f..a7b027bf2 100644
--- a/drivers/usb/usb.h
+++ b/drivers/usb/usb.h
@@ -509,6 +509,7 @@ struct usb_device {
struct usb_device_descriptor descriptor;/* Descriptor */
struct usb_config_descriptor *config; /* All of the configs */
+ int have_langid; /* whether string_langid is valid yet */
int string_langid; /* language ID for strings */
void *hcpriv; /* Host Controller private data */
diff --git a/drivers/video/dn_accel.h b/drivers/video/dn_accel.h
new file mode 100644
index 000000000..b39be932d
--- /dev/null
+++ b/drivers/video/dn_accel.h
@@ -0,0 +1,9 @@
+#ifndef _DN_ACCEL_H_
+#define _DN_ACCEL_H_
+
+#include <linux/fb.h>
+
+void dn_bitblt(struct display *p,int x_src,int y_src, int x_dest, int y_dest,
+ int x_count, int y_count);
+
+#endif
diff --git a/drivers/video/dn_cfb4.c b/drivers/video/dn_cfb4.c
new file mode 100644
index 000000000..453eb52d6
--- /dev/null
+++ b/drivers/video/dn_cfb4.c
@@ -0,0 +1,546 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#include <asm/apollohw.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <video/fbcon.h>
+#include <video/fbcon-mfb.h>
+#include "dn_accel.h"
+
+/* apollo video HW definitions */
+
+/*
+ * Control Registers. IOBASE + $x
+ *
+ * Note: these are the Memory/IO BASE definitions for a mono card set to the
+ * alternate address
+ *
+ * Control 3A and 3B serve identical functions except that 3A
+ * deals with control 1 and 3b deals with Color LUT reg.
+ */
+
+#define AP_IOBASE 0x3d0 /* Base address of 1 plane board. */
+#define AP_STATUS isaIO2mem(AP_IOBASE+0) /* Status register. Read */
+#define AP_WRITE_ENABLE isaIO2mem(AP_IOBASE+0) /* Write Enable Register Write */
+#define AP_DEVICE_ID isaIO2mem(AP_IOBASE+1) /* Device ID Register. Read */
+#define AP_ROP_1 isaIO2mem(AP_IOBASE+2) /* Raster Operation reg. Write Word */
+#define AP_DIAG_MEM_REQ isaIO2mem(AP_IOBASE+4) /* Diagnostic Memory Request. Write Word */
+#define AP_CONTROL_0 isaIO2mem(AP_IOBASE+8) /* Control Register 0. Read/Write */
+#define AP_CONTROL_1 isaIO2mem(AP_IOBASE+0xa) /* Control Register 1. Read/Write */
+#define AP_CONTROL_2 isaIO2mem(AP_IOBASE+0xc) /* Control Register 2. Read/Write */
+#define AP_CONTROL_3A isaIO2mem(AP_IOBASE+0xe) /* Control Register 3a. Read/Write */
+#define AP_LUT_RED isaIO2mem(AP_IOBASE+9) /* Red Lookup Table register. Write */
+#define AP_LUT_GREEN isaIO2mem(AP_IOBASE+0xb) /* Green Lookup Table register. Write */
+#define AP_LUT_BLUE isaIO2mem(AP_IOBASE+0xd) /* Blue Lookup Table register. Write */
+#define AP_AD_CHANNEL isaIO2mem(AP_IOBASE+0xf) /* A/D Result/Channel register. Read/Write */
+
+
+#define FRAME_BUFFER_START 0x0A0000
+#define FRAME_BUFFER_LEN 0x20000
+
+/* CREG 0 */
+#define VECTOR_MODE 0x40 /* 010x.xxxx */
+#define DBLT_MODE 0x80 /* 100x.xxxx */
+#define NORMAL_MODE 0xE0 /* 111x.xxxx */
+#define SHIFT_BITS 0x1F /* xxx1.1111 */
+ /* other bits are Shift value */
+
+/* CREG 1 */
+#define AD_BLT 0x80 /* 1xxx.xxxx */
+
+#define ROP_EN 0x10 /* xxx1.xxxx */
+#define DST_EQ_SRC 0x00 /* xxx0.xxxx */
+#define nRESET_SYNC 0x08 /* xxxx.1xxx */
+#define SYNC_ENAB 0x02 /* xxxx.xx1x */
+
+#define BLANK_DISP 0x00 /* xxxx.xxx0 */
+#define ENAB_DISP 0x01 /* xxxx.xxx1 */
+
+#define NORM_CREG1 (nRESET_SYNC | SYNC_ENAB | ENAB_DISP) /* no reset sync */
+
+/* CREG 2B */
+
+/*
+ * Following 3 defines are common to 1, 4 and 8 plane.
+ */
+
+#define S_DATA_1s 0x00 /* 00xx.xxxx */ /* set source to all 1's -- vector drawing */
+#define S_DATA_PIX 0x40 /* 01xx.xxxx */ /* takes source from ls-bits and replicates over 16 bits */
+#define S_DATA_PLN 0xC0 /* 11xx.xxxx */ /* normal, each data access =16-bits in
+ one plane of image mem */
+
+/* CREG 3A/CREG 3B */
+# define RESET_CREG 0x80 /* 1000.0000 */
+
+/* ROP REG - all one nibble */
+/* ********* NOTE : this is used r0,r1,r2,r3 *********** */
+#define ROP(r2,r3,r0,r1) ( (U_SHORT)((r0)|((r1)<<4)|((r2)<<8)|((r3)<<12)) )
+#define DEST_ZERO 0x0
+#define SRC_AND_DEST 0x1
+#define SRC_AND_nDEST 0x2
+#define SRC 0x3
+#define nSRC_AND_DEST 0x4
+#define DEST 0x5
+#define SRC_XOR_DEST 0x6
+#define SRC_OR_DEST 0x7
+#define SRC_NOR_DEST 0x8
+#define SRC_XNOR_DEST 0x9
+#define nDEST 0xA
+#define SRC_OR_nDEST 0xB
+#define nSRC 0xC
+#define nSRC_OR_DEST 0xD
+#define SRC_NAND_DEST 0xE
+#define DEST_ONE 0xF
+
+#define SWAP(A) ((A>>8) | ((A&0xff) <<8))
+
+
+void dn_video_setup(char *options, int *ints);
+
+/* frame buffer operations */
+
+static int dn_fb_open(struct fb_info *info,int user);
+static int dn_fb_release(struct fb_info *info,int user);
+static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info);
+static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int dn_fb_set_var(struct fb_var_screeninfo *var, int isactive,
+ struct fb_info *info);
+static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
+ struct fb_info *info);
+static int dn_fb_set_cmap(struct fb_cmap *cmap,int kspc,int con,
+ struct fb_info *info);
+static int dn_fb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int dn_fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg, int con, struct fb_info *info);
+
+static int dnfbcon_switch(int con,struct fb_info *info);
+static int dnfbcon_updatevar(int con,struct fb_info *info);
+static void dnfbcon_blank(int blank,struct fb_info *info);
+
+static void dn_fb_set_disp(int con,struct fb_info *info);
+
+static struct display disp[MAX_NR_CONSOLES];
+static struct fb_info fb_info;
+static struct fb_ops dn_fb_ops = {
+ dn_fb_open,dn_fb_release, dn_fb_get_fix, dn_fb_get_var, dn_fb_set_var,
+ dn_fb_get_cmap, dn_fb_set_cmap, dn_fb_pan_display, dn_fb_ioctl
+};
+
+static int currcon=0;
+
+#define NUM_TOTAL_MODES 1
+struct fb_var_screeninfo dn_fb_predefined[] = {
+
+ { 0, },
+
+};
+
+static char dn_fb_name[]="Apollo ";
+
+/* accel stuff */
+#define USE_DN_ACCEL
+
+static struct display_switch dispsw_apollofb;
+
+static int dn_fb_open(struct fb_info *info,int user)
+{
+ /*
+ * Nothing, only a usage count for the moment
+ */
+
+ MOD_INC_USE_COUNT;
+ return(0);
+}
+
+static int dn_fb_release(struct fb_info *info,int user)
+{
+ MOD_DEC_USE_COUNT;
+ return(0);
+}
+
+static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info) {
+
+ strcpy(fix->id,"Apollo Color4");
+ fix->smem_start=(FRAME_BUFFER_START+IO_BASE);
+ fix->smem_len=FRAME_BUFFER_LEN;
+ fix->type=FB_TYPE_PACKED_PIXELS;
+ fix->type_aux=0;
+ fix->visual=FB_VISUAL_MONO10;
+ fix->xpanstep=0;
+ fix->ypanstep=0;
+ fix->ywrapstep=0;
+ fix->line_length=128;
+
+ return 0;
+
+}
+
+static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info) {
+
+ var->xres=1024;
+ var->yres=800;
+ var->xres_virtual=1024;
+ var->yres_virtual=1024;
+ var->xoffset=0;
+ var->yoffset=0;
+ var->bits_per_pixel=1;
+ var->grayscale=0;
+ var->nonstd=0;
+ var->activate=0;
+ var->height=-1;
+ var->width=-1;
+ var->pixclock=0;
+ var->left_margin=0;
+ var->right_margin=0;
+ var->hsync_len=0;
+ var->vsync_len=0;
+ var->sync=0;
+ var->vmode=FB_VMODE_NONINTERLACED;
+
+ return 0;
+
+}
+
+static int dn_fb_set_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info) {
+
+ printk("fb_set_var\n");
+ if(var->xres!=1024)
+ return -EINVAL;
+ if(var->yres!=800)
+ return -EINVAL;
+ if(var->xres_virtual!=1024)
+ return -EINVAL;
+ if(var->yres_virtual!=1024)
+ return -EINVAL;
+ if(var->xoffset!=0)
+ return -EINVAL;
+ if(var->yoffset!=0)
+ return -EINVAL;
+ if(var->bits_per_pixel!=1)
+ return -EINVAL;
+ if(var->grayscale!=0)
+ return -EINVAL;
+ if(var->nonstd!=0)
+ return -EINVAL;
+ if(var->activate!=0)
+ return -EINVAL;
+ if(var->pixclock!=0)
+ return -EINVAL;
+ if(var->left_margin!=0)
+ return -EINVAL;
+ if(var->right_margin!=0)
+ return -EINVAL;
+ if(var->hsync_len!=0)
+ return -EINVAL;
+ if(var->vsync_len!=0)
+ return -EINVAL;
+ if(var->sync!=0)
+ return -EINVAL;
+ if(var->vmode!=FB_VMODE_NONINTERLACED)
+ return -EINVAL;
+
+ return 0;
+
+}
+
+static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
+ struct fb_info *info) {
+
+ printk("get cmap not supported\n");
+
+ return -EINVAL;
+}
+
+static int dn_fb_set_cmap(struct fb_cmap *cmap,int kspc,int con,
+ struct fb_info *info) {
+
+ printk("set cmap not supported\n");
+
+ return -EINVAL;
+
+}
+
+static int dn_fb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info) {
+
+ printk("panning not supported\n");
+
+ return -EINVAL;
+
+}
+
+static int dn_fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg, int con, struct fb_info *info) {
+
+ printk("no IOCTLs as of yet.\n");
+
+ return -EINVAL;
+
+}
+
+static void dn_fb_set_disp(int con, struct fb_info *info) {
+
+ struct fb_fix_screeninfo fix;
+ struct display *display;
+
+
+ dn_fb_get_fix(&fix,con, info);
+
+ if (con>=0)
+ display=&fb_display[con];
+ else
+ display=&disp[0];
+
+ if(con==-1)
+ con=0;
+
+ display->screen_base = (u_char *)fix.smem_start;
+printk("screenbase: %lx\n",fix.smem_start);
+ display->visual = fix.visual;
+ display->type = fix.type;
+ display->type_aux = fix.type_aux;
+ display->ypanstep = fix.ypanstep;
+ display->ywrapstep = fix.ywrapstep;
+ display->can_soft_blank = 1;
+ display->inverse = 0;
+ display->line_length = fix.line_length;
+ display->scrollmode = SCROLL_YREDRAW;
+#ifdef FBCON_HAS_MFB
+ display->dispsw = &fbcon_mfb;
+#else
+ display->dispsw=&fbcon_dummy;
+#endif
+
+}
+
+unsigned long dnfb_init(unsigned long mem_start) {
+
+ int err;
+
+printk("dn_fb_init\n");
+
+ fb_info.changevar=NULL;
+ strcpy(&fb_info.modename[0],dn_fb_name);
+ fb_info.fontname[0]=0;
+ fb_info.disp=disp;
+ fb_info.switch_con=&dnfbcon_switch;
+ fb_info.updatevar=&dnfbcon_updatevar;
+ fb_info.blank=&dnfbcon_blank;
+ fb_info.node = -1;
+ fb_info.fbops = &dn_fb_ops;
+ fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+ dn_fb_get_var(&disp[0].var,0, &fb_info);
+ dn_fb_set_disp(-1, &fb_info);
+
+printk("dn_fb_init: register\n");
+ err=register_framebuffer(&fb_info);
+ if(err < 0) {
+ panic("unable to register apollo frame buffer\n");
+ }
+
+ /* now we have registered we can safely setup the hardware */
+
+ outb(RESET_CREG, AP_CONTROL_3A);
+ outb(NORMAL_MODE, AP_CONTROL_0);
+ outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1);
+ outb(S_DATA_PLN, AP_CONTROL_2);
+ outw(SWAP(0x3), AP_ROP_1);
+
+ printk("apollo frame buffer alive and kicking !\n");
+
+
+ return mem_start;
+
+}
+
+
+static int dnfbcon_switch(int con, struct fb_info *info) {
+
+ currcon=con;
+
+ return 0;
+
+}
+
+static int dnfbcon_updatevar(int con, struct fb_info *info) {
+
+ return 0;
+
+}
+
+static void dnfbcon_blank(int blank, struct fb_info *info) {
+
+ if(blank) {
+ outb(0x0, AP_CONTROL_3A);
+ }
+ else {
+ outb(0x1, AP_CONTROL_3A);
+ }
+
+ return ;
+
+}
+
+void dn_video_setup(char *options, int *ints) {
+
+ return;
+
+}
+
+void dn_bitblt(struct display *p,int x_src,int y_src, int x_dest, int y_dest,
+ int x_count, int y_count) {
+
+ int incr,y_delta,pre_read=0,x_end,x_word_count;
+ ushort *src,dummy;
+ uint start_mask,end_mask,dest;
+ short i,j;
+
+ incr=(y_dest<=y_src) ? 1 : -1 ;
+
+ src=(ushort *)(p->screen_base+ y_src*p->next_line+(x_src >> 4));
+ dest=y_dest*(p->next_line >> 1)+(x_dest >> 4);
+
+ if(incr>0) {
+ y_delta=(p->next_line*8)-x_src-x_count;
+ x_end=x_dest+x_count-1;
+ x_word_count=(x_end>>4) - (x_dest >> 4) + 1;
+ start_mask=0xffff0000 >> (x_dest & 0xf);
+ end_mask=0x7ffff >> (x_end & 0xf);
+ outb((((x_dest & 0xf) - (x_src &0xf)) % 16)|(0x4 << 5),AP_CONTROL_0);
+ if((x_dest & 0xf) < (x_src & 0xf))
+ pre_read=1;
+ }
+ else {
+ y_delta=-((p->next_line*8)-x_src-x_count);
+ x_end=x_dest-x_count+1;
+ x_word_count=(x_dest>>4) - (x_end >> 4) + 1;
+ start_mask=0x7ffff >> (x_dest & 0xf);
+ end_mask=0xffff0000 >> (x_end & 0xf);
+ outb(((-((x_src & 0xf) - (x_dest &0xf))) % 16)|(0x4 << 5),AP_CONTROL_0);
+ if((x_dest & 0xf) > (x_src & 0xf))
+ pre_read=1;
+ }
+
+ for(i=0;i<y_count;i++) {
+
+ if(pre_read) {
+ dummy=*src;
+ src+=incr;
+ }
+
+ if(x_word_count) {
+ outb(start_mask,AP_WRITE_ENABLE);
+ *src=dest;
+ src+=incr;
+ dest+=incr;
+ outb(0,AP_WRITE_ENABLE);
+
+ for(j=1;j<(x_word_count-1);j++) {
+ *src=dest;
+ src+=incr;
+ dest+=incr;
+ }
+
+ outb(start_mask,AP_WRITE_ENABLE);
+ *src=dest;
+ dest+=incr;
+ src+=incr;
+ }
+ else {
+ outb(start_mask | end_mask, AP_WRITE_ENABLE);
+ *src=dest;
+ dest+=incr;
+ src+=incr;
+ }
+ src+=(y_delta/16);
+ dest+=(y_delta/16);
+ }
+ outb(NORMAL_MODE,AP_CONTROL_0);
+}
+
+static void bmove_apollofb(struct display *p, int sy, int sx, int dy, int dx,
+ int height, int width)
+{
+
+ int fontheight,fontwidth;
+
+ fontheight=fontheight(p);
+ fontwidth=fontwidth(p);
+
+#ifdef USE_DN_ACCEL
+ dn_bitblt(p,sx,sy*fontheight,dx,dy*fontheight,width*fontwidth,
+ height*fontheight);
+#else
+ u_char *src, *dest;
+ u_int rows;
+
+ if (sx == 0 && dx == 0 && width == p->next_line) {
+ src = p->screen_base+sy*fontheight*width;
+ dest = p->screen_base+dy*fontheight*width;
+ mymemmove(dest, src, height*fontheight*width);
+ } else if (dy <= sy) {
+ src = p->screen_base+sy*fontheight*p->next_line+sx;
+ dest = p->screen_base+dy*fontheight*p->next_line+dx;
+ for (rows = height*fontheight; rows--;) {
+ mymemmove(dest, src, width);
+ src += p->next_line;
+ dest += p->next_line;
+ }
+ } else {
+ src = p->screen_base+((sy+height)*fontheight-1)*p->next_line+sx;
+ dest = p->screen_base+((dy+height)*fontheight-1)*p->next_line+dx;
+ for (rows = height*fontheight; rows--;) {
+ mymemmove(dest, src, width);
+ src -= p->next_line;
+ dest -= p->next_line;
+ }
+ }
+#endif
+}
+
+static void clear_apollofb(struct vc_data *conp, struct display *p, int sy, int sx,
+ int height, int width)
+{
+ fbcon_mfb_clear(conp,p,sy,sx,height,width);
+}
+
+static void putc_apollofb(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx)
+{
+ fbcon_mfb_putc(conp,p,c,yy,xx);
+}
+
+static void putcs_apollofb(struct vc_data *conp, struct display *p, const unsigned short *s,
+ int count, int yy, int xx)
+{
+ fbcon_mfb_putcs(conp,p,s,count,yy,xx);
+}
+
+static void rev_char_apollofb(struct display *p, int xx, int yy)
+{
+ fbcon_mfb_revc(p,xx,yy);
+}
+
+static struct display_switch dispsw_apollofb = {
+ fbcon_mfb_setup, bmove_apollofb, clear_apollofb,
+ putc_apollofb, putcs_apollofb, rev_char_apollofb
+};
diff --git a/drivers/video/dn_cfb8.c b/drivers/video/dn_cfb8.c
new file mode 100644
index 000000000..fe650f6e3
--- /dev/null
+++ b/drivers/video/dn_cfb8.c
@@ -0,0 +1,594 @@
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
+#include <asm/apollohw.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include "dn_accel.h"
+#include "fbcon.h"
+#include "fbcon-mfb.h"
+
+/* apollo video HW definitions */
+
+/*
+ * Control Registers. IOBASE + $x
+ *
+ * Note: these are the Memory/IO BASE definitions for a mono card set to the
+ * alternate address
+ *
+ * Control 3A and 3B serve identical functions except that 3A
+ * deals with control 1 and 3b deals with Color LUT reg.
+ */
+
+#define AP_IOBASE 0x3d0 /* Base address of 1 plane board. */
+#define AP_STATUS isaIO2mem(AP_IOBASE+0) /* Status register. Read */
+#define AP_WRITE_ENABLE isaIO2mem(AP_IOBASE+0) /* Write Enable Register Write */
+#define AP_DEVICE_ID isaIO2mem(AP_IOBASE+1) /* Device ID Register. Read */
+#define AP_ROP_0 isaIO2mem(AP_IOBASE+2) /* Raster Operation reg. Write Word */
+#define AP_ROP_1 isaIO2mem(AP_IOBASE+4) /* Raster Operation reg. Write Word */
+#define AP_DIAG_MEM_REQ isaIO2mem(AP_IOBASE+6) /* Diagnostic Memory Request. Write Word */
+#define AP_CONTROL_0 isaIO2mem(AP_IOBASE+8) /* Control Register 0. Read/Write */
+#define AP_LUT_DATA isaIO2mem(AP_IOBASE+9) /* Control Register 0. Read/Write */
+#define AP_CONTROL_1 isaIO2mem(AP_IOBASE+0xa) /* Control Register 1. Read/Write */
+#define AP_LUT_CONTROL isaIO2mem(AP_IOBASE+0xb) /* Control Register 1. Read/Write */
+#define AP_CONTROL_2A isaIO2mem(AP_IOBASE+0xc) /* Control Register 2. Read/Write */
+#define AP_CONTROL_2B isaIO2mem(AP_IOBASE+0xd) /* Control Register 2. Read/Write */
+#define AP_CONTROL_3A isaIO2mem(AP_IOBASE+0xe) /* Control Register 3a. Read/Write */
+#define AP_CONTROL_3B isaIO2mem(AP_IOBASE+0xf) /* Control Register 3a. Read/Write */
+
+
+#define FRAME_BUFFER_START 0x0A0000
+#define FRAME_BUFFER_LEN 0x20000
+
+/* CREG 0 */
+#define VECTOR_MODE 0x40 /* 010x.xxxx */
+#define DBLT_MODE 0x80 /* 100x.xxxx */
+#define NORMAL_MODE 0xE0 /* 111x.xxxx */
+#define SHIFT_BITS 0x1F /* xxx1.1111 */
+ /* other bits are Shift value */
+
+/* CREG 1 */
+#define AD_BLT 0x80 /* 1xxx.xxxx */
+
+#define ROP_EN 0x10 /* xxx1.xxxx */
+#define DST_EQ_SRC 0x00 /* xxx0.xxxx */
+#define nRESET_SYNC 0x08 /* xxxx.1xxx */
+#define SYNC_ENAB 0x02 /* xxxx.xx1x */
+
+#define BLANK_DISP 0x00 /* xxxx.xxx0 */
+#define ENAB_DISP 0x01 /* xxxx.xxx1 */
+
+#define NORM_CREG1 (nRESET_SYNC | SYNC_ENAB | ENAB_DISP) /* no reset sync */
+
+/* CREG 2B */
+
+/*
+ * Following 3 defines are common to 1, 4 and 8 plane.
+ */
+
+#define S_DATA_1s 0x00 /* 00xx.xxxx */ /* set source to all 1's -- vector drawing */
+#define S_DATA_PIX 0x40 /* 01xx.xxxx */ /* takes source from ls-bits and replicates over 16 bits */
+#define S_DATA_PLN 0xC0 /* 11xx.xxxx */ /* normal, each data access =16-bits in
+ one plane of image mem */
+
+/* CREG 3A/CREG 3B */
+# define RESET_CREG 0x80 /* 1000.0000 */
+
+/* ROP REG - all one nibble */
+/* ********* NOTE : this is used r0,r1,r2,r3 *********** */
+#define ROP(r2,r3,r0,r1) ( (U_SHORT)((r0)|((r1)<<4)|((r2)<<8)|((r3)<<12)) )
+#define DEST_ZERO 0x0
+#define SRC_AND_DEST 0x1
+#define SRC_AND_nDEST 0x2
+#define SRC 0x3
+#define nSRC_AND_DEST 0x4
+#define DEST 0x5
+#define SRC_XOR_DEST 0x6
+#define SRC_OR_DEST 0x7
+#define SRC_NOR_DEST 0x8
+#define SRC_XNOR_DEST 0x9
+#define nDEST 0xA
+#define SRC_OR_nDEST 0xB
+#define nSRC 0xC
+#define nSRC_OR_DEST 0xD
+#define SRC_NAND_DEST 0xE
+#define DEST_ONE 0xF
+
+#define SWAP(A) ((A>>8) | ((A&0xff) <<8))
+
+
+void dn_video_setup(char *options, int *ints);
+
+/* frame buffer operations */
+
+static int dn_fb_open(struct fb_info *info);
+static int dn_fb_release(struct fb_info *info);
+static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info);
+static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int dn_fb_set_var(struct fb_var_screeninfo *var, int isactive,
+ struct fb_info *info);
+static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
+ struct fb_info *info);
+static int dn_fb_set_cmap(struct fb_cmap *cmap,int kspc,int con,
+ struct fb_info *info);
+static int dn_fb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int dn_fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg, int con, struct fb_info *info);
+
+static int dnfbcon_switch(int con,struct fb_info *info);
+static int dnfbcon_updatevar(int con,struct fb_info *info);
+static void dnfbcon_blank(int blank,struct fb_info *info);
+
+static void dn_fb_set_disp(int con,struct fb_info *info);
+
+static struct display disp[MAX_NR_CONSOLES];
+static struct fb_info fb_info;
+static struct fb_ops dn_fb_ops = {
+ dn_fb_open,dn_fb_release, dn_fb_get_fix, dn_fb_get_var, dn_fb_set_var,
+ dn_fb_get_cmap, dn_fb_set_cmap, dn_fb_pan_display, dn_fb_ioctl
+};
+
+static int currcon=0;
+
+#define NUM_TOTAL_MODES 1
+struct fb_var_screeninfo dn_fb_predefined[] = {
+
+ { 0, },
+
+};
+
+static char dn_fb_name[]="Apollo ";
+
+/* accel stuff */
+#define USE_DN_ACCEL
+
+static struct display_switch dispsw_apollofb;
+
+static int dn_fb_open(struct fb_info *info)
+{
+ /*
+ * Nothing, only a usage count for the moment
+ */
+
+ MOD_INC_USE_COUNT;
+ return(0);
+}
+
+static int dn_fb_release(struct fb_info *info)
+{
+ MOD_DEC_USE_COUNT;
+ return(0);
+}
+
+static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info) {
+
+ strcpy(fix->id,"Apollo Color8");
+ fix->smem_start=(char*)(FRAME_BUFFER_START+IO_BASE);
+ fix->smem_len=FRAME_BUFFER_LEN;
+ fix->type=FB_TYPE_PACKED_PIXELS;
+ fix->type_aux=0;
+ fix->visual=FB_VISUAL_MONO10;
+ fix->xpanstep=0;
+ fix->ypanstep=0;
+ fix->ywrapstep=0;
+ fix->line_length=128;
+
+ return 0;
+
+}
+
+static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info) {
+
+ var->xres=1024;
+ var->yres=800;
+ var->xres_virtual=1024;
+ var->yres_virtual=1024;
+ var->xoffset=0;
+ var->yoffset=0;
+ var->bits_per_pixel=1;
+ var->grayscale=0;
+ var->nonstd=0;
+ var->activate=0;
+ var->height=-1;
+ var->width=-1;
+ var->pixclock=0;
+ var->left_margin=0;
+ var->right_margin=0;
+ var->hsync_len=0;
+ var->vsync_len=0;
+ var->sync=0;
+ var->vmode=FB_VMODE_NONINTERLACED;
+
+ return 0;
+
+}
+
+static int dn_fb_set_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info) {
+
+ printk("fb_set_var\n");
+ if(var->xres!=1024)
+ return -EINVAL;
+ if(var->yres!=800)
+ return -EINVAL;
+ if(var->xres_virtual!=1024)
+ return -EINVAL;
+ if(var->yres_virtual!=1024)
+ return -EINVAL;
+ if(var->xoffset!=0)
+ return -EINVAL;
+ if(var->yoffset!=0)
+ return -EINVAL;
+ if(var->bits_per_pixel!=1)
+ return -EINVAL;
+ if(var->grayscale!=0)
+ return -EINVAL;
+ if(var->nonstd!=0)
+ return -EINVAL;
+ if(var->activate!=0)
+ return -EINVAL;
+ if(var->pixclock!=0)
+ return -EINVAL;
+ if(var->left_margin!=0)
+ return -EINVAL;
+ if(var->right_margin!=0)
+ return -EINVAL;
+ if(var->hsync_len!=0)
+ return -EINVAL;
+ if(var->vsync_len!=0)
+ return -EINVAL;
+ if(var->sync!=0)
+ return -EINVAL;
+ if(var->vmode!=FB_VMODE_NONINTERLACED)
+ return -EINVAL;
+
+ return 0;
+
+}
+
+static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
+ struct fb_info *info) {
+
+ printk("get cmap not supported\n");
+
+ return -EINVAL;
+}
+
+static int dn_fb_set_cmap(struct fb_cmap *cmap,int kspc,int con,
+ struct fb_info *info) {
+
+ printk("set cmap not supported\n");
+
+ return -EINVAL;
+
+}
+
+static int dn_fb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info) {
+
+ printk("panning not supported\n");
+
+ return -EINVAL;
+
+}
+
+static int dn_fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg, int con, struct fb_info *info) {
+
+ printk("no IOCTLs as of yet.\n");
+
+ return -EINVAL;
+
+}
+
+static void dn_fb_set_disp(int con, struct fb_info *info) {
+
+ struct fb_fix_screeninfo fix;
+
+ dn_fb_get_fix(&fix,con, info);
+ if(con==-1)
+ con=0;
+
+ disp[con].screen_base = (u_char *)fix.smem_start;
+printk("screenbase: %p\n",fix.smem_start);
+ disp[con].visual = fix.visual;
+ disp[con].type = fix.type;
+ disp[con].type_aux = fix.type_aux;
+ disp[con].ypanstep = fix.ypanstep;
+ disp[con].ywrapstep = fix.ywrapstep;
+ disp[con].can_soft_blank = 1;
+ disp[con].inverse = 0;
+ disp[con].line_length = fix.line_length;
+ disp[con].dispsw = &dispsw_apollofb;
+}
+
+unsigned long dn_fb_init(unsigned long mem_start) {
+
+ int err;
+
+printk("dn_fb_init\n");
+
+ fb_info.changevar=NULL;
+ strcpy(&fb_info.modename[0],dn_fb_name);
+ fb_info.fontname[0]=0;
+ fb_info.disp=disp;
+ fb_info.switch_con=&dnfbcon_switch;
+ fb_info.updatevar=&dnfbcon_updatevar;
+ fb_info.blank=&dnfbcon_blank;
+ fb_info.node = -1;
+ fb_info.fbops = &dn_fb_ops;
+
+printk("dn_fb_init: register\n");
+ err=register_framebuffer(&fb_info);
+ if(err < 0) {
+ panic("unable to register apollo frame buffer\n");
+ }
+
+ /* now we have registered we can safely setup the hardware */
+
+ outb(RESET_CREG, AP_CONTROL_3A);
+ outb(RESET_CREG, AP_CONTROL_3B);
+ outw(0x0, AP_WRITE_ENABLE);
+ outb(NORMAL_MODE, AP_CONTROL_0);
+ outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1);
+ outb(0, AP_CONTROL_2A);
+ outb(S_DATA_PLN, AP_CONTROL_2B);
+ outw(SWAP(0x3), AP_ROP_1);
+
+ printk("apollo frame buffer alive and kicking !\n");
+
+ dn_fb_get_var(&disp[0].var,0, &fb_info);
+
+ dn_fb_set_disp(-1, &fb_info);
+
+ return mem_start;
+
+}
+
+
+static int dnfbcon_switch(int con, struct fb_info *info) {
+
+ currcon=con;
+
+ return 0;
+
+}
+
+static int dnfbcon_updatevar(int con, struct fb_info *info) {
+
+ return 0;
+
+}
+
+static void dnfbcon_blank(int blank, struct fb_info *info) {
+
+ if(blank) {
+ outb(0x0, AP_CONTROL_3A);
+ }
+ else {
+ outb(0x1, AP_CONTROL_3A);
+ }
+
+ return ;
+
+}
+
+void dn_video_setup(char *options, int *ints) {
+
+ return;
+
+}
+
+void dn_bitblt(struct display *p,int x_src,int y_src, int x_dest, int y_dest,
+ int x_count, int y_count) {
+
+ int incr,y_delta,pre_read=0,x_end,x_word_count;
+ ushort *src,dummy;
+ uint start_mask,end_mask,dest;
+ short i,j;
+
+ incr=(y_dest<=y_src) ? 1 : -1 ;
+
+ src=(ushort *)(p->screen_base+ y_src*p->next_line+(x_src >> 4));
+ dest=y_dest*(p->next_line >> 1)+(x_dest >> 4);
+
+ if(incr>0) {
+ y_delta=(p->next_line*8)-x_src-x_count;
+ x_end=x_dest+x_count-1;
+ x_word_count=(x_end>>4) - (x_dest >> 4) + 1;
+ start_mask=0xffff0000 >> (x_dest & 0xf);
+ end_mask=0x7ffff >> (x_end & 0xf);
+ outb((((x_dest & 0xf) - (x_src &0xf)) % 16)|(0x4 << 5),AP_CONTROL_0);
+ if((x_dest & 0xf) < (x_src & 0xf))
+ pre_read=1;
+ }
+ else {
+ y_delta=-((p->next_line*8)-x_src-x_count);
+ x_end=x_dest-x_count+1;
+ x_word_count=(x_dest>>4) - (x_end >> 4) + 1;
+ start_mask=0x7ffff >> (x_dest & 0xf);
+ end_mask=0xffff0000 >> (x_end & 0xf);
+ outb(((-((x_src & 0xf) - (x_dest &0xf))) % 16)|(0x4 << 5),AP_CONTROL_0);
+ if((x_dest & 0xf) > (x_src & 0xf))
+ pre_read=1;
+ }
+
+ for(i=0;i<y_count;i++) {
+
+ if(pre_read) {
+ dummy=*src;
+ src+=incr;
+ }
+
+ if(x_word_count) {
+ outb(start_mask,AP_WRITE_ENABLE);
+ *src=dest;
+ src+=incr;
+ dest+=incr;
+ outb(0,AP_WRITE_ENABLE);
+
+ for(j=1;j<(x_word_count-1);j++) {
+ *src=dest;
+ src+=incr;
+ dest+=incr;
+ }
+
+ outb(start_mask,AP_WRITE_ENABLE);
+ *src=dest;
+ dest+=incr;
+ src+=incr;
+ }
+ else {
+ outb(start_mask | end_mask, AP_WRITE_ENABLE);
+ *src=dest;
+ dest+=incr;
+ src+=incr;
+ }
+ src+=(y_delta/16);
+ dest+=(y_delta/16);
+ }
+ outb(NORMAL_MODE,AP_CONTROL_0);
+}
+
+static void bmove_apollofb(struct display *p, int sy, int sx, int dy, int dx,
+ int height, int width)
+{
+
+#ifdef USE_DN_ACCEL
+ dn_bitblt(p,sx,sy*p->fontheight,dx,dy*p->fontheight,width*p->fontwidth,
+ height*p->fontheight);
+#else
+ u_char *src, *dest;
+ u_int rows;
+
+ if (sx == 0 && dx == 0 && width == p->next_line) {
+ src = p->screen_base+sy*p->fontheight*width;
+ dest = p->screen_base+dy*p->fontheight*width;
+ mymemmove(dest, src, height*p->fontheight*width);
+ } else if (dy <= sy) {
+ src = p->screen_base+sy*p->fontheight*p->next_line+sx;
+ dest = p->screen_base+dy*p->fontheight*p->next_line+dx;
+ for (rows = height*p->fontheight; rows--;) {
+ mymemmove(dest, src, width);
+ src += p->next_line;
+ dest += p->next_line;
+ }
+ } else {
+ src = p->screen_base+((sy+height)*p->fontheight-1)*p->next_line+sx;
+ dest = p->screen_base+((dy+height)*p->fontheight-1)*p->next_line+dx;
+ for (rows = height*p->fontheight; rows--;) {
+ mymemmove(dest, src, width);
+ src -= p->next_line;
+ dest -= p->next_line;
+ }
+ }
+#endif
+}
+
+static void clear_apollofb(struct vc_data *conp, struct display *p, int sy, int sx,
+ int height, int width)
+{
+ u_char *dest;
+ u_int rows;
+
+ dest = p->screen_base+sy*p->fontheight*p->next_line+sx;
+
+ if (sx == 0 && width == p->next_line)
+ if (attr_reverse(p,conp))
+ mymemset(dest, height*p->fontheight*width);
+ else
+ mymemclear(dest, height*p->fontheight*width);
+ else
+ for (rows = height*p->fontheight; rows--; dest += p->next_line)
+ if (attr_reverse(p,conp))
+ mymemset(dest, width);
+ else
+ mymemclear_small(dest, width);
+}
+
+static void putc_apollofb(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx)
+{
+ u_char *dest, *cdat;
+ u_int rows, bold, revs, underl;
+ u_char d;
+
+ c &= 0xff;
+
+ dest = p->screen_base+yy*p->fontheight*p->next_line+xx;
+ cdat = p->fontdata+c*p->fontheight;
+ bold = attr_bold(p,conp);
+ revs = attr_reverse(p,conp);
+ underl = attr_underline(p,conp);
+
+ for (rows = p->fontheight; rows--; dest += p->next_line) {
+ d = *cdat++;
+ if (underl && !rows)
+ d = 0xff;
+ else if (bold)
+ d |= d>>1;
+ if (revs)
+ d = ~d;
+ *dest = d;
+ }
+}
+
+static void putcs_apollofb(struct vc_data *conp, struct display *p, const char *s,
+ int count, int yy, int xx)
+{
+ u_char *dest, *dest0, *cdat;
+ u_int rows, bold, revs, underl;
+ u_char c, d;
+
+ dest0 = p->screen_base+yy*p->fontheight*p->next_line+xx;
+ bold = attr_bold(p,conp);
+ revs = attr_reverse(p,conp);
+ underl = attr_underline(p,conp);
+
+ while (count--) {
+ c = *s++;
+ dest = dest0++;
+ cdat = p->fontdata+c*p->fontheight;
+ for (rows = p->fontheight; rows--; dest += p->next_line) {
+ d = *cdat++;
+ if (underl && !rows)
+ d = 0xff;
+ else if (bold)
+ d |= d>>1;
+ if (revs)
+ d = ~d;
+ *dest = d;
+ }
+ }
+}
+
+static void rev_char_apollofb(struct display *p, int xx, int yy)
+{
+ u_char *dest;
+ u_int rows;
+
+ dest = p->screen_base+yy*p->fontheight*p->next_line+xx;
+ for (rows = p->fontheight; rows--; dest += p->next_line)
+ *dest = ~*dest;
+}
+
+static struct display_switch dispsw_apollofb = {
+ fbcon_mfb_setup, bmove_apollofb, clear_apollofb,
+ putc_apollofb, putcs_apollofb, rev_char_apollofb
+};
diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c
index 3730695dd..30860ae2b 100644
--- a/drivers/video/dnfb.c
+++ b/drivers/video/dnfb.c
@@ -10,14 +10,15 @@
#include <asm/segment.h>
#include <asm/system.h>
#include <asm/irq.h>
+#include <asm/amigahw.h>
+#include <asm/amigaints.h>
#include <asm/apollohw.h>
#include <linux/fb.h>
#include <linux/module.h>
-
+#include "dn_accel.h"
#include <video/fbcon.h>
#include <video/fbcon-mfb.h>
-
/* apollo video HW definitions */
/*
@@ -30,16 +31,16 @@
* deals with control 1 and 3b deals with Color LUT reg.
*/
-#define AP_IOBASE 0x5d80 /* Base address of 1 plane board. */
-#define AP_STATUS 0x5d80 /* Status register. Read */
-#define AP_WRITE_ENABLE 0x5d80 /* Write Enable Register Write */
-#define AP_DEVICE_ID 0x5d81 /* Device ID Register. Read */
-#define AP_ROP_1 0x5d82 /* Raster Operation reg. Write Word */
-#define AP_DIAG_MEM_REQ 0x5d84 /* Diagnostic Memory Request. Write Word */
-#define AP_CONTROL_0 0x5d88 /* Control Register 0. Read/Write */
-#define AP_CONTROL_1 0x5d8a /* Control Register 1. Read/Write */
-#define AP_CONTROL_3A 0x5d8e /* Control Register 3a. Read/Write */
-#define AP_CONTROL_2 0x5d8c /* Control Register 2. Read/Write */
+#define AP_IOBASE 0x3b0 /* Base address of 1 plane board. */
+#define AP_STATUS isaIO2mem(AP_IOBASE+0) /* Status register. Read */
+#define AP_WRITE_ENABLE isaIO2mem(AP_IOBASE+0) /* Write Enable Register Write */
+#define AP_DEVICE_ID isaIO2mem(AP_IOBASE+1) /* Device ID Register. Read */
+#define AP_ROP_1 isaIO2mem(AP_IOBASE+2) /* Raster Operation reg. Write Word */
+#define AP_DIAG_MEM_REQ isaIO2mem(AP_IOBASE+4) /* Diagnostic Memory Request. Write Word */
+#define AP_CONTROL_0 isaIO2mem(AP_IOBASE+8) /* Control Register 0. Read/Write */
+#define AP_CONTROL_1 isaIO2mem(AP_IOBASE+0xa) /* Control Register 1. Read/Write */
+#define AP_CONTROL_3A isaIO2mem(AP_IOBASE+0xe) /* Control Register 3a. Read/Write */
+#define AP_CONTROL_2 isaIO2mem(AP_IOBASE+0xc) /* Control Register 2. Read/Write */
#define FRAME_BUFFER_START 0x0FA0000
@@ -112,44 +113,57 @@
#endif
+void dn_video_setup(char *options, int *ints);
+
/* frame buffer operations */
-static int dnfb_open(struct fb_info *info, int user);
-static int dnfb_release(struct fb_info *info, int user);
-static int dnfb_get_fix(struct fb_fix_screeninfo *fix, int con,
- struct fb_info *info);
-static int dnfb_get_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info);
-static int dnfb_set_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info);
-static int dnfb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
+static int dn_fb_open(struct fb_info *info,int user);
+static int dn_fb_release(struct fb_info *info,int user);
+static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
struct fb_info *info);
-static int dnfb_set_cmap(struct fb_cmap *cmap,int kspc,int con,
+static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
struct fb_info *info);
-static int dnfb_pan_display(struct fb_var_screeninfo *var, int con,
- struct fb_info *info);
-static int dnfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg, int con,
- struct fb_info *info);
+static int dn_fb_set_var(struct fb_var_screeninfo *var, int isactive,
+ struct fb_info *info);
+static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
+ struct fb_info *info);
+static int dn_fb_set_cmap(struct fb_cmap *cmap,int kspc,int con,
+ struct fb_info *info);
+static int dn_fb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int dn_fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg, int con, struct fb_info *info);
-static int dnfbcon_switch(int con, struct fb_info *info);
-static int dnfbcon_updatevar(int con, struct fb_info *info);
-static void dnfbcon_blank(int blank, struct fb_info *info);
+static int dnfbcon_switch(int con,struct fb_info *info);
+static int dnfbcon_updatevar(int con,struct fb_info *info);
+static void dnfbcon_blank(int blank,struct fb_info *info);
-static void dnfb_set_disp(int con, struct fb_info *info);
+static void dn_fb_set_disp(int con,struct fb_info *info);
static struct display disp[MAX_NR_CONSOLES];
static struct fb_info fb_info;
-static struct fb_ops dnfb_ops = {
- dnfb_open,dnfb_release, dnfb_get_fix, dnfb_get_var, dnfb_set_var,
- dnfb_get_cmap, dnfb_set_cmap, dnfb_pan_display, dnfb_ioctl
+static struct fb_ops dn_fb_ops = {
+ dn_fb_open,dn_fb_release, dn_fb_get_fix, dn_fb_get_var, dn_fb_set_var,
+ dn_fb_get_cmap, dn_fb_set_cmap, dn_fb_pan_display, dn_fb_ioctl
};
static int currcon=0;
-static char dnfb_name[]="Apollo";
+#define NUM_TOTAL_MODES 1
+struct fb_var_screeninfo dn_fb_predefined[] = {
+
+ { 0, },
+
+};
+
+static char dn_fb_name[]="Apollo ";
+
+/* accel stuff */
+#define USE_DN_ACCEL
-static int dnfb_open(struct fb_info *info, int user)
+static struct display_switch dispsw_apollofb;
+
+static int dn_fb_open(struct fb_info *info,int user)
{
/*
* Nothing, only a usage count for the moment
@@ -159,18 +173,17 @@ static int dnfb_open(struct fb_info *info, int user)
return(0);
}
-static int dnfb_release(struct fb_info *info, int user)
+static int dn_fb_release(struct fb_info *info,int user)
{
MOD_DEC_USE_COUNT;
return(0);
}
-static int dnfb_get_fix(struct fb_fix_screeninfo *fix, int con,
- struct fb_info *info)
-{
- memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+static int dn_fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info) {
+
strcpy(fix->id,"Apollo Mono");
- fix->smem_start=FRAME_BUFFER_START+IO_BASE;
+ fix->smem_start=(FRAME_BUFFER_START+IO_BASE);
fix->smem_len=FRAME_BUFFER_LEN;
fix->type=FB_TYPE_PACKED_PIXELS;
fix->type_aux=0;
@@ -184,10 +197,9 @@ static int dnfb_get_fix(struct fb_fix_screeninfo *fix, int con,
}
-static int dnfb_get_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
-{
- memset(var, 0, sizeof(struct fb_var_screeninfo));
+static int dn_fb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info) {
+
var->xres=1280;
var->yres=1024;
var->xres_virtual=2048;
@@ -212,9 +224,10 @@ static int dnfb_get_var(struct fb_var_screeninfo *var, int con,
}
-static int dnfb_set_var(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
-{
+static int dn_fb_set_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info) {
+
+ printk("fb_set_var\n");
if(var->xres!=1280)
return -EINVAL;
if(var->yres!=1024)
@@ -254,119 +267,284 @@ static int dnfb_set_var(struct fb_var_screeninfo *var, int con,
}
-static int dnfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info)
-{
+static int dn_fb_get_cmap(struct fb_cmap *cmap,int kspc,int con,
+ struct fb_info *info) {
+
printk("get cmap not supported\n");
return -EINVAL;
}
-static int dnfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
- struct fb_info *info)
-{
+static int dn_fb_set_cmap(struct fb_cmap *cmap,int kspc,int con,
+ struct fb_info *info) {
+
printk("set cmap not supported\n");
return -EINVAL;
}
-static int dnfb_pan_display(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
-{
+static int dn_fb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info) {
+
printk("panning not supported\n");
return -EINVAL;
}
-static int dnfb_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg, int con,
- struct fb_info *info)
-{
+static int dn_fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg, int con, struct fb_info *info) {
+
+ printk("no IOCTLs as of yet.\n");
+
return -EINVAL;
+
}
-static void dnfb_set_disp(int con, struct fb_info *info)
-{
+static void dn_fb_set_disp(int con, struct fb_info *info) {
+
struct fb_fix_screeninfo fix;
+ struct display *display;
+
+ dn_fb_get_fix(&fix,con, info);
+
+ if (con>=0)
+ display=&fb_display[con];
+ else
+ display=&disp[0];
- dnfb_get_fix(&fix, con, info);
if(con==-1)
con=0;
- disp[con].screen_base = fix.smem_start;
- disp[con].visual = fix.visual;
- disp[con].type = fix.type;
- disp[con].type_aux = fix.type_aux;
- disp[con].ypanstep = fix.ypanstep;
- disp[con].ywrapstep = fix.ywrapstep;
- disp[con].can_soft_blank = 1;
- disp[con].inverse = 0;
- disp[con].line_length = fix.line_length;
+ display->screen_base = (u_char *)fix.smem_start;
+ display->visual = fix.visual;
+ display->type = fix.type;
+ display->type_aux = fix.type_aux;
+ display->ypanstep = fix.ypanstep;
+ display->ywrapstep = fix.ywrapstep;
+ display->can_soft_blank = 1;
+ display->inverse = 0;
+ display->line_length = fix.line_length;
#ifdef FBCON_HAS_MFB
- disp[con].dispsw = &fbcon_mfb;
+ display->dispsw = &fbcon_mfb;
#else
- disp[con].dispsw = &fbcon_dummy;
+ display->dispsw=&fbcon_dummy;
#endif
+
}
-int dnfb_init(void)
-{
+unsigned long dnfb_init(unsigned long mem_start) {
+
+ int err;
+
+
fb_info.changevar=NULL;
- strcpy(&fb_info.modename[0],dnfb_name);
+ strcpy(&fb_info.modename[0],dn_fb_name);
fb_info.fontname[0]=0;
fb_info.disp=disp;
fb_info.switch_con=&dnfbcon_switch;
fb_info.updatevar=&dnfbcon_updatevar;
fb_info.blank=&dnfbcon_blank;
fb_info.node = -1;
- fb_info.fbops = &dnfb_ops;
- fb_info.flags = FBINFO_FLAG_DEFAULT;
+ fb_info.fbops = &dn_fb_ops;
- outb(RESET_CREG, AP_CONTROL_3A);
- outw(0x0, AP_WRITE_ENABLE);
- outb(NORMAL_MODE,AP_CONTROL_0);
- outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1);
- outb(S_DATA_PLN, AP_CONTROL_2);
- outw(SWAP(0x3),AP_ROP_1);
-
- dnfb_get_var(&disp[0].var, 0, &fb_info);
- dnfb_set_disp(-1, &fb_info);
-
- if (register_framebuffer(&fb_info) < 0) {
- printk(KERN_ERR "unable to register apollo frame buffer\n");
- return -EINVAL;
+ dn_fb_get_var(&disp[0].var,0, &fb_info);
+
+ dn_fb_set_disp(-1, &fb_info);
+
+ err=register_framebuffer(&fb_info);
+ if(err < 0) {
+ panic("unable to register apollo frame buffer\n");
}
- printk("fb%d: apollo frame buffer alive and kicking !\n",
- GET_FB_IDX(fb_info.node));
- return 0;
+ /* now we have registered we can safely setup the hardware */
+
+ outb(RESET_CREG, AP_CONTROL_3A);
+ outw(0x0, AP_WRITE_ENABLE);
+ outb(NORMAL_MODE, AP_CONTROL_0);
+ outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1);
+ outb(S_DATA_PLN, AP_CONTROL_2);
+ outw(SWAP(0x3), AP_ROP_1);
+
+ printk("apollo frame buffer alive and kicking !\n");
+
+
+ return mem_start;
+
}
-static int dnfbcon_switch(int con, struct fb_info *info)
-{
+static int dnfbcon_switch(int con, struct fb_info *info) {
+
currcon=con;
return 0;
}
-static int dnfbcon_updatevar(int con, struct fb_info *info)
-{
+static int dnfbcon_updatevar(int con, struct fb_info *info) {
+
return 0;
+
}
-static void dnfbcon_blank(int blank, struct fb_info *info)
-{
+static void dnfbcon_blank(int blank, struct fb_info *info) {
+
if(blank) {
- outb(0, AP_CONTROL_3A);
- outb((AD_BLT | DST_EQ_SRC | NORM_CREG1) & ~ENAB_DISP,
- AP_CONTROL_1);
+ outb(0x0, AP_CONTROL_3A);
+ }
+ else {
+ outb(0x1, AP_CONTROL_3A);
+ }
+
+ return ;
+
+}
+
+void dn_video_setup(char *options, int *ints) {
+
+ return;
+
+}
+
+void dn_bitblt(struct display *p,int x_src,int y_src, int x_dest, int y_dest,
+ int x_count, int y_count) {
+
+ int incr,y_delta,pre_read=0,x_end,x_word_count;
+ ushort *src,dummy;
+ uint start_mask,end_mask,dest;
+ short i,j;
+
+ incr=(y_dest<=y_src) ? 1 : -1 ;
+
+ src=(ushort *)(p->screen_base+ y_src*p->next_line+(x_src >> 4));
+ dest=y_dest*(p->next_line >> 1)+(x_dest >> 4);
+
+ if(incr>0) {
+ y_delta=(p->next_line*8)-x_src-x_count;
+ x_end=x_dest+x_count-1;
+ x_word_count=(x_end>>4) - (x_dest >> 4) + 1;
+ start_mask=0xffff0000 >> (x_dest & 0xf);
+ end_mask=0x7ffff >> (x_end & 0xf);
+ outb((((x_dest & 0xf) - (x_src &0xf)) % 16)|(0x4 << 5),AP_CONTROL_0);
+ if((x_dest & 0xf) < (x_src & 0xf))
+ pre_read=1;
}
else {
- outb(1, AP_CONTROL_3A);
- outb((AD_BLT | DST_EQ_SRC | NORM_CREG1), AP_CONTROL_1);
+ y_delta=-((p->next_line*8)-x_src-x_count);
+ x_end=x_dest-x_count+1;
+ x_word_count=(x_dest>>4) - (x_end >> 4) + 1;
+ start_mask=0x7ffff >> (x_dest & 0xf);
+ end_mask=0xffff0000 >> (x_end & 0xf);
+ outb(((-((x_src & 0xf) - (x_dest &0xf))) % 16)|(0x4 << 5),AP_CONTROL_0);
+ if((x_dest & 0xf) > (x_src & 0xf))
+ pre_read=1;
+ }
+
+ for(i=0;i<y_count;i++) {
+
+ outb(0xc | (dest >> 16), AP_CONTROL_3A);
+
+ if(pre_read) {
+ dummy=*src;
+ src+=incr;
+ }
+
+ if(x_word_count) {
+ outb(start_mask,AP_WRITE_ENABLE);
+ *src=dest;
+ src+=incr;
+ dest+=incr;
+ outb(0,AP_WRITE_ENABLE);
+
+ for(j=1;j<(x_word_count-1);j++) {
+ *src=dest;
+ src+=incr;
+ dest+=incr;
+ }
+
+ outb(start_mask,AP_WRITE_ENABLE);
+ *src=dest;
+ dest+=incr;
+ src+=incr;
+ }
+ else {
+ outb(start_mask | end_mask, AP_WRITE_ENABLE);
+ *src=dest;
+ dest+=incr;
+ src+=incr;
+ }
+ src+=(y_delta/16);
+ dest+=(y_delta/16);
+ }
+ outb(NORMAL_MODE,AP_CONTROL_0);
+}
+
+static void bmove_apollofb(struct display *p, int sy, int sx, int dy, int dx,
+ int height, int width)
+{
+
+ int fontheight,fontwidth;
+
+ fontheight=fontheight(p);
+ fontwidth=fontwidth(p);
+
+#ifdef USE_DN_ACCEL
+ dn_bitblt(p,sx,sy*fontheight,dx,dy*fontheight,width*fontwidth,
+ height*fontheight);
+#else
+ u_char *src, *dest;
+ u_int rows;
+
+ if (sx == 0 && dx == 0 && width == p->next_line) {
+ src = p->screen_base+sy*fontheight*width;
+ dest = p->screen_base+dy*fontheight*width;
+ mymemmove(dest, src, height*fontheight*width);
+ } else if (dy <= sy) {
+ src = p->screen_base+sy*fontheight*next_line+sx;
+ dest = p->screen_base+dy*fontheight*next_line+dx;
+ for (rows = height*fontheight; rows--;) {
+ mymemmove(dest, src, width);
+ src += p->next_line;
+ dest += p->next_line;
}
+ } else {
+ src = p->screen_base+((sy+height)*fontheight-1)*p->next_line+sx;
+ dest = p->screen_base+((dy+height)*fontheight-1)*p->next_line+dx;
+ for (rows = height*fontheight; rows--;) {
+ mymemmove(dest, src, width);
+ src -= p->next_line;
+ dest -= p->next_line;
+ }
+ }
+#endif
+}
+
+static void clear_apollofb(struct vc_data *conp, struct display *p, int sy, int sx,
+ int height, int width)
+{
+ fbcon_mfb_clear(conp,p,sy,sx,height,width);
}
+
+static void putc_apollofb(struct vc_data *conp, struct display *p, int c, int yy,
+ int xx)
+{
+ fbcon_mfb_putc(conp,p,c,yy,xx);
+}
+
+static void putcs_apollofb(struct vc_data *conp, struct display *p, const char *s,
+ int count, int yy, int xx)
+{
+ fbcon_mfb_putcs(conp,p,s,count,yy,xx);
+}
+
+static void rev_char_apollofb(struct display *p, int xx, int yy)
+{
+ fbcon_mfb_revc(p,xx,yy);
+}
+
+static struct display_switch dispsw_apollofb = {
+ fbcon_mfb_setup, bmove_apollofb, clear_apollofb,
+ putc_apollofb, putcs_apollofb, rev_char_apollofb
+};
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index 3d3485c9d..1b512ee1c 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -140,7 +140,7 @@ static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
*gid = current->gid;
*pgrp = current->pgrp;
- *minproto = *maxproto = AUTOFS_PROTO_VERSION;
+ *minproto = *maxproto = AUTOFS_MAX_PROTO_VERSION;
*pipefd = -1;
@@ -278,15 +278,15 @@ struct super_block *autofs4_read_super(struct super_block *s, void *data,
/* Couldn't this be tested earlier? */
if (maxproto < AUTOFS_MIN_PROTO_VERSION ||
- minproto > AUTOFS_PROTO_VERSION) {
+ minproto > AUTOFS_MAX_PROTO_VERSION) {
printk("autofs: kernel does not match daemon version "
"daemon (%d, %d) kernel (%d, %d)\n",
minproto, maxproto,
- AUTOFS_MIN_PROTO_VERSION, AUTOFS_PROTO_VERSION);
+ AUTOFS_MIN_PROTO_VERSION, AUTOFS_MAX_PROTO_VERSION);
goto fail_dput;
}
- sbi->version = maxproto > AUTOFS_PROTO_VERSION ? AUTOFS_PROTO_VERSION : maxproto;
+ sbi->version = maxproto > AUTOFS_MAX_PROTO_VERSION ? AUTOFS_MAX_PROTO_VERSION : maxproto;
DPRINTK(("autofs: pipe fd = %d, pgrp = %u\n", pipefd, sbi->oz_pgrp));
pipe = fget(pipefd);
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index 4d9a4a727..bfa5729ea 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -611,6 +611,7 @@ struct flags {
{ NFSEXP_SUNSECURE, { "sunsecure", ""}},
{ NFSEXP_CROSSMNT, {"nohide", ""}},
{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
+ { NFSEXP_NOAUTHNLM, {"no_auth_nlm", ""}},
{ 0, {"", ""}}
};
diff --git a/fs/nfsd/lockd.c b/fs/nfsd/lockd.c
index e23f48e5b..cdd6f2e4e 100644
--- a/fs/nfsd/lockd.c
+++ b/fs/nfsd/lockd.c
@@ -30,7 +30,7 @@ nlm_fopen(struct svc_rqst *rqstp, struct knfs_fh *f, struct file *filp)
fh.fh_handle = *f;
fh.fh_export = NULL;
- nfserr = nfsd_open(rqstp, &fh, S_IFREG, 0, filp);
+ nfserr = nfsd_open(rqstp, &fh, S_IFREG, MAY_LOCK, filp);
if (!nfserr)
dget(filp->f_dentry);
fh_put(&fh);
diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c
index 28ac3cc3c..ef69be746 100644
--- a/fs/nfsd/nfsproc.c
+++ b/fs/nfsd/nfsproc.c
@@ -391,10 +391,6 @@ nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp,
argp->tname, argp->tlen,
&newfh, &argp->attrs);
- if (!nfserr) {
- argp->attrs.ia_valid &= ~ATTR_SIZE;
- nfserr = nfsd_setattr(rqstp, &newfh, &argp->attrs);
- }
fh_put(&argp->ffh);
fh_put(&newfh);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 856e345f6..95bec2fc5 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -46,19 +46,12 @@
#define NFSDDBG_FACILITY NFSDDBG_FILEOP
#define NFSD_PARANOIA
-/* Open mode for nfsd_open */
-#define OPEN_READ 0
-#define OPEN_WRITE 1
-/* Hack until we have a macro check for mandatory locks. */
-#ifndef IS_ISMNDLK
-/* We must ignore files (but only file) which might have mandatory
+/* We must ignore files (but only files) which might have mandatory
* locks on them because there is no way to know if the accesser has
* the lock.
*/
-#define IS_ISMNDLK(i) (((i)->i_mode & (S_ISGID|S_IXGRP|S_IFMT)) \
- == (S_ISGID|S_IFREG))
-#endif
+#define IS_ISMNDLK(i) (S_ISREG((i)->i_mode) && MANDATORY_LOCK(i))
/* Check for dir entries '.' and '..' */
#define isdotent(n, l) (l < 3 && n[0] == '.' && (l == 1 || n[1] == '.'))
@@ -427,18 +420,17 @@ out:
/*
* Open an existing file or directory.
- * The wflag argument indicates write access.
+ * The access argument indicates the type of open (read/write/lock)
* N.B. After this call fhp needs an fh_put
*/
int
nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
- int wflag, struct file *filp)
+ int access, struct file *filp)
{
struct dentry *dentry;
struct inode *inode;
- int access, err;
+ int err;
- access = wflag? MAY_WRITE : MAY_READ;
err = fh_verify(rqstp, fhp, type, access);
if (err)
goto out;
@@ -455,24 +447,27 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
if (!inode->i_op || !inode->i_op->default_file_ops)
goto out;
- if (wflag && (err = get_write_access(inode)) != 0)
+ if ((access & MAY_WRITE) && (err = get_write_access(inode)) != 0)
goto out_nfserr;
memset(filp, 0, sizeof(*filp));
filp->f_op = inode->i_op->default_file_ops;
atomic_set(&filp->f_count, 1);
- filp->f_flags = wflag? O_WRONLY : O_RDONLY;
- filp->f_mode = wflag? FMODE_WRITE : FMODE_READ;
filp->f_dentry = dentry;
-
- if (wflag)
+ if (access & MAY_WRITE) {
+ filp->f_flags = O_WRONLY;
+ filp->f_mode = FMODE_WRITE;
DQUOT_INIT(inode);
+ } else {
+ filp->f_flags = O_RDONLY;
+ filp->f_mode = FMODE_READ;
+ }
err = 0;
if (filp->f_op && filp->f_op->open) {
err = filp->f_op->open(inode, filp);
if (err) {
- if (wflag)
+ if (access & MAY_WRITE)
put_write_access(inode);
/* I nearly added put_filp() call here, but this filp
@@ -581,7 +576,7 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
int err;
struct file file;
- err = nfsd_open(rqstp, fhp, S_IFREG, OPEN_READ, &file);
+ err = nfsd_open(rqstp, fhp, S_IFREG, MAY_READ, &file);
if (err)
goto out;
err = nfserr_perm;
@@ -648,7 +643,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
if (!cnt)
goto out;
- err = nfsd_open(rqstp, fhp, S_IFREG, OPEN_WRITE, &file);
+ err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file);
if (err)
goto out;
err = nfserr_perm;
@@ -774,7 +769,7 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp,
struct file file;
int err;
- if ((err = nfsd_open(rqstp, fhp, S_IFREG, OPEN_WRITE, &file)) != 0)
+ if ((err = nfsd_open(rqstp, fhp, S_IFREG, MAY_WRITE, &file)) != 0)
return err;
if (file.f_op && file.f_op->fsync) {
@@ -1204,6 +1199,8 @@ nfsd_symlink(struct svc_rqst *rqstp, struct svc_fh *fhp,
iap->ia_valid &= ATTR_MODE /* ~(ATTR_MODE|ATTR_UID|ATTR_GID)*/;
if (iap->ia_valid) {
iap->ia_valid |= ATTR_CTIME;
+ iap->ia_mode = (iap->ia_mode&S_IALLUGO)
+ | S_IFLNK;
err = notify_change(dnew, iap);
if (!err && EX_ISSYNC(fhp->fh_export))
write_inode_now(dentry->d_inode);
@@ -1532,7 +1529,7 @@ nfsd_readdir(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
if (offset > ~(u32) 0)
goto out;
- err = nfsd_open(rqstp, fhp, S_IFDIR, OPEN_READ, &file);
+ err = nfsd_open(rqstp, fhp, S_IFDIR, MAY_READ, &file);
if (err)
goto out;
@@ -1650,13 +1647,14 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
if (acc == MAY_NOP)
return 0;
#if 0
- dprintk("nfsd: permission 0x%x%s%s%s%s%s mode 0%o%s%s%s\n",
+ dprintk("nfsd: permission 0x%x%s%s%s%s%s%s mode 0%o%s%s%s\n",
acc,
(acc & MAY_READ)? " read" : "",
(acc & MAY_WRITE)? " write" : "",
(acc & MAY_EXEC)? " exec" : "",
(acc & MAY_SATTR)? " sattr" : "",
(acc & MAY_TRUNC)? " trunc" : "",
+ (acc & MAY_LOCK)? " lock" : "",
inode->i_mode,
IS_IMMUTABLE(inode)? " immut" : "",
IS_APPEND(inode)? " append" : "",
@@ -1674,6 +1672,15 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
if ((acc & MAY_TRUNC) && IS_APPEND(inode))
return nfserr_perm;
+ if (acc & MAY_LOCK) {
+ /* If we cannot rely on authentication in NLM requests,
+ * just allow locks, others require read permission
+ */
+ if (exp->ex_flags & NFSEXP_NOAUTHNLM)
+ return 0;
+ else
+ acc = MAY_READ;
+ }
/*
* The file owner always gets access permission. This is to make
* file access work even when the client has done a fchmod(fd, 0).
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 1dd50817c..4670b456c 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -498,9 +498,6 @@ enum pid_directory_inos {
PROC_PID_STAT,
PROC_PID_STATM,
PROC_PID_MAPS,
-#if CONFIG_AP1000
- PROC_PID_RINGBUF,
-#endif
PROC_PID_CPU,
PROC_PID_FD_DIR = 0x8000, /* 0x8000-0xffff */
};
@@ -516,9 +513,6 @@ static struct pid_entry base_stuff[] = {
#ifdef __SMP__
E(PROC_PID_CPU, "cpu", S_IFREG|S_IRUGO),
#endif
-#if CONFIG_AP1000
- E(PROC_PID_RINGBUF, "ringbuf", S_IFREG|S_IRUGO|S_IWUSR),
-#endif
E(PROC_PID_MAPS, "maps", S_IFREG|S_IRUGO),
E(PROC_PID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
E(PROC_PID_CWD, "cwd", S_IFLNK|S_IRWXUGO),
@@ -871,11 +865,6 @@ static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
inode->u.proc_i.op.proc_read = proc_pid_cpu;
break;
#endif
-#if CONFIG_AP1000
- case PROC_PID_RINGBUF:
- inode->i_op = &proc_ringbuf_inode_operations;
- break;
-#endif
case PROC_PID_MEM:
inode->i_op = &proc_mem_inode_operations;
break;
diff --git a/fs/qnx4/bitmap.c b/fs/qnx4/bitmap.c
index 141caa2d1..56e7790bb 100644
--- a/fs/qnx4/bitmap.c
+++ b/fs/qnx4/bitmap.c
@@ -76,16 +76,12 @@ unsigned long qnx4_count_free_blocks(struct super_block *sb)
count_bits(bh->b_data, size - total, &total_free);
brelse(bh);
total += QNX4_BLOCK_SIZE;
+ offset++;
}
return total_free;
}
-unsigned long qnx4_count_free_inodes(struct super_block *sb)
-{
- return qnx4_count_free_blocks(sb) * QNX4_INODES_PER_BLOCK; /* FIXME */
-}
-
#ifdef CONFIG_QNX4FS_RW
int qnx4_is_free(struct super_block *sb, long block)
diff --git a/fs/qnx4/dir.c b/fs/qnx4/dir.c
index 7dd304735..068c56535 100644
--- a/fs/qnx4/dir.c
+++ b/fs/qnx4/dir.c
@@ -35,13 +35,13 @@ static int qnx4_readdir(struct file *filp, void *dirent, filldir_t filldir)
QNX4DEBUG(("filp->f_pos = %ld\n", (long) filp->f_pos));
while (filp->f_pos < inode->i_size) {
- blknum = qnx4_block_map( inode, filp->f_pos / QNX4_BLOCK_SIZE );
+ blknum = qnx4_block_map( inode, filp->f_pos >> QNX4_BLOCK_SIZE_BITS );
bh = bread(inode->i_dev, blknum, QNX4_BLOCK_SIZE);
if(bh==NULL) {
printk(KERN_ERR "qnx4_readdir: bread failed (%ld)\n", blknum);
break;
}
- ix = (filp->f_pos / QNX4_DIR_ENTRY_SIZE - (filp->f_pos / QNX4_BLOCK_SIZE) * QNX4_INODES_PER_BLOCK) % QNX4_INODES_PER_BLOCK;
+ ix = (int)(filp->f_pos >> QNX4_DIR_ENTRY_SIZE_BITS) % QNX4_INODES_PER_BLOCK;
while (ix < QNX4_INODES_PER_BLOCK) {
offset = ix * QNX4_DIR_ENTRY_SIZE;
de = (struct qnx4_inode_entry *) (bh->b_data + offset);
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c
index 67c9f3d3a..5b70d5211 100644
--- a/fs/qnx4/inode.c
+++ b/fs/qnx4/inode.c
@@ -275,13 +275,13 @@ static int qnx4_statfs(struct super_block *sb,
struct statfs tmp;
memset(&tmp, 0, sizeof tmp);
- tmp.f_type = sb->s_magic;
- tmp.f_bsize = sb->s_blocksize;
- tmp.f_blocks = le32_to_cpu(sb->u.qnx4_sb.BitMap->di_size) * 8;
- tmp.f_bfree = qnx4_count_free_blocks(sb);
- tmp.f_bavail = tmp.f_bfree;
- tmp.f_files = 0x00; /* change this !!! */
- tmp.f_ffree = qnx4_count_free_inodes(sb);
+ tmp.f_type = sb->s_magic;
+ tmp.f_bsize = sb->s_blocksize;
+ tmp.f_blocks = le32_to_cpu(sb->u.qnx4_sb.BitMap->di_size) * 8;
+ tmp.f_bfree = qnx4_count_free_blocks(sb);
+ tmp.f_bavail = tmp.f_bfree;
+ tmp.f_files = -1; /* we don't count files */
+ tmp.f_ffree = -1; /* inodes are allocated dynamically */
tmp.f_namelen = QNX4_NAME_MAX;
return copy_to_user(buf, &tmp, bufsize) ? -EFAULT : 0;
diff --git a/fs/select.c b/fs/select.c
index b664d3e81..7df7e0c9b 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -414,11 +414,14 @@ asmlinkage long sys_poll(struct pollfd * ufds, unsigned int nfds, long timeout)
wait = wait_table;
}
- fds = (struct pollfd **)kmalloc(
- (1 + (nfds - 1) / POLLFD_PER_PAGE) * sizeof(struct pollfd *),
- GFP_KERNEL);
- if (fds == NULL)
- goto out;
+ fds = NULL;
+ if (nfds != 0) {
+ fds = (struct pollfd **)kmalloc(
+ (1 + (nfds - 1) / POLLFD_PER_PAGE) * sizeof(struct pollfd *),
+ GFP_KERNEL);
+ if (fds == NULL)
+ goto out;
+ }
nchunks = 0;
nleft = nfds;
@@ -467,7 +470,8 @@ out_fds1:
out_fds:
for (i=0; i < nchunks; i++)
free_page((unsigned long)(fds[i]));
- kfree(fds);
+ if (nfds != 0)
+ kfree(fds);
out:
if (wait)
free_wait(wait_table);
diff --git a/include/asm-alpha/checksum.h b/include/asm-alpha/checksum.h
index 2f6b82e6c..38ca41f37 100644
--- a/include/asm-alpha/checksum.h
+++ b/include/asm-alpha/checksum.h
@@ -83,7 +83,7 @@ static inline unsigned short csum_fold(unsigned int sum)
#define _HAVE_ARCH_IPV6_CSUM
extern unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
struct in6_addr *daddr,
- __u16 len,
+ __u32 len,
unsigned short proto,
unsigned int sum);
diff --git a/include/asm-arm/checksum.h b/include/asm-arm/checksum.h
index 5e1fb8792..5f1e0f695 100644
--- a/include/asm-arm/checksum.h
+++ b/include/asm-arm/checksum.h
@@ -148,10 +148,10 @@ __csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u32 len,
__u32 proto, unsigned int sum);
extern __inline__ unsigned short int
-csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u16 len,
+csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u32 len,
unsigned short proto, unsigned int sum)
{
- return csum_fold(__csum_ipv6_magic(saddr, daddr, htonl((__u32)len),
+ return csum_fold(__csum_ipv6_magic(saddr, daddr, htonl(len),
htonl(proto), sum));
}
#endif
diff --git a/include/asm-i386/checksum.h b/include/asm-i386/checksum.h
index 6cd9c0992..b5085f376 100644
--- a/include/asm-i386/checksum.h
+++ b/include/asm-i386/checksum.h
@@ -154,7 +154,7 @@ static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
#define _HAVE_ARCH_IPV6_CSUM
static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
struct in6_addr *daddr,
- __u16 len,
+ __u32 len,
unsigned short proto,
unsigned int sum)
{
@@ -173,7 +173,7 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
"
: "=&r" (sum)
: "r" (saddr), "r" (daddr),
- "r"(htonl((__u32) (len))), "r"(htonl(proto)), "0"(sum));
+ "r"(htonl(len)), "r"(htonl(proto)), "0"(sum));
return csum_fold(sum);
}
diff --git a/include/asm-m68k/checksum.h b/include/asm-m68k/checksum.h
index f5236490a..22041aa52 100644
--- a/include/asm-m68k/checksum.h
+++ b/include/asm-m68k/checksum.h
@@ -123,7 +123,7 @@ ip_compute_csum(unsigned char * buff, int len)
#define _HAVE_ARCH_IPV6_CSUM
static __inline__ unsigned short int
csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
- __u16 len, unsigned short proto, unsigned int sum)
+ __u32 len, unsigned short proto, unsigned int sum)
{
register unsigned long tmp;
__asm__("addl %2@,%0\n\t"
@@ -145,7 +145,7 @@ csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr,
"clrl %1\n\t"
"addxl %1,%0"
: "=&d" (sum), "=&d" (tmp)
- : "a" (saddr), "a" (daddr), "d" ((__u32) len + proto),
+ : "a" (saddr), "a" (daddr), "d" (len + proto),
"0" (sum));
return csum_fold(sum);
diff --git a/include/asm-m68k/entry.h b/include/asm-m68k/entry.h
index 3575894b5..444d5ba35 100644
--- a/include/asm-m68k/entry.h
+++ b/include/asm-m68k/entry.h
@@ -4,9 +4,6 @@
#include <linux/config.h>
#include <asm/setup.h>
#include <asm/page.h>
-#ifdef CONFIG_KGDB
-#include <asm/kgdb.h>
-#endif
/*
* Stack layout in 'ret_from_exception':
@@ -69,7 +66,7 @@ PF_DTRACE_BIT = 5
* regs a3-a6 and d6-d7 are preserved by C code
* the kernel doesn't mess with usp unless it needs to
*/
-#ifndef CONFIG_KGDB
+
/*
* a -1 in the orig_d0 field signifies
* that the stack frame is NOT for syscall
@@ -87,27 +84,6 @@ PF_DTRACE_BIT = 5
movel %d0,%sp@- | d0
moveml %d1-%d5/%a0-%a1/%curptr,%sp@-
.endm
-#else
-/* Need to save the "missing" registers for kgdb...
- */
-.macro save_all_int
- clrl %sp@- | stk_adj
- pea -1:w | orig d0
- movel %d0,%sp@- | d0
- moveml %d1-%d5/%a0-%a1/%curptr,%sp@-
- moveml %d6-%d7,kgdb_registers+GDBOFFA_D6
- moveml %a3-%a6,kgdb_registers+GDBOFFA_A3
-.endm
-
-.macro save_all_sys
- clrl %sp@- | stk_adj
- movel %d0,%sp@- | orig d0
- movel %d0,%sp@- | d0
- moveml %d1-%d5/%a0-%a1/%curptr,%sp@-
- moveml %d6-%d7,kgdb_registers+GDBOFFA_D6
- moveml %a3-%a6,kgdb_registers+GDBOFFA_A3
-.endm
-#endif
.macro restore_all
moveml %sp@+,%a0-%a1/%curptr/%d1-%d5
@@ -145,21 +121,11 @@ PF_DTRACE_BIT = 5
#define PT_OFF_ORIG_D0 0x24
#define PT_OFF_FORMATVEC 0x32
#define PT_OFF_SR 0x2C
-#ifndef CONFIG_KGDB
#define SAVE_ALL_INT \
"clrl %%sp@-;" /* stk_adj */ \
"pea -1:w;" /* orig d0 = -1 */ \
"movel %%d0,%%sp@-;" /* d0 */ \
"moveml %%d1-%%d5/%%a0-%%a2,%%sp@-"
-#else
-#define SAVE_ALL_INT \
- "clrl %%sp@-\n\t" /* stk_adj */ \
- "pea -1:w\n\t" /* orig d0 = -1 */ \
- "movel %%d0,%%sp@-\n\t" /* d0 */ \
- "moveml %%d1-%%d5/%%a0-%%a2,%%sp@-\n\t" \
- "moveml %%d6-%%d7,kgdb_registers+"STR(GDBOFFA_D6)"\n\t" \
- "moveml %%a3-%%a6,kgdb_registers+"STR(GDBOFFA_A3)
-#endif
#define GET_CURRENT(tmp) \
"movel %%sp,"#tmp"\n\t" \
"andw #-"STR(KTHREAD_SIZE)","#tmp"\n\t" \
diff --git a/include/asm-m68k/init.h b/include/asm-m68k/init.h
index dc73aed8a..aa3351983 100644
--- a/include/asm-m68k/init.h
+++ b/include/asm-m68k/init.h
@@ -1,10 +1,6 @@
#ifndef _M68K_INIT_H
#define _M68K_INIT_H
-#include <linux/config.h>
-
-#ifndef CONFIG_KGDB
-
#define __init __attribute__ ((__section__ (".text.init")))
#define __initdata __attribute__ ((__section__ (".data.init")))
/* For assembly routines */
@@ -12,18 +8,4 @@
#define __FINIT .previous
#define __INITDATA .section ".data.init",#alloc,#write
-#else
-
-/* gdb doesn't like it all if the code for one source file isn't together in
- * the executable, so we must avoid the .init sections :-( */
-
-#define __init
-#define __initdata
-/* For assembly routines */
-#define __INIT
-#define __FINIT
-#define __INITDATA
-
-#endif /* CONFIG_KGDB */
-
#endif
diff --git a/include/asm-m68k/kgdb.h b/include/asm-m68k/kgdb.h
deleted file mode 100644
index e1d3c493f..000000000
--- a/include/asm-m68k/kgdb.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * include/asm-m68k/kgdb.h
- *
- * Copyright (C) 1996 Roman Hodek
- */
-
-#ifndef __ASM_M68k_KGDB_H
-#define __ASM_M68k_KGDB_H
-
-/*
- * Structure to save all register values in, already in the order gdb wants
- * it. Note that the upper half of the SR field is recycled for the FORMAT and
- * VECTOR fields. Hope that doesn't confuse gdb... That upper half is ignored
- * on exiting the stub, so gdb can modify it as it likes.
- */
-
-#define GDBREG_A6 14
-#define GDBREG_A7 15
-#define GDBREG_SP 15
-#define GDBREG_SR 16
-#define GDBREG_PC 17
-#define GDBREG_FP0 18
-#define GDBREG_FP7 25
-#define GDBREG_FPCR 26
-#define GDBREG_FPIAR 28
-
-#define GDBOFFA_D6 (6*4)
-#define GDBOFFA_A3 (11*4)
-
-#define NUMREGSBYTES 180
-
-#ifndef __ASSEMBLY__
-
-struct gdb_regs {
- long regs[16]; /* d0-a7 */
- unsigned format : 4; /* frame format specifier */
- unsigned vector : 12; /* vector offset */
- unsigned short sr; /* status register */
- unsigned long pc; /* program counter */
- unsigned long fpregs[8*3]; /* fp0-fp7 */
- unsigned long fpcntl[3]; /* fpcr, fpsr, fpiar */
-};
-
-extern struct gdb_regs kgdb_registers;
-extern void kgdb_init( void );
-struct frame;
-extern asmlinkage void enter_kgdb( struct pt_regs *fp );
-
-extern int kgdb_initialized;
-
-/*
- * This function will generate a breakpoint exception. It is used at the
- * beginning of a program to sync up with a debugger and can be used
- * otherwise as a quick means to stop program execution and "break" into
- * the debugger.
- */
-extern inline void breakpoint( void )
-{
- if (!kgdb_initialized)
- /* if kgdb not inited, do nothing */
- return;
-
- /* breakpoint instruction is TRAP #15 */
- __asm__ __volatile__ ( "trap #15" );
-}
-
-/*
- * This function will report a SIGABORT to gdb.
- */
-extern inline void kgdb_abort( void )
-{
- if (!kgdb_initialized)
- /* if kgdb not inited, do nothing */
- return;
-
- /* TRAP #14 is reported as SIGABORT */
- __asm__ __volatile__ ( "trap #14" );
-}
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __ASM_M68k_KGDB_H */
-
diff --git a/include/asm-m68k/semaphore.h b/include/asm-m68k/semaphore.h
index 16ab57862..0b76132f6 100644
--- a/include/asm-m68k/semaphore.h
+++ b/include/asm-m68k/semaphore.h
@@ -1,6 +1,8 @@
#ifndef _M68K_SEMAPHORE_H
#define _M68K_SEMAPHORE_H
+#define RW_LOCK_BIAS 0x01000000
+
#ifndef __ASSEMBLY__
#include <linux/linkage.h>
@@ -205,11 +207,38 @@ struct rw_semaphore {
atomic_t writers;
#endif
};
-#endif /* __ASSEMBLY__ */
-#define RW_LOCK_BIAS 0x01000000
+#if WAITQUEUE_DEBUG
+#define __RWSEM_DEBUG_INIT , ATOMIC_INIT(0), ATOMIC_INIT(0)
+#else
+#define __RWSEM_DEBUG_INIT /* */
+#endif
-#ifndef __ASSEMBLY__
+#define __RWSEM_INITIALIZER(name,count) \
+{ ATOMIC_INIT(count), 0, 0, 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
+ __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
+ __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
+
+#define __DECLARE_RWSEM_GENERIC(name,count) \
+ struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
+
+#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
+#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
+#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
+
+extern inline void init_rwsem(struct rw_semaphore *sem)
+{
+ atomic_set(&sem->count, RW_LOCK_BIAS);
+ sem->read_bias_granted = 0;
+ sem->write_bias_granted = 0;
+ init_waitqueue_head(&sem->wait);
+ init_waitqueue_head(&sem->write_bias_wait);
+#if WAITQUEUE_DEBUG
+ sem->__magic = (long)&sem->__magic;
+ atomic_set(&sem->readers, 0);
+ atomic_set(&sem->writers, 0);
+#endif
+}
extern inline void down_read(struct rw_semaphore *sem)
{
diff --git a/include/asm-mips/checksum.h b/include/asm-mips/checksum.h
index a5c61a5d0..25e303e8c 100644
--- a/include/asm-mips/checksum.h
+++ b/include/asm-mips/checksum.h
@@ -1,4 +1,4 @@
-/* $Id: checksum.h,v 1.7 2000/02/16 01:07:48 ralf Exp $
+/* $Id: checksum.h,v 1.8 2000/02/18 00:24:48 ralf Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -202,7 +202,7 @@ static inline unsigned short ip_compute_csum(unsigned char * buff, int len)
#define _HAVE_ARCH_IPV6_CSUM
static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
struct in6_addr *daddr,
- __u16 len,
+ __u32 len,
unsigned short proto,
unsigned int sum)
{
@@ -260,7 +260,7 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
"=r" (proto)
: "r" (saddr),
"r" (daddr),
- "0" (htonl((__u32) (len))),
+ "0" (htonl(len)),
"1" (htonl(proto)),
"r"(sum)
: "$1");
diff --git a/include/asm-mips64/checksum.h b/include/asm-mips64/checksum.h
index 979088f57..effc917c7 100644
--- a/include/asm-mips64/checksum.h
+++ b/include/asm-mips64/checksum.h
@@ -1,4 +1,4 @@
-/* $Id: checksum.h,v 1.4 2000/02/16 01:07:48 ralf Exp $
+/* $Id: checksum.h,v 1.5 2000/02/18 00:24:48 ralf Exp $
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
@@ -194,7 +194,7 @@ ip_compute_csum(unsigned char * buff, int len)
#define _HAVE_ARCH_IPV6_CSUM
static inline unsigned short int
-csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u16 len,
+csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u32 len,
unsigned short proto, unsigned int sum)
{
__asm__("
@@ -249,7 +249,7 @@ csum_ipv6_magic(struct in6_addr *saddr, struct in6_addr *daddr, __u16 len,
.set noreorder"
: "=r" (sum), "=r" (proto)
: "r" (saddr), "r" (daddr),
- "0" (htonl((__u32) (len))), "1" (htonl(proto)), "r"(sum)
+ "0" (htonl(len)), "1" (htonl(proto)), "r"(sum)
: "$1");
return csum_fold(sum);
diff --git a/include/asm-sh/checksum.h b/include/asm-sh/checksum.h
index 6d5f89c04..ae0272e9b 100644
--- a/include/asm-sh/checksum.h
+++ b/include/asm-sh/checksum.h
@@ -189,7 +189,7 @@ static __inline__ unsigned short ip_compute_csum(unsigned char * buff, int len)
#define _HAVE_ARCH_IPV6_CSUM
static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
struct in6_addr *daddr,
- __u16 len,
+ __u32 len,
unsigned short proto,
unsigned int sum)
{
@@ -217,7 +217,7 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
"add %1,%0\n"
: "=r" (sum), "=&r" (__dummy)
: "r" (saddr), "r" (daddr),
- "r" (htonl((__u32) (len))), "r" (htonl(proto)), "0" (sum));
+ "r" (htonl(len)), "r" (htonl(proto)), "0" (sum));
return csum_fold(sum);
}
diff --git a/include/asm-sparc/ap1000/DdvReqTable.h b/include/asm-sparc/ap1000/DdvReqTable.h
deleted file mode 100644
index 78ffacfd3..000000000
--- a/include/asm-sparc/ap1000/DdvReqTable.h
+++ /dev/null
@@ -1,107 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * Request table size
- */
-
-#define TABLE_SIZE 200
-
-/*
- * Indirect memory address table size
- */
-
-#define MTABLE_SIZE 1000
-
-static inline int INC_T(int a)
-{
- return (++a == TABLE_SIZE?0:a);
-}
-
-static inline int INC_ML(int a)
-{
- return (++a == MTABLE_SIZE?0:a);
-}
-
-/*
- * Status of requiest table
- */
-
-#define DDV_ERROR_RETURN 0
-#define DDV_NORMAL_RETURN 1
-#define DDV_REQ_FREE 2
-#define DDV_DISKREAD_REQ 3
-#define DDV_DISKWRITE_REQ 4
-#define DDV_RAWREAD_REQ 5
-#define DDV_RAWWRITE_REQ 6
-#define DDV_CACHEPOSTALL_REQ 11
-#define DDV_CACHEFLUSHALL_REQ 12
-#define DDV_CAPACITY_REQ 13
-
-/*
- * Specify type of interrupt (set by opiu in PBUF1)
- */
-
-#define DDV_PRINTK_INTR 1
-#define DDV_MLIST_INTR 2
-#define DDV_READY_INTR 3
-#define DDV_REQCOMP_INTR 4
-
-struct RequestInformation {
- volatile int status;
- int rtn;
- unsigned bnum;
- int argv[8];
-};
-
-struct DiskInfo {
- u_long blocks;
- u_long blk_size;
- int pad[8];
- unsigned ptrs[4];
-};
-
-struct RequestTable{
- volatile unsigned cell_pointer; /* Cell requiest pointer */
- volatile unsigned ddv_pointer; /* DDV operation pointer */
- struct RequestInformation async_info[TABLE_SIZE];
- volatile unsigned start_mtable;
- volatile unsigned end_mtable;
- unsigned mtable[MTABLE_SIZE];
-};
-
-#define PRINT_BUFS 32
-
-struct OPrintBuf {
- char *fmt;
- int args[6];
-};
-
-struct OPrintBufArray {
- volatile unsigned option_counter;
- volatile unsigned cell_counter;
- struct OPrintBuf bufs[PRINT_BUFS];
-};
-
-#define ALIGN_SIZE 16
-#define ALIGN_BUFS 128
-#define ALIGN_BUF_SIZE 1024
-
-struct AlignBuf {
- char *dest;
- unsigned size;
- int offset;
- char buf[ALIGN_BUF_SIZE+2*ALIGN_SIZE];
-};
-
-struct OAlignBufArray {
- volatile unsigned option_counter;
- volatile unsigned cell_counter;
- struct AlignBuf bufs[ALIGN_BUFS];
-};
-
-
diff --git a/include/asm-sparc/ap1000/apbif.h b/include/asm-sparc/ap1000/apbif.h
deleted file mode 100644
index 6ef9bf0b6..000000000
--- a/include/asm-sparc/ap1000/apbif.h
+++ /dev/null
@@ -1,205 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-
-/*
-** BIF data registers (system mode)
-*/
-#define BIF_DATA (BIF+0x0000) /* BIF send and receive data registe */
-#define BIF_EDATA (BIF+0x0004) /* BIF end data register */
-/*
-** BIF data registers (user mode)
-*/
-#define UBIF_DATA (UBIF+0x0000) /* BIF send and receive data registe */
-#define UBIF_EDATA (UBIF+0x0004) /* BIF end data register */
-
-/*
-** BIF scatter and gather parameter register (system mode)
-*/
-#define BIF_X0SK (BIF+0x0010) /* initial X-skip register */
-#define BIF_XSK (BIF+0x0014) /* X-skip register */
-#define BIF_XSZ (BIF+0x0018) /* X-size register */
-
-#define BIF_Y0SK (BIF+0x001c) /* initial Y-skip register */
-#define BIF_YSK (BIF+0x0020) /* Y-skip register */
-#define BIF_YSZ (BIF+0x0024) /* Y-size register */
-
-#define BIF_CX0SK (BIF+0x0028) /* initial counter of X-skip */
-#define BIF_CXSK (BIF+0x002c) /* X-skip counter */
-#define BIF_CXSZ (BIF+0x0030) /* X-size counter */
-
-#define BIF_CY0SK (BIF+0x0034) /* initial counter of Y-skip */
-#define BIF_CYSK (BIF+0x0038) /* Y-skip counter */
-#define BIF_CYSZ (BIF+0x003c) /* Y-size counter */
-
-#define BIF_TTL (BIF+0x0040) /* number of data transfer register */
-#define BIF_CTTL (BIF+0x0044) /* number of data transfer counter */
-
-/*
-** BIF scatter and gather parameter register (user mode)
-*/
-#define UBIF_X0SK (UBIF+0x0010) /* initial X-skip register */
-#define UBIF_XSK (UBIF+0x0014) /* X-skip register */
-#define UBIF_XSZ (UBIF+0x0018) /* X-size register */
-
-#define UBIF_Y0SK (UBIF+0x001c) /* initial Y-skip register */
-#define UBIF_YSK (UBIF+0x0020) /* Y-skip register */
-#define UBIF_YSZ (UBIF+0x0024) /* Y-size register */
-
-#define UBIF_CX0SK (UBIF+0x0028) /* initial counter of X-skip */
-#define UBIF_CXSK (UBIF+0x002c) /* X-skip counter */
-#define UBIF_CXSZ (UBIF+0x0030) /* X-size counter */
-
-#define UBIF_CY0SK (UBIF+0x0034) /* initial counter of Y-skip */
-#define UBIF_CYSK (UBIF+0x0038) /* Y-skip counter */
-#define UBIF_CYSZ (UBIF+0x003c) /* Y-size counter */
-
-#define UBIF_TTL (UBIF+0x0040) /* number of data transfer register */
-#define UBIF_CTTL (UBIF+0x0044) /* number of data transfer counter */
-
-/*
-** BIF control registers (system mode)
-*/
-#define BIF_CIDR0 (BIF+0x0048) /* cell-id register 0 */
-#define BIF_CIDR1 (BIF+0x004c) /* cell-id register 1 (for cell mode) */
-#define BIF_CIDR2 (BIF+0x0050) /* cell-id register 2 */
-#define BIF_CIDR3 (BIF+0x0054) /* cell-id register 3 */
-#define BIF_HEADER (BIF+0x0058) /* header register */
-#define BIF_INTR (BIF+0x006c) /* BIF interrupt control register */
-#define BIF_SDCSR (BIF+0x0070) /* BIF data control set register */
-#define BIF_RDCSR (BIF+0x0074) /* BIF data control reset reregister */
-#define BIF_MHOCR (BIF+0x0078) /* BIF extentional control reregister */
-
-/*
-** BIF control registers (user mode)
-*/
-#define UBIF_CIDR0 (UBIF+0x0048) /* cell-id register 0 */
-#define UBIF_CIDR1 (UBIF+0x004c) /* cell-id register 1 (for cell mode) */
-#define UBIF_CIDR2 (UBIF+0x0050) /* cell-id register 2 */
-#define UBIF_CIDR3 (UBIF+0x0054) /* cell-id register 3 */
-#define UBIF_HEADER (UBIF+0x0058) /* header register */
-#define UBIF_INTR (UBIF+0x006c) /* BIF interrupt control register */
-#define UBIF_SDCSR (UBIF+0x0070) /* BIF data control set register */
-#define UBIF_RDCSR (UBIF+0x0074) /* BIF data control reset reregister */
-#define UBIF_MHOCR (UBIF+0x0078) /* BIF extentional control reregister */
-
-/*
-** bit assignment
-*/
-#define BIF_HEADER_ID 0xffff0000 /* cell-id */
-#define BIF_HEADER_BR 0x00008000 /* broad bit */
-#define BIF_HEADER_IS 0x00006000 /* ID select */
-#define BIF_HEADER_IS_00 0x00000000
-#define BIF_HEADER_IS_01 0x00002000
-#define BIF_HEADER_IS_10 0x00004000
-#define BIF_HEADER_IS_11 0x00006000
-#define BIF_HEADER_IN 0x00001000 /* interrupt bit */
-#define BIF_HEADER_LS 0x00000800 /* line send */
-#define BIF_HEADER_SC 0x00000400 /* scatter bit */
-#define BIF_HEADER_HS 0x00000200 /* header strip */
-#define BIF_HEADER_RS 0x00000100 /* bus release */
-
-#define BIF_HEADER_ID_SHIFT 16
-
-#define BIF_INTR_GS 0x00020000 /* grant interrupt select */
-#define BIF_INTR_GM 0x00010000 /* grant interrupt mask */
-#define BIF_INTR_GI 0x00008000 /* grant interrupt request */
-#define BIF_INTR_HS 0x00004000 /* header interrupt select */
-#define BIF_INTR_HM 0x00002000 /* header interrupt mask */
-#define BIF_INTR_HI 0x00001000 /* header interrupt request */
-#define BIF_INTR_SS 0x00000800 /* send interrupt select */
-#define BIF_INTR_SM 0x00000400 /* send interrupt mask */
-#define BIF_INTR_SI 0x00000200 /* send interrupt request */
-#define BIF_INTR_RS 0x00000100 /* receive interrupt select */
-#define BIF_INTR_RM 0x00000080 /* receive interrupt mask */
-#define BIF_INTR_RI 0x00000040 /* receive interrupt request */
-#define BIF_INTR_ES 0x00000020 /* error interrupt select */
-#define BIF_INTR_EM 0x00000010 /* error interrupt mask */
-#define BIF_INTR_EI 0x00000008 /* error interrupt request */
-#define BIF_INTR_AS 0x00000004 /* attention interrupt select */
-#define BIF_INTR_AM 0x00000002 /* attention interrupt mask */
-#define BIF_INTR_AI 0x00000001 /* attention interrupt request */
-
-#define BIF_SDCSR_ER 0x7fffc000 /* error detected by BIF */
-#define BIF_SDCSR_PE 0x80000000 /* detect parity error in sync */
-#define BIF_SDCSR_SP 0x40000000 /* parity error in sync */
-#define BIF_SDCSR_LP 0x20000000 /* L-bus parity error */
-#define BIF_SDCSR_LR 0x10000000 /* */
-#define BIF_SDCSR_LW 0x08000000 /* */
-#define BIF_SDCSR_AL 0x04000000 /* specify end bit except of end data */
-#define BIF_SDCSR_SS 0x02000000 /* request bit but masked by slow sync */
-#define BIF_SDCSR_SC 0x01000000 /* clear bit but masked by slow sync */
-#define BIF_SDCSR_SY 0x00800000 /* set bit but masked by slow status */
-#define BIF_SDCSR_FS 0x00400000 /* request bit but masked by fast sync */
-#define BIF_SDCSR_FC 0x00200000 /* clear bit but masked by fast sync */
-#define BIF_SDCSR_FY 0x00100000 /* set bit but masked by fast status */
-#define BIF_SDCSR_CP 0x00080000 /* parity error in commnad bus */
-#define BIF_SDCSR_FP 0x00040000 /* execute scatter or gather but FN=0 */
-#define BIF_SDCSR_PS 0x00020000 /* header receive error */
-#define BIF_SDCSR_RA 0x00010000 /* change scatter,gather parameter */
-#define BIF_SDCSR_PA 0x00008000 /* check if send or receive error */
-#define BIF_SDCSR_DL 0x00004000 /* lost data */
-#define BIF_SDCSR_BB 0x00002000 /* check if some BIF use command bus */
-#define BIF_SDCSR_BG 0x00001000 /* check if command bus got */
-#define BIF_SDCSR_BR 0x00000800 /* request command bus */
-#define BIF_SDCSR_CN 0x00000400 /* release BIF from command bus */
-#define BIF_SDCSR_FN 0x00000200 /* scatter gather enable */
-#define BIF_SDCSR_EB 0x00000100 /* send data that have end bit */
-#define BIF_SDCSR_TB 0x000000E0 /* data in send FIFO */
-#define BIF_SDCSR_TB4 0x00000080
-#define BIF_SDCSR_TB2 0x00000040
-#define BIF_SDCSR_TB1 0x00000020
-#define BIF_SDCSR_RB 0x0000001c /* data in receive FIFO */
-#define BIF_SDCSR_RB4 0x00000010
-#define BIF_SDCSR_RB2 0x00000008
-#define BIF_SDCSR_RB1 0x00000004
-#define BIF_SDCSR_DE 0x00000002 /* DMA interface enable bitr */
-#define BIF_SDCSR_DR 0x00000001 /* data transfer direction */
-
-#define BIF_RDCSR_ER BIF_SDCSR_ER /* error detected by BIF */
-#define BIF_RDCSR_PE BIF_SDCSR_PE /* detect parity error in sync */
-#define BIF_RDCSR_SP BIF_SDCSR_SP /* parity error in sync */
-#define BIF_RDCSR_LP BIF_SDCSR_LP /* L-bus parity error */
-#define BIF_RDCSR_LR BIF_SDCSR_LR /* */
-#define BIF_RDCSR_LW BIF_SDCSR_LW /* */
-#define BIF_RDCSR_AL BIF_SDCSR_AL /* specify end bit except of end data */
-#define BIF_RDCSR_SS BIF_SDCSR_SS /* request bit but masked by slow sync */
-#define BIF_RDCSR_SC BIF_SDCSR_SC /* clear bit but masked by slow sync */
-#define BIF_RDCSR_SY BIF_SDCSR_SY /* set bit but masked by slow status */
-#define BIF_RDCSR_FS BIF_SDCSR_FS /* request bit but masked by fast sync*/
-#define BIF_RDCSR_FC BIF_SDCSR_FC /* clear bit but masked by fast sync */
-#define BIF_RDCSR_FY BIF_SDCSR_FY /* set bit but masked by fast status */
-#define BIF_RDCSR_CP BIF_SDCSR_CP /* parity error in commnad bus */
-#define BIF_RDCSR_FP BIF_SDCSR_FP /* execute scatter or gather but FN=0 */
-#define BIF_RDCSR_PS BIF_SDCSR_PS /* header receive error */
-#define BIF_RDCSR_RA BIF_SDCSR_RA /* change scatter,gather parameter */
-#define BIF_RDCSR_DL BIF_SDCSR_DL /* lost data */
-#define BIF_RDCSR_PA BIF_SDCSR_PA /* check if send or receive error */
-#define BIF_RDCSR_BB BIF_SDCSR_BB /* check if some BIF use command bus */
-#define BIF_RDCSR_BG BIF_SDCSR_BG /* check if command bus got */
-#define BIF_RDCSR_BR BIF_SDCSR_BR /* request command bus */
-#define BIF_RDCSR_CN BIF_SDCSR_CN /* release BIF from command bus */
-#define BIF_RDCSR_EB BIF_SDCSR_EB /* send data that have end bit */
-#define BIF_RDCSR_TB BIF_SDCSR_TB /* data in send FIFO */
-#define BIF_RDCSR_RB BIF_SDCSR_RB /* data in receive FIFO */
-#define BIF_RDCSR_DE BIF_SDCSR_DE /* DMA interface enable bitr */
-#define BIF_RDCSR_DR BIF_SDCSR_DR /* data transfer direction */
-#define BIF_RDCSR_FN BIF_SDCSR_FN /* scatter gather enable */
-
-#define BIF_MHOCR_RS 0x00000800 /* bif reset */
-#define BIF_MHOCR_RC 0x00000400 /* commnad bus circuit reset */
-#define BIF_MHOCR_RI 0x00000200 /* remove input buffer data */
-#define BIF_MHOCR_RO 0x00000100 /* remove output buffer data */
-#define BIF_MHOCR_BA 0x00000008 /* command bus arbitlater reset */
-#define BIF_MHOCR_MD 0x00000006 /* command bus mode */
-#define BIF_MHOCR_AT 0x00000001 /* command bus attention signal */
-
-#define BIF_MHOCR_MD_NORMAL 0x00000006 /* command bus mode [normal] */
-#define BIF_MHOCR_MD_BUSWGR 0x00000004 /* command bus mode [bus gather] */
-#define BIF_MHOCR_MD_SETCID 0x00000002 /* command bus mode [set cid] */
-
-
diff --git a/include/asm-sparc/ap1000/aplib.h b/include/asm-sparc/ap1000/aplib.h
deleted file mode 100644
index 55e2f528d..000000000
--- a/include/asm-sparc/ap1000/aplib.h
+++ /dev/null
@@ -1,119 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-
-/* aplib kernel interface definition */
-
-#ifndef _APLIB_H_
-#define _APLIB_H_
-
-struct aplib_struct {
- unsigned *ringbuf;
- unsigned write_pointer, read_pointer; /* in words */
- unsigned ringbuf_size; /* in words */
- unsigned rbuf_counter; /* read messages */
- unsigned rbuf_flag1, rbuf_flag2; /* received messages */
- unsigned *physical_cid; /* logical to physical mapping */
- unsigned *rel_cid; /* logical to relative (RTC) mapping */
- unsigned numcells; /* number of logical cells */
- unsigned numcells_x; /* number of logical cells in x direction */
- unsigned numcells_y; /* number of logical cells in y direction */
- unsigned cid, tid; /* this cells logical cell ID and task ID */
- unsigned cidx, cidy; /* logical cell id in x and y direction */
- unsigned ack_flag, ack_request;
- unsigned ok_x, ok_y, ok_xy; /* whether hardware x, y and xy sends are allowed */
-};
-
-
-/*
- * the system ringbuffer structure
- * this is also the old way that tasks accessed the MSC hardware
- */
-struct ringbuf_struct {
- void *ringbuf; /* pointer to the ringbuf */
- void *shared; /* pointer to the shared page */
- int order; /* arg to __get_free_pages */
- unsigned write_ptr; /* write pointer into the ringbuf */
- unsigned vaddr; /* base virtual address of ringbuf for task */
- unsigned frag_count; /* how many words in the frag queue */
- unsigned frag_len; /* how many words expected in the frag queue */
- unsigned sq_fragment[16]; /* if the task switches part way through
- an op then shove the partial op here */
-};
-
-
-#define APLIB_INIT 1
-#define APLIB_SYNC 2
-#define APLIB_GET 3
-#define APLIB_PUT 4
-#define APLIB_SEND 5
-#define APLIB_PROBE 6
-#define APLIB_POLL 7
-#define APLIB_XSEND 8
-#define APLIB_YSEND 9
-#define APLIB_XYSEND 10
-#define APLIB_XPUT 11
-#define APLIB_YPUT 12
-#define APLIB_XYPUT 13
-
-
-/* message kinds */
-#define RBUF_SYSTEM 0
-#define RBUF_SEND 1
-#define RBUF_X_BRD 2
-#define RBUF_Y_BRD 3
-#define RBUF_XY_BRD 4
-#define RBUF_RPC 5
-#define RBUF_GET 6
-#define RBUF_MPI 7
-#define RBUF_BIGSEND 8
-#define RBUF_SEEN 0xE
-#define RBUF_READ 0xF
-
-#define APLIB_PAGE_BASE 0xd0000000
-#define APLIB_PAGE_LEN 8192
-
-struct aplib_init {
- unsigned numcells, cid;
- unsigned numcells_x, numcells_y;
- unsigned *phys_cells; /* physical cell list */
- unsigned *ringbuffer; /* pointer to user supplied ring buffer */
- unsigned ringbuf_size; /* in words */
-};
-
-
-struct aplib_putget {
- unsigned cid;
- unsigned *src_addr, *dest_addr;
- unsigned size; /* in words */
- unsigned *dest_flag, *src_flag;
- unsigned ack;
-};
-
-
-struct aplib_send {
- /* the ordering here is actually quite important - the parts to be
- read by the bigrecv function must be in the first 24 bytes */
- unsigned src_addr;
- unsigned size;
- unsigned info1, info2;
- unsigned flag_addr;
- volatile unsigned flag;
- unsigned type;
- unsigned tag;
- unsigned cid;
-};
-
-#ifdef __KERNEL__
-#define MAX_PUT_SIZE (1024*1024 - 1) /* in words */
-#define SMALL_SEND_THRESHOLD 128
-
-
-#endif
-
-#endif /* _APLIB_H_ */
-
diff --git a/include/asm-sparc/ap1000/apreg.h b/include/asm-sparc/ap1000/apreg.h
deleted file mode 100644
index bf1ea66d3..000000000
--- a/include/asm-sparc/ap1000/apreg.h
+++ /dev/null
@@ -1,619 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/* ap1000 register definitions needed for Linux/AP+ */
-
-#ifndef _AP1000_APREG_H
-#define _AP1000_APREG_H
-#include <asm/page.h>
-#include <asm/ap1000/apservice.h>
-#include <asm/ap1000/apbif.h>
-#include <linux/threads.h>
-
-/*
- * Macros for accessing I/O registers.
- */
-#define BIF_IN(reg) (*(volatile unsigned *)(reg))
-#define BIF_OUT(reg,v) (*(volatile unsigned *)(reg) = (v))
-#define DMA_IN(reg) (*(volatile unsigned *)(reg))
-#define DMA_OUT(reg,v) (*(volatile unsigned *)(reg) = (v))
-#define MC_IN(reg) (*(volatile unsigned *)(reg))
-#define MC_OUT(reg,v) (*(volatile unsigned *)(reg) = (v))
-#define MSC_IN(reg) (*(volatile unsigned *)(reg))
-#define MSC_OUT(reg,v) (*(volatile unsigned *)(reg) = (v))
-#define MSC_IO(reg) (*(volatile unsigned *)(reg))
-#define RTC_IO(reg) (*(volatile unsigned *)(reg))
-#define MC_IO(reg) (*(volatile unsigned *)(reg))
-#define OPT_IO(reg) (*(volatile unsigned *)(reg))
-
-/*
- * B-net interface register definitions.
- */
-#define BIF 0xfff30000
-#define BIF_CIDR1 (BIF+0x004c) /* cell-id register 1 (for cell mode)*/
-#define BIF_SDCSR (BIF+0x0070) /* BIF data control set register */
-#define BIF_DATA (BIF+0x0000) /* BIF send and receive data registe */
-#define BIF_EDATA (BIF+0x0004) /* BIF end data register */
-#define BIF_INTR (BIF+0x006c) /* BIF interrupt control register */
-
-#define SSTT_SET (BIF+0xe0) /* set SSTT */
-#define SSTT_CLR (BIF+0xe4) /* clear SSTT */
-#define SSTT_SMSK (BIF+0xe8) /* set SSTT mask */
-#define SSTT_CMSK (BIF+0xec) /* clear SSTT mask */
-#define SSTT_SMD (BIF+0xf0) /* set SSYN & SSTT mode */
-#define SSTT_CMD (BIF+0xf4) /* clear SSYN & SSTT mode */
-
-/*
-** FSTT registers
-*/
-#define FSTT BIF /* FSTT only system mode */
-#define FSTT_SET (FSTT+0xa0) /* set FSTT */
-#define FSTT_CLR (FSTT+0xa4) /* clear FSTT */
-#define FSTT_SMSK (FSTT+0xa8) /* set FSTT mask */
-#define FSTT_CMSK (FSTT+0xac) /* clear FSTT mask */
-#define FSTT_SMD (FSTT+0xb0) /* set FSYN & FSTT mode */
-#define FSTT_CMD (FSTT+0xb4) /* clear FSYN & FSTT mode */
-#define FSTT_TIM (FSTT+0xb8) /* status timer */
-
-
-#define BIF_SDCSR_RB 0x0000001c /* data in receive FIFO */
-#define BIF_SDCSR_EB 0x00000100 /* send data that have end bit */
-#define BIF_SDCSR_BG 0x00001000 /* check if command bus got */
-#define BIF_SDCSR_BR 0x00000800 /* request command bus */
-#define BIF_SDCSR_TB 0x000000E0 /* data in send FIFO */
-#define BIF_SDCSR_PE 0x80000000 /* detect parity error in sync */
-#define BIF_SDCSR_BB 0x00002000 /* check if some BIF use command bus */
-
-#define BIF_SDCSR_RB_SHIFT 2
-#define BIF_SDCSR_TB_SHIFT 5
-
-#define BIF_INTR_GET_SH 15 /* get bus interrupt */
-#define BIF_INTR_HEADER_SH 12 /* header interrupt */
-#define BIF_INTR_SEND_SH 9 /* send interrupt */
-#define BIF_INTR_RECV_SH 6 /* receive interrupt */
-#define BIF_INTR_ERR_SH 3 /* error interrupt */
-#define BIF_INTR_ATTN_SH 0 /* attention interrupt */
-
-
-#define BIF_HEADER_HS 0x00000200 /* header strip */
-#define BIF_HEADER_RS 0x00000100 /* bus release */
-#define BIF_HEADER_IN 0x00001000 /* interrupt bit */
-#define BIF_HEADER_BR 0x00008000 /* broad bit */
-#define BIF_INTR_HS 0x00004000 /* header interrupt select */
-#define HOST_CID 0x1000
-#define MAKE_HEADER(cid) (BIF_HEADER_IN | \
- ((cid)==-1?BIF_HEADER_BR:((cid)<<16) | (1<<13)))
-
-#define BIF_RDCSR (BIF+0x0074) /* BIF data control reset reregister */
-
-/*
- * Interrupt levels for AP+ devices
- */
-#define APBIFGET_IRQ 1 /* have acquired B-net */
-#define APOPT0_IRQ 2 /* option interrupt level 0 */
-#define APSYNC_IRQ 3 /* sync (S-net) interrupt */
-#define APDMA_IRQ 4 /* DMA complete interrupt */
-#define APRTC_IRQ 5 /* RTC data transfer interrupt */
-#define APIPORT_IRQ 6 /* Interrupt port interrupt */
-#define APOPT1_IRQ 7 /* option interrupt level 1 */
-#define APBIF_IRQ 8 /* B-net interface interrupt */
-#define APMAS_IRQ 9 /* Send/Recv mem acc. seq. intr */
-#define APTIM1_IRQ 10 /* Timer 1 interrupt */
-#define APMSC_IRQ 11 /* MSC+ ring buf/queue spill etc. */
-#define APLBUS_IRQ 12 /* LBUS error interrupt */
-#define APATTN_IRQ 13 /* Attention interrupt */
-#define APTIM0_IRQ 14 /* Timer 0 interrupt */
-#define APMEM_IRQ 15 /* Memory error interrupt */
-
-/*
- * LBUS DMA controller register definitions
- */
-#define DMA 0xfff00000 /* dma controller address */
-#define DMA3 (DMA+0xc0) /* DMA channel 3 */
-#define DMA_DMST 0x04
-#define DMA_MADDR 0x10
-#define DMA_HSKIP 0x08
-#define DMA_HCNT 0x0a
-#define DMA_VSKIP 0x0c
-#define DMA_VCNT 0x0e
-#define DMA_DCMD 0x00
-#define DMA_HDRP 0x28
-#define DMA_DSIZE 0x02
-#define DMA_CSIZE 0x06
-#define DMA_VCNT 0x0e
-
-#define DMA_BIF_BCMD (DMA+0x120) /* BIF receive command register */
-#define DMA_BIF_BRST (DMA+0x124) /* BIF receive status register */
-#define DMA_BCMD_SA 0x40000000 /* software abort */
-#define DMA_DMST_AC 0x80000000 /* channel active */
-#define DMA_DMST_RST 0xffe40000 /* reset bits and reqs */
-#define DMA_DCMD_ST 0x80000000 /* start operation */
-#define DMA_DCMD_TYP_AUTO 0x30000000 /* 11: auto */
-
-#define DMA_DCMD_TD_MD 0x04000000 /* transfer mem->dev */
-#define DMA_DCMD_TD_DM 0x00000000 /* transfer direction dev->mem*/
-
-#define DMA_CH2 (DMA+0x80) /* DMA channel 2 */
-#define DMA_CH3 (DMA+0xc0) /* DMA channel 3 */
-#define DMA2_DMST (DMA_CH2+0x04) /* DMA2 status register */
-#define DMA3_DMST (DMA_CH3+0x04) /* DMA3 status register */
-#define DMA2_DCMD (DMA_CH2+0x00) /* DMA2 command register */
-
-#define DMA_INTR_NORMAL_SH 19 /* normal DMA interrupt */
-#define DMA_INTR_ERROR_SH 16 /* error DMA interrupt */
-
-#define DMA_DCMD_SA 0x40000000 /* software abort */
-
-
-#define DMA_MAX_TRANS_SIZE (0xffff<<2)
-#define DMA_TRANS_BLOCK_SIZE (64<<2)
-
-#define WORD_SIZE 4
-#define B2W(x) (((x) + WORD_SIZE - 1) / WORD_SIZE)
-#define W2B(x) ((x) * WORD_SIZE)
-
-#define DMA_GEN 0xfff00180 /* DMA general control reg */
-
-/* AP1000+ Message Controller (MSC+) */
-
-#define MSC_BASE0 0xfa008000
-
-#define MSC_SQCTRL (MSC_BASE0 + 0x0) /* Send Queue control */
-
-/* bits in MSC_SQCTRL */
-#define MSC_SQC_STABLE 0x400 /* Send Queue stable */
-#define MSC_SQC_MODE 0x300 /* Send Queue mode: */
-#define MSC_SQC_MODE_BLOCK 0 /* blocking */
-#define MSC_SQC_MODE_THRU 0x100 /* through */
-#define MSC_SQC_MODE_NORMAL 0x200 /* or normal */
-#define MSC_SQC_SPLF_SH 3 /* bit# for spill flags */
-#define MSC_SQC_SPLF_M 0x1f /* 5 bits wide */
-#define MSC_SQC_REPLYF 0x080 /* Reply queue full */
-#define MSC_SQC_REMRF 0x040 /* Remote reply queue full */
-#define MSC_SQC_USERF 0x020 /* User queue full */
-#define MSC_SQC_REMAF 0x010 /* Remote access queue full */
-#define MSC_SQC_SYSF 0x008 /* System queue full */
-#define MSC_SQC_PAUSE 0x004 /* Send Queue pause */
-#define MSC_SQC_RMODE 0x003 /* Requested mode: */
-#define MSC_SQC_RMODE_BLOCK 0 /* blocking */
-#define MSC_SQC_RMODE_THRU 1 /* through */
-#define MSC_SQC_RMODE_NORMAL 2 /* or normal */
-
-#define MSC_SQPTR0 (MSC_BASE0 + 0x8) /* Send Queue 0 pointers */
-#define MSC_SQPTR1 (MSC_BASE0 + 0x10) /* Send Queue 1 pointers */
-#define MSC_SQPTR2 (MSC_BASE0 + 0x18) /* Send Queue 2 pointers */
-#define MSC_SQPTR3 (MSC_BASE0 + 0x20) /* Send Queue 3 pointers */
-#define MSC_SQPTR4 (MSC_BASE0 + 0x28) /* Send Queue 4 pointers */
-
-/* bits in MSC_SQPTR[0-4] */
-#define MSC_SQP_MODE (1 << 20) /* 64/32 word queue mode */
-#define MSC_SQP_BP_SH 17 /* bit no. for base ptr */
-#define MSC_SQP_BP_M 7 /* (it's 3 bits wide) */
-#define MSC_SQP_CNT_SH 12 /* bit no. for count */
-#define MSC_SQP_CNT_M 0x1f /* (it's 5 bits wide) */
-#define MSC_SQP_RP_SH 6 /* bit no. for read ptr */
-#define MSC_SQP_RP_M 0x3f /* (it's 6 bits wide() */
-#define MSC_SQP_WP_SH 0 /* bit no. for write ptr */
-#define MSC_SQP_WP_M 0x3f /* (it's 6 bits wide() */
-
-#define MSC_OPTADR (MSC_BASE0 + 0x30) /* option memory address */
-
-#define MSC_MASCTRL (MSC_BASE0 + 0x38) /* Mem Access Sequencer ctrl */
-
-/* Bits in MSC_MASCTRL */
-#define MSC_MASC_SPAUSE 0x80 /* Send MAS pause */
-#define MSC_MASC_RPAUSE 0x40 /* Recv MAS pause */
-#define MSC_MASC_SFEXIT 0x20 /* Send MAS fault/exit */
-#define MSC_MASC_RFEXIT 0x10 /* Recv MAS fault/exit */
-#define MSC_MASC_SREADY 0x08 /* Send MAS ready */
-#define MSC_MASC_RREADY 0x04 /* Recv MAS ready */
-#define MSC_MASC_SSTOP 0x02 /* Send MAS is stopped */
-#define MSC_MASC_RSTOP 0x01 /* Recv MAS is stopped */
-
-#define MSC_SMASADR (MSC_BASE0 + 0x40) /* Send Mem Acc Seq address */
-#define MSC_RMASADR (MSC_BASE0 + 0x48) /* Recv Mem Acc Seq address */
-
-#define MSC_PID (MSC_BASE0 + 0x50) /* Context number (proc id) */
-
-#define MSC_QWORDCNT (MSC_BASE0 + 0x60) /* Queue word counts */
-
-/* Fields in MSC_QWORDCNT */
-#define MSC_QWDC_SYSCNT_SH 24 /* bit# for system count */
-#define MSC_QWDC_SYSCNT_M 0x3f /* 6 bits wide */
-#define MSC_QWDC_SYSLEN_SH 16 /* bit# for len of sys cmd */
-#define MSC_QWDC_SYSLEN_M 0x3f /* 6 bits wide */
-#define MSC_QWDC_USRCNT_SH 8 /* bit# for user count */
-#define MSC_QWDC_USRCNT_M 0x3f /* 6 bits wide */
-#define MSC_QWDC_USRLEN_SH 0 /* bit# for len of user cmd */
-#define MSC_QWDC_USRLEN_M 0x3f /* 6 bits wide */
-
-#define MSC_INTR (MSC_BASE0 + 0x70) /* Interrupt control/status */
-
-/* Bit offsets of interrupt fields in MSC_INTR */
-#define MSC_INTR_QBMFUL_SH 28 /* Queue buffer full intr */
-#define MSC_INTR_SQFILL_SH 24 /* Send queue fill intr */
-#define MSC_INTR_RBMISS_SH 20 /* Ring buffer miss intr */
-#define MSC_INTR_RBFULL_SH 16 /* Ring buffer full intr */
-#define MSC_INTR_RMASF_SH 12 /* Recv MAS fault intr */
-#define MSC_INTR_RMASE_SH 8 /* Recv MAS error intr */
-#define MSC_INTR_SMASF_SH 4 /* Send MAS fault intr */
-#define MSC_INTR_SMASE_SH 0 /* Send MAS error intr */
-
-#define MSC_PPIO (MSC_BASE0 + 0x1000) /* PArallel port I/O */
-#define MSC_PACSELECT (MSC_BASE0 + 0x1008) /* Performance analyser sel. */
-
-#define MSC_CIDRANGE (MSC_BASE0 + 0x1010) /* Rel. Cell-id range limits */
-
-/* Fields in MSC_CIDRANGE */
-#define MSC_CIDR_LRX_SH 24 /* Rel. X lower limit bit# */
-#define MSC_CIDR_LRX_M 0xFF /* it's 8 bits wide */
-#define MSC_CIDR_HRX_SH 16 /* Rel. X upper limit bit# */
-#define MSC_CIDR_HRX_M 0xFF /* it's 8 bits wide */
-#define MSC_CIDR_LRY_SH 8 /* Rel. Y lower limit bit# */
-#define MSC_CIDR_LRY_M 0xFF /* it's 8 bits wide */
-#define MSC_CIDR_HRY_SH 0 /* Rel. Y upper limit bit# */
-#define MSC_CIDR_HRY_M 0xFF /* it's 8 bits wide */
-
-#define MSC_QBMPTR (MSC_BASE0 + 0x1018) /* Queue buffer mgr. ptrs */
-
-/* Fields in MSC_QBMPTR */
-#define MSC_QBMP_LIM_SH 24 /* Pointer limit bit# */
-#define MSC_QBMP_LIM_M 0x3F /* (6 bits wide) */
-#define MSC_QBMP_BP_SH 16 /* Base pointer bit# */
-#define MSC_QBMP_BP_M 0xFF /* (8 bits wide) */
-#define MSC_QBMP_WP_SH 0 /* Write pointer bit# */
-#define MSC_QBMP_WP_M 0xFFFF /* (16 bits wide) */
-
-#define MSC_SMASTWP (MSC_BASE0 + 0x1030) /* Send MAS virt page etc. */
-#define MSC_SMASREG (MSC_BASE0 + 0x1038) /* Send MAS context etc. */
-#define MSC_RMASTWP (MSC_BASE0 + 0x1040) /* Recv MAS virt page etc. */
-#define MSC_RMASREG (MSC_BASE0 + 0x1048) /* Recv MAS context etc. */
-
-/* Bits in MSC_[SR]MASREG */
-#define MSC_MASR_CONTEXT_SH 20 /* Context at bit 20 */
-#define MSC_MASR_CONTEXT_M 0xfff /* 12 bits wide */
-#define MSC_MASR_AVIO 8 /* Address violation bit */
-#define MSC_MASR_CMD 7 /* MAS command bits */
-#define MSC_MASR_CMD_XFER 0 /* transfer data cmd */
-#define MSC_MASR_CMD_FOP 5 /* fetch & operate cmd */
-#define MSC_MASR_CMD_INC 6 /* increment cmd (i.e. flag) */
-#define MSC_MASR_CMD_CSI 7 /* compare & swap cmd */
-
-#define MSC_HDGERRPROC (MSC_BASE0 + 0x1050) /* Header gen. error process */
-#define MSC_RHDERRPROC (MSC_BASE0 + 0x1058) /* Recv. header decoder err. */
-
-#define MSC_SMASCNT (MSC_BASE0 + 0x1060) /* Send MAS counters */
-
-/* Bits in MSC_SMASCNT */
-#define MSC_SMCT_ACCSZ_SH 28 /* Access size at bit 28 */
-#define MSC_SMCT_ACCSZ_M 7 /* 3 bits wide */
-#define MSC_SMCT_MCNT_SH 8 /* M(?) count at bit 8 */
-#define MSC_SMCT_MCNT_M 0xfffff /* 20 bits wide */
-#define MSC_SMCT_ICNT_SH 0 /* I(?) count at bit 0 */
-#define MSC_SMCT_ICNT_M 0xff /* 8 bits wide */
-
-#define MSC_IRL (MSC_BASE0 + 0x1070) /* highest current int req */
-#define MSC_SIMMCHK (MSC_BASE0 + 0x1078) /* DRAM type installed */
-
-#define MSC_SIMMCHK_MASK 0x00000008
-
-#define MSC_SQRAM (MSC_BASE0 + 0x2000) /* Send Queue RAM (to +23f8) */
-
-#define MSC_VERSION (MSC_BASE0 + 0x3000) /* MSC+ version */
-
-#define MSC_NR_RBUFS 3
-
-#define MSC_RBMBWP0 (MSC_BASE0 + 0x4000) /* Ring buf 0 base/write ptr */
-#define MSC_RBMMODE0 (MSC_BASE0 + 0x4008) /* Ring buf 0 mode/context */
-#define MSC_RBMBWP1 (MSC_BASE0 + 0x4010) /* Ring buf 1 base/write ptr */
-#define MSC_RBMMODE1 (MSC_BASE0 + 0x4018) /* Ring buf 1 mode/context */
-#define MSC_RBMBWP2 (MSC_BASE0 + 0x4020) /* Ring buf 2 base/write ptr */
-#define MSC_RBMMODE2 (MSC_BASE0 + 0x4028) /* Ring buf 2 mode/context */
-
-#define MSC_RBMRP0 (MSC_BASE0 + 0x5000) /* Ring buf 0 read pointer */
-#define MSC_RBMRP1 (MSC_BASE0 + 0x6000) /* Ring buf 1 read pointer */
-#define MSC_RBMRP2 (MSC_BASE0 + 0x7000) /* Ring buf 2 read pointer */
-
-/* locations of queues in virtual memory */
-#define MSC_QUEUE_BASE 0xfa800000
-#define MSC_PUT_QUEUE_S (MSC_QUEUE_BASE + 0*PAGE_SIZE)
-#define MSC_GET_QUEUE_S (MSC_QUEUE_BASE + 1*PAGE_SIZE)
-#define MSC_XYG_QUEUE_S (MSC_QUEUE_BASE + 2*PAGE_SIZE)
-#define MSC_SEND_QUEUE_S (MSC_QUEUE_BASE + 3*PAGE_SIZE)
-#define MSC_CPUT_QUEUE_S (MSC_QUEUE_BASE + 4*PAGE_SIZE)
-#define MSC_BSEND_QUEUE_S (MSC_QUEUE_BASE + 5*PAGE_SIZE)
-#define MSC_CXYG_QUEUE_S (MSC_QUEUE_BASE + 6*PAGE_SIZE)
-#define MSC_CGET_QUEUE_S (MSC_QUEUE_BASE + 7*PAGE_SIZE)
-
-/* the 4 interrupt ports - physical addresses (on bus 8) */
-#define MC_INTP_0 0x80004000
-#define MC_INTP_1 0x80005000
-#define MC_INTP_2 0x80006000
-#define MC_INTP_3 0x80007000
-
-/* the address used to send a remote signal - note that 32 pages
- are used here - none of them are mapped to anything though */
-#define MSC_REM_SIGNAL (MSC_QUEUE_BASE + 0x10 * PAGE_SIZE)
-
-#define MSC_PUT_QUEUE (MSC_QUEUE_BASE + 0x100*PAGE_SIZE)
-#define MSC_GET_QUEUE (MSC_QUEUE_BASE + 0x101*PAGE_SIZE)
-#define MSC_SEND_QUEUE (MSC_QUEUE_BASE + 0x102*PAGE_SIZE)
-#define MSC_XY_QUEUE (MSC_QUEUE_BASE + 0x103*PAGE_SIZE)
-#define MSC_X_QUEUE (MSC_QUEUE_BASE + 0x104*PAGE_SIZE)
-#define MSC_Y_QUEUE (MSC_QUEUE_BASE + 0x105*PAGE_SIZE)
-#define MSC_XYG_QUEUE (MSC_QUEUE_BASE + 0x106*PAGE_SIZE)
-#define MSC_XG_QUEUE (MSC_QUEUE_BASE + 0x107*PAGE_SIZE)
-#define MSC_YG_QUEUE (MSC_QUEUE_BASE + 0x108*PAGE_SIZE)
-#define MSC_CSI_QUEUE (MSC_QUEUE_BASE + 0x109*PAGE_SIZE)
-#define MSC_FOP_QUEUE (MSC_QUEUE_BASE + 0x10a*PAGE_SIZE)
-
-#define SYSTEM_RINGBUF_BASE (MSC_QUEUE_BASE + 0x200*PAGE_SIZE)
-#define SYSTEM_RINGBUF_ORDER 5
-#define SYSTEM_RINGBUF_SIZE ((1<<SYSTEM_RINGBUF_ORDER)*PAGE_SIZE)
-
-#define MSC_SYSTEM_DIRECT (MSC_QUEUE_BASE + 0x700 * PAGE_SIZE)
-#define MSC_USER_DIRECT (MSC_QUEUE_BASE + 0x701 * PAGE_SIZE)
-#define MSC_REMOTE_DIRECT (MSC_QUEUE_BASE + 0x702 * PAGE_SIZE)
-#define MSC_REPLY_DIRECT (MSC_QUEUE_BASE + 0x703 * PAGE_SIZE)
-#define MSC_REMREPLY_DIRECT (MSC_QUEUE_BASE + 0x704 * PAGE_SIZE)
-
-#define MSC_SYSTEM_DIRECT_END (MSC_QUEUE_BASE + 0x708 * PAGE_SIZE)
-#define MSC_USER_DIRECT_END (MSC_QUEUE_BASE + 0x709 * PAGE_SIZE)
-#define MSC_REMOTE_DIRECT_END (MSC_QUEUE_BASE + 0x70a * PAGE_SIZE)
-#define MSC_REPLY_DIRECT_END (MSC_QUEUE_BASE + 0x70b * PAGE_SIZE)
-#define MSC_REMREPLY_DIRECT_END (MSC_QUEUE_BASE + 0x70c * PAGE_SIZE)
-
-/* AP1000+ Memory Controller (MC+) */
-
-#define MC_BASE0 0xfa000000
-
-#define MC_DRAM_CTRL (MC_BASE0 + 0x0) /* DRAM control */
-#define MC_DRAM_CHKBIT (MC_BASE0 + 0x8) /* DRAM check bits */
-#define MC_DRAM_ERRADR (MC_BASE0 + 0x10) /* DRAM error address */
-#define MC_DRAM_ERRSYN (MC_BASE0 + 0x18) /* DRAM error syndrome */
-
-#define MC_FREERUN (MC_BASE0 + 0x20) /* Free run ctr (12.5MHz) */
-#define MC_ITIMER0 (MC_BASE0 + 0x28) /* Interval timer 0 */
-#define MC_ITIMER1 (MC_BASE0 + 0x30) /* Interval timer 1 */
-
-#define MC_INTR (MC_BASE0 + 0x38) /* Interrupt control/status */
-
-/* Interrupt control/status fields in MC_INTR */
-#define MC_INTR_ECCD_SH 12 /* ECC double (uncorr.) err */
-#define MC_INTR_ECCS_SH 8 /* ECC single (corr.) error */
-#define MC_INTR_ITIM1_SH 4 /* Interval timer 1 intr */
-#define MC_INTR_ITIM0_SH 0 /* Interval timer 0 intr */
-
-#define MC_CTP (MC_BASE0 + 0x50) /* Context table pointer */
-
-#define MC_VBUS_FAST (MC_BASE0 + 0x60) /* VBus fast data mode ctrl */
-
-#define MC_INTR_PORT (MC_BASE0 + 0x68) /* Interrupt port ctrl/stat */
-
-/* Interrupt control/status fields in MC_INTR_PORT */
-#define MC_INTP_3_SH 12 /* port 0 (880007000) */
-#define MC_INTP_2_SH 8 /* port 1 (880006000) */
-#define MC_INTP_1_SH 4 /* port 1 (880005000) */
-#define MC_INTP_0_SH 0 /* port 1 (880004000) */
-
-#define MC_PAC_COUNT (MC_BASE0 + 0x1000) /* Perf. an. counters */
-#define MC_PAC_SELECT (MC_BASE0 + 0x1008) /* Perf. an. ctr. select */
-
-#define MC_VERSION (MC_BASE0 + 0x3000) /* MC+ version/date */
-
-#define MC_MMU_TLB4K (MC_BASE0 + 0x6000) /* MC+ TLB for 4k pages */
-#define MC_MMU_TLB256K (MC_BASE0 + 0x7000) /* MC+ TLB for 256k pages */
-#define MC_MMU_TLB4K_SIZE 256
-#define MC_MMU_TLB256K_SIZE 64
-
-
-/*
- * Bit values for a standard AP1000 3-bit interrupt control/status field.
- */
-#define AP_INTR_REQ 1 /* interrupt request bit */
-#define AP_INTR_MASK 2 /* interrupt mask bit (1 disables) */
-#define AP_INTR_WENABLE 4 /* enable write to mask/req bits */
-#define AP_CLR_INTR_REQ 4 /* clear req. bit (dismiss intr) */
-#define AP_CLR_INTR_MASK 5 /* clear mask bit (enable ints) */
-#define AP_SET_INTR_REQ 6 /* set request bit */
-#define AP_SET_INTR_MASK 7 /* set mask bit (disable ints) */
-
-/*
- * Bit field extraction/insertion macros.
- */
-#define EXTFIELD(val, fld) (((val) >> fld ## _SH) & fld ## _M)
-#define MKFIELD(val, fld) (((val) & fld ## _M) << fld ## _SH)
-#define INSFIELD(dst, val, fld) (((dst) & ~(fld ## _M << fld ## _SH)) \
- | MKFIELD(val, fld))
-
-/*
- * RTC registers
- */
-#define RTC 0xfff10000 /* RTC system mode */
-#define RTC_CSR (RTC+0x0010) /* RTC control register */
-#define RTC_STR (RTC+0x0020) /* RTC status register */
-#define RTC_ITRR (RTC+0x0030) /* RTC interrupt register */
-#define RTC_RSTR (RTC+0x0070) /* RTC reset register */
-#define RTC_RSTR_TR 0x00008000 /* RTC through mode */
-#define RTC_RSTR_TS 0x00004000 /* RTC test mode */
-#define RTC_RSTR_ED 0x00002000 /* RTC reverse mode */
-#define RTC_RSTR_AC 0x00001000 /* RTC long mode */
-#define RTC_RSTR_SN 0x00000800 /* SOUTH/NORTH direction */
-#define RTC_RSTR_EW 0x00000400 /* EAST/WEST direction */
-#define RTC_RSTR_NC 0x00000200 /* get NORTH channel */
-#define RTC_RSTR_SC 0x00000100 /* get SOUTH channel */
-#define RTC_RSTR_WC 0x00000080 /* get WEST channel */
-#define RTC_RSTR_EC 0x00000040 /* get EAST channel */
-#define RTC_RSTR_BM 0x00000020 /* broad also my cell */
-#define RTC_RSTR_RT 0x00000020 /* reset */
-
-
-#define RTC_ITRR_PA 0x00040000 /* parity error for LBUS */
-#define RTC_ITRR_LR 0x00020000 /* MSC read but FIFO is empty*/
-#define RTC_ITRR_LW 0x00010000 /* MSC write but FIFO is full*/
-#define RTC_ITRR_AL 0x00008000 /* specify end data in data transfer */
-#define RTC_ITRR_DN 0x00002000 /* parity error in NORTH channel */
-#define RTC_ITRR_DS 0x00001000 /* parity error in SOUTH channel */
-#define RTC_ITRR_DW 0x00000800 /* parity error in WEST channel */
-#define RTC_ITRR_DE 0x00000400 /* parity error in EAST channel */
-#define RTC_ITRR_BD 0x00000200 /* receive 2 kind of broad data */
-#define RTC_ITRR_EW 0x00000100 /* control to write error bits */
-#define RTC_ITRR_EM 0x00000080 /* mask error interrupt request */
-#define RTC_ITRR_ER 0x00000040 /* error interrput request */
-#define RTC_ITRR_SW 0x00000020 /* control to write SR, SM */
-#define RTC_ITRR_SM 0x00000010 /* mask send interrupt */
-#define RTC_ITRR_SR 0x00000008 /* send interrupt request */
-#define RTC_ITRR_RW 0x00000004 /* icontrol to read RR, RM */
-#define RTC_ITRR_RM 0x00000002 /* mask read interrupt */
-#define RTC_ITRR_RR 0x00000001 /* receive interrupt request */
-
-#define RTC_ITRR_RWM (RTC_ITRR_RW|RTC_ITRR_RM)
-#define RTC_ITRR_SWM (RTC_ITRR_SW|RTC_ITRR_SM)
-#define RTC_ITRR_EWM (RTC_ITRR_EW|RTC_ITRR_EM)
-#define RTC_ITRR_RWR (RTC_ITRR_RW|RTC_ITRR_RR)
-#define RTC_ITRR_SWR (RTC_ITRR_SW|RTC_ITRR_SR)
-#define RTC_ITRR_EWR (RTC_ITRR_EW|RTC_ITRR_ER)
-#define RTC_ITRR_RRM (RTC_ITRR_RM|RTC_ITRR_RR)
-#define RTC_ITRR_SRM (RTC_ITRR_SM|RTC_ITRR_SR)
-#define RTC_ITRR_ERM (RTC_ITRR_EM|RTC_ITRR_ER)
-#define RTC_ITRR_RWMR (RTC_ITRR_RW|RTC_ITRR_RM|RTC_ITRR_RR)
-#define RTC_ITRR_SWMR (RTC_ITRR_SW|RTC_ITRR_SM|RTC_ITRR_SR)
-#define RTC_ITRR_EWMR (RTC_ITRR_EW|RTC_ITRR_EM|RTC_ITRR_ER)
-
-#define RTC_ITRR_ALLMSK (RTC_ITRR_RWM|RTC_ITRR_SWM|RTC_ITRR_EWM)
-#define RTC_ITRR_ALLCLR (RTC_ITRR_RW|RTC_ITRR_SW|RTC_ITRR_EW)
-#define RTC_ITRR_ALLWR (RTC_ITRR_RWMR|RTC_ITRR_SWMR|RTC_ITRR_EWMR)
-#define RTC_ITRR_ALLRD (RTC_ITRR_RRM|RTC_ITRR_SRM|RTC_ITRR_ERM)
-
-
-/*
- * macros to manipulate context/task/pid numbers for parallel programs
- */
-#define MPP_CONTEXT_BASE (AP_NUM_CONTEXTS - (NR_TASKS - MPP_TASK_BASE))
-#define MPP_TASK_TO_CTX(taskid) (((taskid) - MPP_TASK_BASE)+MPP_CONTEXT_BASE)
-#define MPP_CTX_TO_TASK(ctx) (((ctx)-MPP_CONTEXT_BASE)+MPP_TASK_BASE)
-#define MPP_IS_PAR_TASK(taskid) ((taskid) >= MPP_TASK_BASE)
-#define MPP_IS_PAR_CTX(ctx) ((ctx) >= MPP_CONTEXT_BASE)
-
-
-/*
- * ioctls available on the ring buffer
- */
-#define CAP_GETINIT 1
-#define CAP_SYNC 2
-#define CAP_SETTASK 3
-#define CAP_SETGANG 4
-#define CAP_MAP 5
-
-/*
- * the structure shared by the kernel and the parallel tasks in the
- * front of the cap_shared area
- */
-#ifndef _ASM_
-#ifdef _APLIB_
-struct _kernel_cap_shared {
- unsigned rbuf_read_ptr;
- unsigned dummy[32]; /* for future expansion */
-};
-#endif
-#endif
-
-/*
- * the mmap'd ringbuffer region is layed out like this:
-
- shared page - one page
- queue pages - 11 pages
- ring buffer - xx pages
- mirror of ring buffer - xx pages
- */
-#define RBUF_VBASE 0xd0000000
-#define RBUF_SHARED_PAGE_OFF 0
-#define RBUF_PUT_QUEUE PAGE_SIZE
-#define RBUF_GET_QUEUE 2*PAGE_SIZE
-#define RBUF_SEND_QUEUE 3*PAGE_SIZE
-#define RBUF_XY_QUEUE 4*PAGE_SIZE
-#define RBUF_X_QUEUE 5*PAGE_SIZE
-#define RBUF_Y_QUEUE 6*PAGE_SIZE
-#define RBUF_XYG_QUEUE 7*PAGE_SIZE
-#define RBUF_XG_QUEUE 8*PAGE_SIZE
-#define RBUF_YG_QUEUE 9*PAGE_SIZE
-#define RBUF_CSI_QUEUE 10*PAGE_SIZE
-#define RBUF_FOP_QUEUE 11*PAGE_SIZE
-#define RBUF_RING_BUFFER_OFFSET 15*PAGE_SIZE
-
-
-/*
- * number of MMU contexts to use
- */
-#define AP_NUM_CONTEXTS 1024
-#define SYSTEM_CONTEXT 1
-
-/*
- * the default gang scheduling factor
-*/
-#define DEF_GANG_FACTOR 15
-
-/*
- * useful for bypassing the cache
-*/
-#ifdef _APLIB_
-#ifndef _ASM_
-static inline unsigned long phys_8_in(unsigned long paddr)
-{
- unsigned long word;
- __asm__ __volatile__("lda [%1] %2, %0\n\t" :
- "=r" (word) :
- "r" (paddr), "i" (0x28) :
- "memory");
- return word;
-}
-
-/*
- * useful for bypassing the cache
-*/
-static inline unsigned long phys_9_in(unsigned long paddr)
-{
- unsigned long word;
- __asm__ __volatile__("lda [%1] %2, %0\n\t" :
- "=r" (word) :
- "r" (paddr), "i" (0x29) :
- "memory");
- return word;
-}
-#endif
-#endif
-
-/*
- * DDV definitions
-*/
-#define OBASE (0xfff40010)
-#define OPTION_BASE 0xfc000000
-#define _OPIBUS_BASE (OPTION_BASE + 0x800000)
-#ifdef CAP2_OPTION
-#define OPIBUS_BASE 0
-#else
-#define OPIBUS_BASE _OPIBUS_BASE
-#endif
-#define PBUF0 (OPIBUS_BASE+0x7e0080)
-#define PBUF1 (OPIBUS_BASE+0x7e0084)
-#define PBUF2 (OPIBUS_BASE+0x7e0088)
-#define PBUF3 (OPIBUS_BASE+0x7e008c)
-#define PIRQ (OPIBUS_BASE+0x7e0090)
-#define PRST (OPIBUS_BASE+0x7e0094)
-
-#define IRC0 (OPIBUS_BASE+0x7d00a0)
-#define IRC1 (OPIBUS_BASE+0x7d00a4)
-
-#define PRST_IRST (0x00000001)
-
-#define OPIU_RESET (0x00000000)
-#define OPIU_OP (PBUF0)
-
-#define LSTR(s) (_OPIBUS_BASE + (s))
-
-#endif /* _AP1000_APREG_H */
-
diff --git a/include/asm-sparc/ap1000/apservice.h b/include/asm-sparc/ap1000/apservice.h
deleted file mode 100644
index 902e774d6..000000000
--- a/include/asm-sparc/ap1000/apservice.h
+++ /dev/null
@@ -1,111 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/* this defines service requests that can be made by the cells of the
- front end "bootap" server
-
- tridge, March 1996
- */
-#ifndef _APSERVICE_H
-#define _APSERVICE_H
-#ifdef __KERNEL__
-#include <linux/sched.h>
-#endif
-
-#ifndef _ASM_
-
-/* all requests start with this structure */
-struct cap_request {
- unsigned header; /* for the hardware */
- int size; /* the total request size in bytes, including this header */
- int cid; /* the cell it came from */
- int type; /* the type of request */
- int data[4]; /* misc data */
-};
-
-/* Initialisation data to be sent to boot cell program */
-struct cap_init {
- int bootcid; /* base cid to boot */
- int numcells; /* number of cells */
- int physcells; /* physical number of cells */
- unsigned long baseIP; /* IP address of cell 0 */
- unsigned long netmask; /* netmask of cells net */
- int gdbcell; /* what cell is the debugger running on */
- unsigned init_time; /* time at startup */
-};
-#endif
-
-/* what fake host number to use for the aliased IP device */
-#define AP_ALIAS_IP 2
-
-/* request types */
-#define REQ_WRITE 0
-#define REQ_SHUTDOWN 1
-#define REQ_LOAD_AOUT 2
-#define REQ_PUTCHAR 3
-#define REQ_GETBOOTARGS 4
-#define REQ_PUTDEBUGCHAR 5
-#define REQ_GETDEBUGCHAR 6
-#define REQ_OPENNET 7
-#define REQ_IP 8
-#define REQ_BREAK 9
-#define REQ_INIT 10
-#define REQ_PUTDEBUGSTRING 11
-#define REQ_BREAD 12
-#define REQ_BWRITE 13
-#define REQ_BOPEN 14
-#define REQ_BCLOSE 15
-#define REQ_DDVOPEN 16
-#define REQ_BIF_TOKEN 17
-#define REQ_KILL 18
-#define REQ_SCHEDULE 19
-
-/* the bit used to indicate that the host wants the BIF */
-#define HOST_STATUS_BIT 2
-
-#ifdef __KERNEL__
-/* some prototypes */
-extern int ap_dma_wait(int ch);
-extern int ap_dma_go(unsigned long ch,unsigned int p,int size,unsigned long cmd);
-extern int mpp_cid(void);
-extern void ap_start_debugger(void);
-extern int bif_queue(struct cap_request *req,char *buf,int bufsize);
-extern void write_bif_polled(char *buf1,int len1,char *buf2,int len2);
-extern void read_bif(char *buf,int size);
-extern void ap_wait_request(struct cap_request *req,int type);
-extern void bif_set_poll(int set);
-extern void ap_led(unsigned char d);
-extern void ap_xor_led(unsigned char d);
-extern void ap_set_led(unsigned char d);
-extern void ap_unset_led(unsigned char d);
-extern void bif_toss(int size);
-void ap_msc_init(void);
-void mac_dma_complete(void);
-void ap_dbg_flush(void);
-void bif_queue_flush(void);
-/* void ap_printk(char *msg,int a1,int a2,int a3,int a4,int a5); */
-void show_mapping_ctx(unsigned *ctp,int context,unsigned Vm);
-void async_fault(unsigned long address, int write, int taskid,
- void (*callback)(int,unsigned long,int,int));
-void ap_bif_init(void);
-void ap_tnet_init(void);
-int wait_on_int(volatile int *p,int x,int interval);
-void ap_put(int dest_cell,u_long local_addr,int size,
- u_long remote_addr,u_long dest_flag,u_long local_flag);
-void ap_bput(u_long local_addr,int size,
- u_long remote_addr,u_long dest_flag,u_long local_flag);
-void msc_switch_check(struct task_struct *tsk);
-int bif_queue_nocopy(struct cap_request *req,char *buf,int bufsize);
-void mpp_set_gang_factor(int factor);
-void bif_register_request(int type,void (*fn)(struct cap_request *));
-void bif_add_debug_key(char key,void (*fn)(void),char *description);
-void ap_complete(struct cap_request *creq);
-void ap_reboot(char *bootstr);
-#endif
-
-
-#endif /* _APSERVICE_H */
diff --git a/include/asm-sparc/ap1000/pgtapmmu.h b/include/asm-sparc/ap1000/pgtapmmu.h
deleted file mode 100644
index 9e238db45..000000000
--- a/include/asm-sparc/ap1000/pgtapmmu.h
+++ /dev/null
@@ -1,141 +0,0 @@
- /*
- * Copyright 1996 The Australian National University.
- * Copyright 1996 Fujitsu Laboratories Limited
- *
- * This software may be distributed under the terms of the Gnu
- * Public License version 2 or later
- */
-/*
- * based on pgtsrmmu.h
- *
- */
-
-#ifndef _SPARC_PGTAPMMU_H
-#define _SPARC_PGTAPMMU_H
-
-#include <asm/page.h>
-#include <asm/ap1000/apreg.h>
-
-
-/* PMD_SHIFT determines the size of the area a second-level page table can map */
-#define APMMU_PMD_SHIFT 18
-#define APMMU_PMD_SIZE (1UL << APMMU_PMD_SHIFT)
-#define APMMU_PMD_MASK (~(APMMU_PMD_SIZE-1))
-#define APMMU_PMD_ALIGN(addr) (((addr)+APMMU_PMD_SIZE-1)&APMMU_PMD_MASK)
-
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
-#define APMMU_PGDIR_SHIFT 24
-#define APMMU_PGDIR_SIZE (1UL << APMMU_PGDIR_SHIFT)
-#define APMMU_PGDIR_MASK (~(APMMU_PGDIR_SIZE-1))
-#define APMMU_PGDIR_ALIGN(addr) (((addr)+APMMU_PGDIR_SIZE-1)&APMMU_PGDIR_MASK)
-
-#define APMMU_PTRS_PER_PTE 64
-#define APMMU_PTRS_PER_PMD 64
-#define APMMU_PTRS_PER_PGD 256
-
-#define APMMU_PTE_TABLE_SIZE 0x100 /* 64 entries, 4 bytes a piece */
-#define APMMU_PMD_TABLE_SIZE 0x100 /* 64 entries, 4 bytes a piece */
-#define APMMU_PGD_TABLE_SIZE 0x400 /* 256 entries, 4 bytes a piece */
-
-#define APMMU_VMALLOC_START (0xfe300000)
-#define APMMU_VMALLOC_END ~0x0UL
-
-/* Definition of the values in the ET field of PTD's and PTE's */
-#define APMMU_ET_MASK 0x3
-#define APMMU_ET_INVALID 0x0
-#define APMMU_ET_PTD 0x1
-#define APMMU_ET_PTE 0x2
-#define APMMU_ET_REPTE 0x3 /* AIEEE, SuperSparc II reverse endian page! */
-
-/* Physical page extraction from PTP's and PTE's. */
-#define APMMU_CTX_PMASK 0xfffffff0
-#define APMMU_PTD_PMASK 0xfffffff0
-#define APMMU_PTE_PMASK 0xffffff00
-
-/* The pte non-page bits. Some notes:
- * 1) cache, dirty, valid, and ref are frobbable
- * for both supervisor and user pages.
- * 2) exec and write will only give the desired effect
- * on user pages
- * 3) use priv and priv_readonly for changing the
- * characteristics of supervisor ptes
- */
-#define APMMU_CACHE 0x80
-#define APMMU_DIRTY 0x40
-#define APMMU_REF 0x20
-#define APMMU_EXEC 0x08
-#define APMMU_WRITE 0x04
-#define APMMU_VALID 0x02 /* APMMU_ET_PTE */
-#define APMMU_PRIV 0x1c
-#define APMMU_PRIV_RDONLY 0x18
-
-#define APMMU_CHG_MASK (0xffffff00 | APMMU_REF | APMMU_DIRTY)
-
-/*
- * "normal" sun systems have their memory on bus 0. This means the top
- * 4 bits of 36 bit physical addresses are 0. We use this define to
- * determine if a piece of memory might be normal memory, or if its
- * definately some sort of device memory.
- *
- * On the AP+ normal memory is on bus 8. Why? Ask Fujitsu :-)
-*/
-#define MEM_BUS_SPACE 8
-
-/* Some day I will implement true fine grained access bits for
- * user pages because the APMMU gives us the capabilities to
- * enforce all the protection levels that vma's can have.
- * XXX But for now...
- */
-#define APMMU_PAGE_NONE __pgprot((MEM_BUS_SPACE<<28) | \
- APMMU_VALID | APMMU_CACHE | \
- APMMU_PRIV | APMMU_REF)
-#define APMMU_PAGE_SHARED __pgprot((MEM_BUS_SPACE<<28) | \
- APMMU_VALID | APMMU_CACHE | \
- APMMU_EXEC | APMMU_WRITE | APMMU_REF)
-#define APMMU_PAGE_COPY __pgprot((MEM_BUS_SPACE<<28) | \
- APMMU_VALID | APMMU_CACHE | \
- APMMU_EXEC | APMMU_REF)
-#define APMMU_PAGE_RDONLY __pgprot((MEM_BUS_SPACE<<28) | \
- APMMU_VALID | APMMU_CACHE | \
- APMMU_EXEC | APMMU_REF)
-#define APMMU_PAGE_KERNEL __pgprot((MEM_BUS_SPACE<<28) | \
- APMMU_VALID | APMMU_CACHE | APMMU_PRIV | \
- APMMU_DIRTY | APMMU_REF)
-
-#define APMMU_CTXTBL_PTR 0x00000100
-#define APMMU_CTX_REG 0x00000200
-
-extern __inline__ unsigned long apmmu_get_ctable_ptr(void)
-{
- unsigned int retval;
-
- __asm__ __volatile__("lda [%1] %2, %0\n\t" :
- "=r" (retval) :
- "r" (APMMU_CTXTBL_PTR),
- "i" (ASI_M_MMUREGS));
- return (retval & APMMU_CTX_PMASK) << 4;
-}
-
-extern __inline__ void apmmu_set_context(int context)
-{
- __asm__ __volatile__("sta %0, [%1] %2\n\t" : :
- "r" (context), "r" (APMMU_CTX_REG),
- "i" (ASI_M_MMUREGS) : "memory");
- /* The AP1000+ message controller also needs to know
- the current task's context. */
- MSC_OUT(MSC_PID, context);
-}
-
-extern __inline__ int apmmu_get_context(void)
-{
- register int retval;
- __asm__ __volatile__("lda [%1] %2, %0\n\t" :
- "=r" (retval) :
- "r" (APMMU_CTX_REG),
- "i" (ASI_M_MMUREGS));
- return retval;
-}
-
-#endif /* !(_SPARC_PGTAPMMU_H) */
-
-
diff --git a/include/asm-sparc/checksum.h b/include/asm-sparc/checksum.h
index 625ff3bda..00324fc79 100644
--- a/include/asm-sparc/checksum.h
+++ b/include/asm-sparc/checksum.h
@@ -1,4 +1,4 @@
-/* $Id: checksum.h,v 1.30 2000/01/05 21:27:39 davem Exp $ */
+/* $Id: checksum.h,v 1.31 2000/01/31 01:26:52 davem Exp $ */
#ifndef __SPARC_CHECKSUM_H
#define __SPARC_CHECKSUM_H
@@ -210,7 +210,7 @@ static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
struct in6_addr *daddr,
- __u16 len,
+ __u32 len,
unsigned short proto,
unsigned int sum)
{
@@ -237,7 +237,7 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
"
: "=&r" (sum)
: "r" (saddr), "r" (daddr),
- "r"(htonl((__u32) (len))), "r"(htonl(proto)), "r"(sum)
+ "r"(htonl(len)), "r"(htonl(proto)), "r"(sum)
: "g2", "g3", "g4", "cc");
return csum_fold(sum);
diff --git a/include/asm-sparc/ethtool.h b/include/asm-sparc/ethtool.h
index bea36b6c6..572db24fb 100644
--- a/include/asm-sparc/ethtool.h
+++ b/include/asm-sparc/ethtool.h
@@ -1,7 +1,7 @@
-/* $Id: ethtool.h,v 1.1 1998/12/19 15:09:38 davem Exp $
+/* $Id: ethtool.h,v 1.2 2000/01/31 04:59:17 davem Exp $
* ethtool.h: Defines for SparcLinux ethtool.
*
- * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1998 David S. Miller (davem@redhat.com)
*/
#ifndef _SPARC_ETHTOOL_H
diff --git a/include/asm-sparc/page.h b/include/asm-sparc/page.h
index 352590e2e..344640811 100644
--- a/include/asm-sparc/page.h
+++ b/include/asm-sparc/page.h
@@ -1,4 +1,4 @@
-/* $Id: page.h,v 1.46 2000/01/08 16:38:22 anton Exp $
+/* $Id: page.h,v 1.47 2000/01/29 00:41:49 anton Exp $
* page.h: Various defines and such for MMU operations on the Sparc for
* the Linux kernel.
*
@@ -93,132 +93,6 @@ typedef struct { unsigned long iopgprot; } iopgprot_t;
#define __pgprot(x) ((pgprot_t) { (x) } )
#define __iopgprot(x) ((iopgprot_t) { (x) } )
-#elif CONFIG_AP1000_DEBUG
-
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long iopte; } iopte_t;
-typedef struct { unsigned long pmd; } pmd_t;
-typedef struct { unsigned long pgd; } pgd_t;
-typedef struct { unsigned long ctxd; } ctxd_t;
-typedef struct { unsigned long pgprot; } pgprot_t;
-typedef struct { unsigned long iopgprot; } iopgprot_t;
-
-static inline unsigned long __get_val(unsigned long x)
-{
- if ((x & 0xF0000000) == (8<<28))
- return x & 0x0FFFFFFF;
- return x;
-}
-
-static inline unsigned long __set_val(unsigned long x)
-{
- if ((x & 0xF0000000) == (0<<28))
- return x | 0x80000000;
- return x;
-}
-
-#define __pte_val(x) ((x).pte)
-#define __iopte_val(x) ((x).iopte)
-#define __pmd_val(x) ((x).pmd)
-#define __pgd_val(x) ((x).pgd)
-#define __ctxd_val(x) ((x).ctxd)
-#define __pgprot_val(x) ((x).pgprot)
-#define __iopgprot_val(x) ((x).iopgprot)
-
-#define ___pte(x) ((pte_t) { (x) } )
-#define ___iopte(x) ((iopte_t) { (x) } )
-#define ___pmd(x) ((pmd_t) { (x) } )
-#define ___pgd(x) ((pgd_t) { (x) } )
-#define ___ctxd(x) ((ctxd_t) { (x) } )
-#define ___pgprot(x) ((pgprot_t) { (x) } )
-#define ___iopgprot(x) ((iopgprot_t) { (x) } )
-
-
-#define pte_val(x) __get_val(__pte_val(x))
-#define iopte_val(x) __get_val(__iopte_val(x))
-#define pmd_val(x) __get_val(__pmd_val(x))
-#define pgd_val(x) __get_val(__pgd_val(x))
-#define ctxd_val(x) __get_val(__ctxd_val(x))
-#define pgprot_val(x) __get_val(__pgprot_val(x))
-#define iopgprot_val(x) __get_val(__iopgprot_val(x))
-
-#define __pte(x) ___pte(__set_val(x))
-#define __iopte(x) ___iopte(__set_val(x))
-#define __pmd(x) ___pmd(__set_val(x))
-#define __pgd(x) ___pgd(__set_val(x))
-#define __ctxd(x) ___ctxd(__set_val(x))
-#define __pgprot(x) ___pgprot(x)
-#define __iopgprot(x) ___iopgprot(__set_val(x))
-
-#elif CONFIG_AP1000
-
-typedef unsigned long pte_t;
-typedef unsigned long iopte_t;
-typedef unsigned long pmd_t;
-typedef unsigned long pgd_t;
-typedef unsigned long ctxd_t;
-typedef unsigned long pgprot_t;
-typedef unsigned long iopgprot_t;
-
-static inline unsigned long __get_val(unsigned long x)
-{
-#if 0
- extern void ap_panic(char *fmt,...);
- if (x && (x & 0xF0000000) == 0) {
- ap_panic("get_val got 0x%x\n",x);
- }
-#endif
- if ((x & 0xF0000000) == (8<<28))
- return x & 0x0FFFFFFF;
- return x;
-}
-
-static inline unsigned long __set_val(unsigned long x)
-{
-#if 0
- extern void ap_panic(char *fmt,...);
- if ((x & 0xF0000000) == (8<<28)) {
- ap_panic("set_val got 0x%x\n",x);
- }
-#endif
- if ((x & 0xF0000000) == (0<<28))
- return x | 0x80000000;
- return x;
-}
-
-#define __pte_val(x) (x)
-#define __iopte_val(x) (x)
-#define __pmd_val(x) (x)
-#define __pgd_val(x) (x)
-#define __ctxd_val(x) (x)
-#define __pgprot_val(x) (x)
-#define __iopgprot_val(x) (x)
-
-#define ___pte(x) ((pte_t) { (x) } )
-#define ___iopte(x) ((iopte_t) { (x) } )
-#define ___pmd(x) ((pmd_t) { (x) } )
-#define ___pgd(x) ((pgd_t) { (x) } )
-#define ___ctxd(x) ((ctxd_t) { (x) } )
-#define ___pgprot(x) ((pgprot_t) { (x) } )
-#define ___iopgprot(x) ((iopgprot_t) { (x) } )
-
-
-#define pte_val(x) __get_val(__pte_val(x))
-#define iopte_val(x) __get_val(__iopte_val(x))
-#define pmd_val(x) __get_val(__pmd_val(x))
-#define pgd_val(x) __get_val(__pgd_val(x))
-#define ctxd_val(x) __get_val(__ctxd_val(x))
-#define pgprot_val(x) __get_val(__pgprot_val(x))
-#define iopgprot_val(x) __get_val(__iopgprot_val(x))
-
-#define __pte(x) ___pte(__set_val(x))
-#define __iopte(x) ___iopte(__set_val(x))
-#define __pmd(x) ___pmd(__set_val(x))
-#define __pgd(x) ___pgd(__set_val(x))
-#define __ctxd(x) ___ctxd(__set_val(x))
-#define __pgprot(x) ___pgprot(x)
-#define __iopgprot(x) ___iopgprot(__set_val(x))
-
#else
/*
* .. while these make it easier on the compiler
diff --git a/include/asm-sparc/sbus.h b/include/asm-sparc/sbus.h
index c96b5660e..b7f2b8f9e 100644
--- a/include/asm-sparc/sbus.h
+++ b/include/asm-sparc/sbus.h
@@ -1,4 +1,4 @@
-/* $Id: sbus.h,v 1.20 1999/12/27 06:37:17 anton Exp $
+/* $Id: sbus.h,v 1.21 2000/01/28 13:43:11 jj Exp $
* sbus.h: Defines for the Sun SBus.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
diff --git a/include/asm-sparc/scatterlist.h b/include/asm-sparc/scatterlist.h
index e5776df9b..02e420275 100644
--- a/include/asm-sparc/scatterlist.h
+++ b/include/asm-sparc/scatterlist.h
@@ -1,4 +1,4 @@
-/* $Id: scatterlist.h,v 1.4 1999/12/27 06:37:20 anton Exp $ */
+/* $Id: scatterlist.h,v 1.5 2000/01/29 16:27:07 jj Exp $ */
#ifndef _SPARC_SCATTERLIST_H
#define _SPARC_SCATTERLIST_H
@@ -14,6 +14,9 @@ struct scatterlist {
__u32 dvma_length;
};
+#define sg_dma_address(sg) ((sg)->dvma_address)
+#define sg_dma_len(sg) ((sg)->dvma_length)
+
#define ISA_DMA_THRESHOLD (~0UL)
#endif /* !(_SPARC_SCATTERLIST_H) */
diff --git a/include/asm-sparc/siginfo.h b/include/asm-sparc/siginfo.h
index 480126b38..9d82eee87 100644
--- a/include/asm-sparc/siginfo.h
+++ b/include/asm-sparc/siginfo.h
@@ -1,4 +1,4 @@
-/* $Id: siginfo.h,v 1.6 2000/01/21 11:39:17 jj Exp $
+/* $Id: siginfo.h,v 1.7 2000/01/29 07:41:51 davem Exp $
* siginfo.c:
*/
diff --git a/include/asm-sparc/types.h b/include/asm-sparc/types.h
index b70210ba8..8a43339c1 100644
--- a/include/asm-sparc/types.h
+++ b/include/asm-sparc/types.h
@@ -1,4 +1,4 @@
-/* $Id: types.h,v 1.11 1997/12/22 13:28:22 mj Exp $ */
+/* $Id: types.h,v 1.12 2000/01/29 02:23:25 anton Exp $ */
#ifndef _SPARC_TYPES_H
#define _SPARC_TYPES_H
@@ -45,6 +45,8 @@ typedef unsigned long long u64;
#define BITS_PER_LONG 32
+typedef u32 dma_addr_t;
+
#endif /* __KERNEL__ */
#endif /* defined(_SPARC_TYPES_H) */
diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h
index c25741549..989c6742c 100644
--- a/include/asm-sparc/unistd.h
+++ b/include/asm-sparc/unistd.h
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.64 2000/01/16 06:20:32 davem Exp $ */
+/* $Id: unistd.h,v 1.66 2000/01/29 17:57:25 jj Exp $ */
#ifndef _SPARC_UNISTD_H
#define _SPARC_UNISTD_H
@@ -161,7 +161,7 @@
/* #define __NR_ni_syscall 143 ENOSYS under SunOS */
#define __NR_getrlimit 144 /* Common */
#define __NR_setrlimit 145 /* Common */
-/* #define __NR_killpg 146 SunOS Specific */
+#define __NR_pivot_root 146 /* Linux Specific, killpg under SunOS */
#define __NR_prctl 147 /* ENOSYS under SunOS */
#define __NR_pciconfig_read 148 /* ENOSYS under SunOS */
#define __NR_pciconfig_write 149 /* ENOSYS under SunOS */
diff --git a/include/asm-sparc64/checksum.h b/include/asm-sparc64/checksum.h
index b2c06823a..11748508e 100644
--- a/include/asm-sparc64/checksum.h
+++ b/include/asm-sparc64/checksum.h
@@ -1,4 +1,4 @@
-/* $Id: checksum.h,v 1.15 2000/01/19 04:06:09 davem Exp $ */
+/* $Id: checksum.h,v 1.16 2000/01/31 01:26:54 davem Exp $ */
#ifndef __SPARC64_CHECKSUM_H
#define __SPARC64_CHECKSUM_H
@@ -167,7 +167,7 @@ static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
struct in6_addr *daddr,
- __u16 len,
+ __u32 len,
unsigned short proto,
unsigned int sum)
{
@@ -192,7 +192,7 @@ static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
addccc %%g3, %%g7, %0
addc 0, %0, %0
" : "=&r" (sum)
- : "r" (saddr), "r" (daddr), "r"(htonl((__u32) (len))),
+ : "r" (saddr), "r" (daddr), "r"(htonl(len)),
"r"(htonl(proto)), "r"(sum)
: "g2", "g3", "g7", "cc");
diff --git a/include/asm-sparc64/dma.h b/include/asm-sparc64/dma.h
index 4f0b0baf2..fce01fcd2 100644
--- a/include/asm-sparc64/dma.h
+++ b/include/asm-sparc64/dma.h
@@ -1,4 +1,4 @@
-/* $Id: dma.h,v 1.18 1999/12/01 10:47:22 davem Exp $
+/* $Id: dma.h,v 1.19 2000/01/28 13:43:14 jj Exp $
* include/asm-sparc64/dma.h
*
* Copyright 1996 (C) David S. Miller (davem@caip.rutgers.edu)
diff --git a/include/asm-sparc64/ethtool.h b/include/asm-sparc64/ethtool.h
index b070ea1a4..18d86c3de 100644
--- a/include/asm-sparc64/ethtool.h
+++ b/include/asm-sparc64/ethtool.h
@@ -1,7 +1,7 @@
-/* $Id: ethtool.h,v 1.1 1998/12/19 15:09:40 davem Exp $
+/* $Id: ethtool.h,v 1.2 2000/01/31 04:59:19 davem Exp $
* ethtool.h: Defines for SparcLinux ethtool.
*
- * Copyright (C) 1998 David S. Miller (davem@dm.cobaltmicro.com)
+ * Copyright (C) 1998 David S. Miller (davem@redhat.com)
*/
#ifndef _SPARC64_ETHTOOL_H
diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h
index 3758686e2..fb65d46dc 100644
--- a/include/asm-sparc64/floppy.h
+++ b/include/asm-sparc64/floppy.h
@@ -1,4 +1,4 @@
-/* $Id: floppy.h,v 1.24 2000/01/09 15:16:34 ecd Exp $
+/* $Id: floppy.h,v 1.25 2000/01/28 13:43:14 jj Exp $
* asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
diff --git a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h
index 37a1e847b..cb7fba53f 100644
--- a/include/asm-sparc64/io.h
+++ b/include/asm-sparc64/io.h
@@ -1,4 +1,4 @@
-/* $Id: io.h,v 1.29 1999/12/20 04:58:42 davem Exp $ */
+/* $Id: io.h,v 1.30 2000/01/28 13:43:14 jj Exp $ */
#ifndef __SPARC64_IO_H
#define __SPARC64_IO_H
diff --git a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h
index 5184ba51a..259c755d5 100644
--- a/include/asm-sparc64/parport.h
+++ b/include/asm-sparc64/parport.h
@@ -1,4 +1,4 @@
-/* $Id: parport.h,v 1.6 2000/01/09 15:16:34 ecd Exp $
+/* $Id: parport.h,v 1.7 2000/01/28 13:43:14 jj Exp $
* parport.h: sparc64 specific parport initialization and dma.
*
* Copyright (C) 1999 Eddie C. Dost (ecd@skynet.be)
diff --git a/include/asm-sparc64/sbus.h b/include/asm-sparc64/sbus.h
index 1b0b5137a..f8c5e247f 100644
--- a/include/asm-sparc64/sbus.h
+++ b/include/asm-sparc64/sbus.h
@@ -1,4 +1,4 @@
-/* $Id: sbus.h,v 1.12 1999/12/20 14:08:25 jj Exp $
+/* $Id: sbus.h,v 1.13 2000/01/28 13:43:14 jj Exp $
* sbus.h: Defines for the Sun SBus.
*
* Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com)
diff --git a/include/asm-sparc64/types.h b/include/asm-sparc64/types.h
index f8e42235c..b1ccfc523 100644
--- a/include/asm-sparc64/types.h
+++ b/include/asm-sparc64/types.h
@@ -1,4 +1,4 @@
-/* $Id: types.h,v 1.2 1997/12/22 13:28:33 mj Exp $ */
+/* $Id: types.h,v 1.3 2000/01/28 13:43:15 jj Exp $ */
#ifndef _SPARC64_TYPES_H
#define _SPARC64_TYPES_H
diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h
index d1c874480..abf6c09eb 100644
--- a/include/asm-sparc64/unistd.h
+++ b/include/asm-sparc64/unistd.h
@@ -1,4 +1,4 @@
-/* $Id: unistd.h,v 1.40 2000/01/16 06:20:38 davem Exp $ */
+/* $Id: unistd.h,v 1.42 2000/01/29 17:57:26 jj Exp $ */
#ifndef _SPARC64_UNISTD_H
#define _SPARC64_UNISTD_H
@@ -161,7 +161,7 @@
/* #define __NR_ni_syscall 143 ENOSYS under SunOS */
#define __NR_getrlimit 144 /* Common */
#define __NR_setrlimit 145 /* Common */
-/* #define __NR_killpg 146 SunOS Specific */
+#define __NR_pivot_root 146 /* Linux Specific, killpg under SunOS */
#define __NR_prctl 147 /* ENOSYS under SunOS */
#define __NR_pciconfig_read 148 /* ENOSYS under SunOS */
#define __NR_pciconfig_write 149 /* ENOSYS under SunOS */
diff --git a/include/linux/agp_backend.h b/include/linux/agp_backend.h
index d2ae68864..eaa8bd1be 100644
--- a/include/linux/agp_backend.h
+++ b/include/linux/agp_backend.h
@@ -94,6 +94,7 @@ typedef struct _agp_memory {
unsigned long *memory;
off_t pg_start;
u32 type;
+ u32 physical;
u8 is_bound;
u8 is_flushed;
} agp_memory;
diff --git a/include/linux/agpgart.h b/include/linux/agpgart.h
index 86617386e..7457cd114 100644
--- a/include/linux/agpgart.h
+++ b/include/linux/agpgart.h
@@ -92,6 +92,10 @@ typedef struct _agp_allocate {
int key; /* tag of allocation */
size_t pg_count; /* number of pages */
__u32 type; /* 0 == normal, other devspec */
+ __u32 physical; /* device specific (some devices
+ * need a phys address of the
+ * actual page behind the gatt
+ * table) */
} agp_allocate;
typedef struct _agp_bind {
@@ -160,6 +164,10 @@ typedef struct _agp_allocate {
int key; /* tag of allocation */
size_t pg_count; /* number of pages */
u32 type; /* 0 == normal, other devspec */
+ u32 physical; /* device specific (some devices
+ * need a phys address of the
+ * actual page behind the gatt
+ * table) */
} agp_allocate;
typedef struct _agp_bind {
diff --git a/include/linux/auto_fs.h b/include/linux/auto_fs.h
index a8b313539..99f9784d3 100644
--- a/include/linux/auto_fs.h
+++ b/include/linux/auto_fs.h
@@ -20,8 +20,14 @@
#include <linux/ioctl.h>
#include <asm/types.h>
+/* This header file describes a range of autofs interface versions;
+ the new implementation ("autofs4") supports them all, but the old
+ implementation only supports v3. */
#define AUTOFS_MIN_PROTO_VERSION 3 /* Min version we support */
-#define AUTOFS_PROTO_VERSION 4 /* Current version */
+#define AUTOFS_MAX_PROTO_VERSION 4 /* Max (current) version */
+
+/* Backwards compat for autofs v3; it just implements a version */
+#define AUTOFS_PROTO_VERSION 3 /* v3 version */
/*
* Architectures where both 32- and 64-bit binaries can be executed
diff --git a/include/linux/i2c-dev.h b/include/linux/i2c-dev.h
index 7d52e52bc..7588f626b 100644
--- a/include/linux/i2c-dev.h
+++ b/include/linux/i2c-dev.h
@@ -19,7 +19,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* $Id: i2c-dev.h,v 1.3 1999/12/21 23:45:58 frodo Exp $ */
+/* $Id: i2c-dev.h,v 1.6 2000/01/24 21:56:58 frodo Exp $ */
#ifndef I2C_DEV_H
#define I2C_DEV_H
@@ -33,10 +33,10 @@
/* This is the structure as used in the I2C_SMBUS ioctl call */
struct i2c_smbus_ioctl_data {
- char read_write;
- __u8 command;
- int size;
- union i2c_smbus_data *data;
+ char read_write;
+ __u8 command;
+ int size;
+ union i2c_smbus_data *data;
};
#ifndef __KERNEL__
@@ -46,79 +46,83 @@ struct i2c_smbus_ioctl_data {
extern inline __s32 i2c_smbus_access(int file, char read_write, __u8 command,
int size, union i2c_smbus_data *data)
{
- struct i2c_smbus_ioctl_data args;
+ struct i2c_smbus_ioctl_data args;
- args.read_write = read_write;
- args.command = command;
- args.size = size;
- args.data = data;
- return ioctl(file,I2C_SMBUS,&args);
+ args.read_write = read_write;
+ args.command = command;
+ args.size = size;
+ args.data = data;
+ return ioctl(file,I2C_SMBUS,&args);
}
extern inline __s32 i2c_smbus_write_quick(int file, __u8 value)
{
- return i2c_smbus_access(file,value,0,I2C_SMBUS_QUICK,NULL);
+ return i2c_smbus_access(file,value,0,I2C_SMBUS_QUICK,NULL);
}
-
+
extern inline __s32 i2c_smbus_read_byte(int file)
{
- union i2c_smbus_data data;
- if (i2c_smbus_access(file,I2C_SMBUS_READ,0,I2C_SMBUS_BYTE,&data))
- return -1;
- else
- return 0x0FF & data.byte;
+ union i2c_smbus_data data;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,0,I2C_SMBUS_BYTE,&data))
+ return -1;
+ else
+ return 0x0FF & data.byte;
}
extern inline __s32 i2c_smbus_write_byte(int file, __u8 value)
{
- return i2c_smbus_access(file,I2C_SMBUS_WRITE,value, I2C_SMBUS_BYTE,NULL);
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,value,
+ I2C_SMBUS_BYTE,NULL);
}
extern inline __s32 i2c_smbus_read_byte_data(int file, __u8 command)
{
- union i2c_smbus_data data;
- if (i2c_smbus_access(file,I2C_SMBUS_READ,command,I2C_SMBUS_BYTE_DATA,&data))
- return -1;
- else
- return 0x0FF & data.byte;
+ union i2c_smbus_data data;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
+ I2C_SMBUS_BYTE_DATA,&data))
+ return -1;
+ else
+ return 0x0FF & data.byte;
}
extern inline __s32 i2c_smbus_write_byte_data(int file, __u8 command,
__u8 value)
{
- union i2c_smbus_data data;
- data.byte = value;
- return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,I2C_SMBUS_BYTE_DATA,
- &data);
+ union i2c_smbus_data data;
+ data.byte = value;
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_BYTE_DATA, &data);
}
extern inline __s32 i2c_smbus_read_word_data(int file, __u8 command)
{
- union i2c_smbus_data data;
- if (i2c_smbus_access(file,I2C_SMBUS_READ,command,I2C_SMBUS_WORD_DATA,&data))
- return -1;
- else
- return 0x0FFFF & data.word;
+ union i2c_smbus_data data;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
+ I2C_SMBUS_WORD_DATA,&data))
+ return -1;
+ else
+ return 0x0FFFF & data.word;
}
extern inline __s32 i2c_smbus_write_word_data(int file, __u8 command,
__u16 value)
{
- union i2c_smbus_data data;
- data.word = value;
- return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,I2C_SMBUS_WORD_DATA,
- &data);
+ union i2c_smbus_data data;
+ data.word = value;
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_WORD_DATA, &data);
}
extern inline __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value)
{
- union i2c_smbus_data data;
- data.word = value;
- if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command,I2C_SMBUS_PROC_CALL,&data))
- return -1;
- else
- return 0x0FFFF & data.word;
+ union i2c_smbus_data data;
+ data.word = value;
+ if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_PROC_CALL,&data))
+ return -1;
+ else
+ return 0x0FFFF & data.word;
}
@@ -126,29 +130,30 @@ extern inline __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value)
extern inline __s32 i2c_smbus_read_block_data(int file, __u8 command,
__u8 *values)
{
- union i2c_smbus_data data;
- int i;
- if (i2c_smbus_access(file,I2C_SMBUS_READ,command,I2C_SMBUS_BLOCK_DATA,&data))
- return -1;
- else {
- for (i = 1; i <= data.block[0]; i++)
- values[i-1] = data.block[i];
- return data.block[0];
- }
+ union i2c_smbus_data data;
+ int i;
+ if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
+ I2C_SMBUS_BLOCK_DATA,&data))
+ return -1;
+ else {
+ for (i = 1; i <= data.block[0]; i++)
+ values[i-1] = data.block[i];
+ return data.block[0];
+ }
}
extern inline __s32 i2c_smbus_write_block_data(int file, __u8 command,
__u8 length, __u8 *values)
{
- union i2c_smbus_data data;
- int i;
- if (length > 32)
- length = 32;
- for (i = 1; i <= length; i++)
- data.block[i] = values[i-1];
- data.block[0] = length;
- return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,I2C_SMBUS_BLOCK_DATA,
- &data);
+ union i2c_smbus_data data;
+ int i;
+ if (length > 32)
+ length = 32;
+ for (i = 1; i <= length; i++)
+ data.block[i] = values[i-1];
+ data.block[0] = length;
+ return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
+ I2C_SMBUS_BLOCK_DATA, &data);
}
#endif /* ndef __KERNEL__ */
diff --git a/include/linux/i2c-elektor.h b/include/linux/i2c-elektor.h
index e10311f22..f2d8155b2 100644
--- a/include/linux/i2c-elektor.h
+++ b/include/linux/i2c-elektor.h
@@ -22,7 +22,7 @@
/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
Frodo Looijaard <frodol@dds.nl> */
-/* $Id: i2c-elektor.h,v 1.3 1999/12/21 23:45:58 frodo Exp $ */
+/* $Id: i2c-elektor.h,v 1.4 2000/01/18 23:54:07 frodo Exp $ */
#ifndef I2C_PCF_ELEKTOR_H
#define I2C_PCF_ELEKTOR_H 1
@@ -33,10 +33,10 @@
*/
struct i2c_pcf_isa {
- int pi_base;
- int pi_irq;
- int pi_clock;
- int pi_own;
+ int pi_base;
+ int pi_irq;
+ int pi_clock;
+ int pi_own;
};
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 540bd8ada..e3d688acf 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -12,13 +12,7 @@
* Free memory management - zoned buddy allocator.
*/
-#if CONFIG_AP1000
-/* the AP+ needs to allocate 8MB contiguous, aligned chunks of ram
- for the ring buffers */
-#define MAX_ORDER 12
-#else
#define MAX_ORDER 10
-#endif
typedef struct free_area_struct {
struct list_head free_list;
diff --git a/include/linux/nfsd/export.h b/include/linux/nfsd/export.h
index febb7c741..0704c88e1 100644
--- a/include/linux/nfsd/export.h
+++ b/include/linux/nfsd/export.h
@@ -37,7 +37,8 @@
#define NFSEXP_SUNSECURE 0x0100
#define NFSEXP_CROSSMNT 0x0200
#define NFSEXP_NOSUBTREECHECK 0x0400
-#define NFSEXP_ALLFLAGS 0x07FF
+#define NFSEXP_NOAUTHNLM 0x0800 /* Don't authenticate NLM requests - just trust */
+#define NFSEXP_ALLFLAGS 0x0FFF
#ifdef __KERNEL__
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h
index 25b95ee44..67456e4d1 100644
--- a/include/linux/nfsd/nfsd.h
+++ b/include/linux/nfsd/nfsd.h
@@ -35,8 +35,9 @@
#define MAY_NOP 0
#define MAY_SATTR 8
#define MAY_TRUNC 16
-#if (MAY_SATTR | MAY_TRUNC) & (MAY_READ | MAY_WRITE | MAY_EXEC)
-# error "please use a different value for MAY_SATTR or MAY_TRUNC."
+#define MAY_LOCK 32
+#if (MAY_SATTR | MAY_TRUNC | MAY_LOCK) & (MAY_READ | MAY_WRITE | MAY_EXEC)
+# error "please use a different value for MAY_SATTR or MAY_TRUNC or MAY_LOCK."
#endif
#define MAY_CREATE (MAY_EXEC|MAY_WRITE)
#define MAY_REMOVE (MAY_EXEC|MAY_WRITE|MAY_TRUNC)
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 1678b897c..30f86f49f 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -115,9 +115,6 @@ extern struct dentry *proc_lookup(struct inode *, struct dentry *);
extern struct inode_operations proc_sys_inode_operations;
extern struct inode_operations proc_kcore_inode_operations;
extern struct inode_operations proc_kmsg_inode_operations;
-#if CONFIG_AP1000
-extern struct inode_operations proc_ringbuf_inode_operations;
-#endif
extern struct inode_operations proc_omirr_inode_operations;
extern struct inode_operations proc_ppc_htab_inode_operations;
diff --git a/include/linux/qnx4_fs.h b/include/linux/qnx4_fs.h
index 8cac77c3c..e340e3dfe 100644
--- a/include/linux/qnx4_fs.h
+++ b/include/linux/qnx4_fs.h
@@ -3,7 +3,7 @@
* Author : Richard Frowijn
* Function : qnx4 global filesystem definitions
* Version : 1.0.2
- * Last modified : 2000-01-06
+ * Last modified : 2000-01-31
*
* History : 23-03-1998 created
*/
@@ -29,7 +29,9 @@
#define QNX4_VALID_FS 0x0001 /* Clean fs. */
#define QNX4_ERROR_FS 0x0002 /* fs has errors. */
#define QNX4_BLOCK_SIZE 0x200 /* blocksize of 512 bytes */
-#define QNX4_DIR_ENTRY_SIZE 0x040 /* dir entry size */
+#define QNX4_BLOCK_SIZE_BITS 9 /* blocksize shift */
+#define QNX4_DIR_ENTRY_SIZE 0x040 /* dir entry size of 64 bytes */
+#define QNX4_DIR_ENTRY_SIZE_BITS 6 /* dir entry size shift */
#define QNX4_XBLK_ENTRY_SIZE 0x200 /* xblk entry size */
#define QNX4_INODES_PER_BLOCK 0x08 /* 512 / 64 */
@@ -96,7 +98,6 @@ struct qnx4_super_block {
#endif
extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry);
-extern unsigned long qnx4_count_free_inodes(struct super_block *sb);
extern unsigned long qnx4_count_free_blocks(struct super_block *sb);
extern unsigned long qnx4_block_map(struct inode *inode, long iblock);
diff --git a/include/linux/serial.h b/include/linux/serial.h
index ffc8d9d49..48db96051 100644
--- a/include/linux/serial.h
+++ b/include/linux/serial.h
@@ -10,6 +10,21 @@
#ifndef _LINUX_SERIAL_H
#define _LINUX_SERIAL_H
+/*
+ * Counters of the input lines (CTS, DSR, RI, CD) interrupts
+ */
+
+struct async_icount {
+ __u32 cts, dsr, rng, dcd, tx, rx;
+ __u32 frame, parity, overrun, brk;
+ __u32 buf_overrun;
+};
+
+/*
+ * The size of the serial xmit buffer is 1 page, or 4096 bytes
+ */
+#define SERIAL_XMIT_SIZE 4096
+
struct serial_struct {
int type;
int line;
diff --git a/include/linux/serialP.h b/include/linux/serialP.h
index ffd52dd86..6bb99d32f 100644
--- a/include/linux/serialP.h
+++ b/include/linux/serialP.h
@@ -19,19 +19,11 @@
* For definitions of the flags field, see tty.h
*/
+#include <linux/config.h>
#include <linux/termios.h>
#include <linux/tqueue.h>
#include <linux/wait.h>
-/*
- * Counters of the input lines (CTS, DSR, RI, CD) interrupts
- */
-struct async_icount {
- __u32 cts, dsr, rng, dcd, tx, rx;
- __u32 frame, parity, overrun, brk;
- __u32 buf_overrun;
-};
-
struct serial_state {
int magic;
int baud_base;
diff --git a/include/net/irda/ircomm_tty.h b/include/net/irda/ircomm_tty.h
index 121e4e796..3946ebb98 100644
--- a/include/net/irda/ircomm_tty.h
+++ b/include/net/irda/ircomm_tty.h
@@ -6,10 +6,10 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Jun 6 23:24:22 1999
- * Modified at: Sun Dec 12 15:57:38 1999
+ * Modified at: Fri Jan 28 13:16:57 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
- * Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
diff --git a/include/net/irda/irda.h b/include/net/irda/irda.h
index 4222d5fa1..3bb5e4e77 100644
--- a/include/net/irda/irda.h
+++ b/include/net/irda/irda.h
@@ -6,10 +6,10 @@
* Status: Stable
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Dec 9 21:13:12 1997
- * Modified at: Sat Dec 25 18:58:49 1999
+ * Modified at: Fri Jan 28 13:16:32 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
- * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
diff --git a/include/net/irda/irda_device.h b/include/net/irda/irda_device.h
index 04502f0e4..5d71dc6ef 100644
--- a/include/net/irda/irda_device.h
+++ b/include/net/irda/irda_device.h
@@ -6,10 +6,10 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Apr 14 12:41:42 1998
- * Modified at: Mon Dec 13 12:05:31 1999
+ * Modified at: Fri Jan 14 10:46:56 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
- * Copyright (c) 1999 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
* Copyright (c) 1998 Thomas Davis, <ratbert@radiks.net>,
*
* This program is free software; you can redistribute it and/or
@@ -121,23 +121,27 @@ struct dongle_reg {
};
/* Chip specific info */
-struct chipio_t {
- int iobase, iobase2; /* IO base */
- int io_ext, io_ext2; /* Length of iobase */
- int membase; /* Shared memory base */
+typedef struct {
+ int cfg_base; /* Config register IO base */
+ int sir_base; /* SIR IO base */
+ int fir_base; /* FIR IO base */
+ int mem_base; /* Shared memory base */
+ int sir_ext; /* Length of SIR iobase */
+ int fir_ext; /* Length of FIR iobase */
int irq, irq2; /* Interrupts used */
+ int dma, dma2; /* DMA channel(s) used */
int fifo_size; /* FIFO size */
-
- int dma, dma2; /* DMA channel used */
int irqflags; /* interrupt flags (ie, SA_SHIRQ|SA_INTERRUPT) */
int direction; /* Link direction, used by some FIR drivers */
-
+ int enabled; /* Powered on? */
+ int suspended; /* Suspended by APM */
__u32 speed; /* Currently used speed */
+ __u32 new_speed; /* Speed we must change to when Tx is finished */
int dongle_id; /* Dongle or transceiver currently used */
-};
+} chipio_t;
/* IO buffer specific info (inspired by struct sk_buff) */
-struct iobuff_t {
+typedef struct {
int state; /* Receiving state (transmit state not used) */
int in_frame; /* True if receiving frame */
@@ -148,7 +152,7 @@ struct iobuff_t {
int len; /* length of data */
int truesize; /* total size of buffer */
__u16 fcs;
-};
+} iobuff_t;
/* Function prototypes */
int irda_device_init(void);
diff --git a/include/net/irda/irmod.h b/include/net/irda/irmod.h
index 64a0a2272..ae61c8682 100644
--- a/include/net/irda/irmod.h
+++ b/include/net/irda/irmod.h
@@ -6,10 +6,10 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Mon Dec 15 13:58:52 1997
- * Modified at: Sun Oct 31 20:01:17 1999
+ * Modified at: Fri Jan 28 13:15:24 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
- * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
diff --git a/include/net/irda/irport.h b/include/net/irda/irport.h
index e79b45339..23b1a244f 100644
--- a/include/net/irda/irport.h
+++ b/include/net/irda/irport.h
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 3 13:49:59 1997
- * Modified at: Mon Jan 3 10:23:34 2000
+ * Modified at: Fri Jan 14 10:21:10 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1997, 1998-2000 Dag Brattli <dagb@cs.uit.no>
@@ -56,9 +56,9 @@ struct irport_cb {
struct irlap_cb *irlap; /* The link layer we are attached to */
- struct chipio_t io; /* IrDA controller information */
- struct iobuff_t tx_buff; /* Transmit buffer */
- struct iobuff_t rx_buff; /* Receive buffer */
+ chipio_t io; /* IrDA controller information */
+ iobuff_t tx_buff; /* Transmit buffer */
+ iobuff_t rx_buff; /* Receive buffer */
struct qos_info qos; /* QoS capabilities for this device */
dongle_t *dongle; /* Dongle driver */
diff --git a/include/net/irda/irtty.h b/include/net/irda/irtty.h
index 5a37ae5a7..f96976bc3 100644
--- a/include/net/irda/irtty.h
+++ b/include/net/irda/irtty.h
@@ -6,10 +6,10 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Dec 9 21:13:12 1997
- * Modified at: Sun Nov 21 21:19:35 1999
+ * Modified at: Tue Jan 25 09:10:18 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
- * Copyright (c) 1997, 1999 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 1997, 1999-2000 Dag Brattli, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -55,15 +55,14 @@ struct irtty_cb {
struct tty_struct *tty;
struct irlap_cb *irlap; /* The link layer we are binded to */
- struct chipio_t io; /* IrDA controller information */
- struct iobuff_t tx_buff; /* Transmit buffer */
- struct iobuff_t rx_buff; /* Receive buffer */
+ chipio_t io; /* IrDA controller information */
+ iobuff_t tx_buff; /* Transmit buffer */
+ iobuff_t rx_buff; /* Receive buffer */
struct qos_info qos; /* QoS capabilities for this device */
dongle_t *dongle; /* Dongle driver */
__u32 new_speed;
-
__u32 flags; /* Interface flags */
INFRARED_MODE mode;
diff --git a/include/net/irda/nsc_fir.h b/include/net/irda/nsc-ircc.h
index bbfb4d724..75e5c2bc7 100644
--- a/include/net/irda/nsc_fir.h
+++ b/include/net/irda/nsc-ircc.h
@@ -1,12 +1,12 @@
/*********************************************************************
*
- * Filename: nsc_fir.h
+ * Filename: nsc-ircc.h
* Version:
* Description:
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Fri Nov 13 14:37:40 1998
- * Modified at: Wed Jan 5 12:00:16 2000
+ * Modified at: Sun Jan 23 17:47:00 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
@@ -25,21 +25,31 @@
*
********************************************************************/
-#ifndef NSC_FIR_H
-#define NSC_FIR_H
+#ifndef NSC_IRCC_H
+#define NSC_IRCC_H
#include <linux/time.h>
#include <linux/spinlock.h>
#include <asm/io.h>
-#define PC87108 0x10
-#define PC97338 0xb0
-
/* DMA modes needed */
#define DMA_TX_MODE 0x08 /* Mem to I/O, ++, demand. */
#define DMA_RX_MODE 0x04 /* I/O to mem, ++, demand. */
+/* Config registers for the '108 */
+#define CFG_BAIC 0x00
+#define CFG_CSRT 0x01
+#define CFG_MCTL 0x02
+
+/* Config registers for the '338 */
+#define CFG_FER 0x00
+#define CFG_FAR 0x01
+#define CFG_PTR 0x02
+#define CFG_PNP0 0x1b
+#define CFG_PNP1 0x1c
+#define CFG_PNP3 0x4f
+
/* Flags for configuration register CRF0 */
#define APEDCRC 0x02
#define ENBNKSEL 0x01
@@ -174,14 +184,32 @@
#define IRM_CR_IRX_MSL 0x40
#define IRM_CR_AF_MNT 0x80 /* Automatic format */
+/* NSC chip information */
+struct nsc_chip {
+ char *name; /* Name of chipset */
+ int cfg[3]; /* Config registers */
+ u_int8_t cid_index; /* Chip identification index reg */
+ u_int8_t cid_value; /* Chip identification expected value */
+ u_int8_t cid_mask; /* Chip identification revision mask */
+
+ /* Functions for probing and initializing the specific chip */
+ int (*probe)(struct nsc_chip *chip, chipio_t *info);
+ int (*init)(struct nsc_chip *chip, chipio_t *info);
+};
+typedef struct nsc_chip nsc_chip_t;
+
/* For storing entries in the status FIFO */
struct st_fifo_entry {
int status;
int len;
};
+#define MAX_TX_WINDOW 7
+#define MAX_RX_WINDOW 7
+
struct st_fifo {
- struct st_fifo_entry entries[10];
+ struct st_fifo_entry entries[MAX_RX_WINDOW];
+ int pending_bytes;
int head;
int tail;
int len;
@@ -192,42 +220,39 @@ struct frame_cb {
int len; /* Lenght of frame in DMA mem */
};
-#define MAX_WINDOW 7
-
struct tx_fifo {
- struct frame_cb queue[MAX_WINDOW]; /* Info about frames in queue */
- int ptr; /* Currently being sent */
- int len; /* Lenght of queue */
- int free; /* Next free slot */
- void *tail; /* Next free start in DMA mem */
+ struct frame_cb queue[MAX_TX_WINDOW]; /* Info about frames in queue */
+ int ptr; /* Currently being sent */
+ int len; /* Lenght of queue */
+ int free; /* Next free slot */
+ void *tail; /* Next free start in DMA mem */
};
/* Private data for each instance */
-struct nsc_fir_cb {
+struct nsc_ircc_cb {
struct st_fifo st_fifo; /* Info about received frames */
struct tx_fifo tx_fifo; /* Info about frames to be transmitted */
- int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
- int tx_len; /* Number of frames in tx_buff */
-
struct net_device *netdev; /* Yes! we are some kind of netdevice */
struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
-
- struct chipio_t io; /* IrDA controller information */
- struct iobuff_t tx_buff; /* Transmit buffer */
- struct iobuff_t rx_buff; /* Receive buffer */
struct qos_info qos; /* QoS capabilities for this device */
+
+ chipio_t io; /* IrDA controller information */
+ iobuff_t tx_buff; /* Transmit buffer */
+ iobuff_t rx_buff; /* Receive buffer */
+
+ __u8 ier; /* Interrupt enable register */
- struct timeval stamp;
- struct timeval now;
+ struct timeval stamp;
+ struct timeval now;
spinlock_t lock; /* For serializing operations */
__u32 flags; /* Interface flags */
__u32 new_speed;
- int suspend;
+ int index; /* Instance index */
};
static inline void switch_bank(int iobase, int bank)
@@ -235,4 +260,4 @@ static inline void switch_bank(int iobase, int bank)
outb(bank, iobase+BSR);
}
-#endif /* NSC_FIR_H */
+#endif /* NSC_IRCC_H */
diff --git a/include/net/irda/smc-ircc.h b/include/net/irda/smc-ircc.h
index e5df56bc0..cac7644ca 100644
--- a/include/net/irda/smc-ircc.h
+++ b/include/net/irda/smc-ircc.h
@@ -35,135 +35,142 @@
#include <net/irda/irport.h>
/* DMA modes needed */
-#define DMA_TX_MODE 0x08 /* Mem to I/O, ++, demand. */
-#define DMA_RX_MODE 0x04 /* I/O to mem, ++, demand. */
+#define DMA_TX_MODE 0x08 /* Mem to I/O, ++, demand. */
+#define DMA_RX_MODE 0x04 /* I/O to mem, ++, demand. */
-#define IRCC_MASTER 0x07
-#define IRCC_MASTER_POWERDOWN 1<<7
-#define IRCC_MASTER_RESET 1<<6
-#define IRCC_MASTER_INT_EN 1<<5
-#define IRCC_MASTER_ERROR_RESET 1<<4
+/* Master Control Register */
+#define IRCC_MASTER 0x07
+#define IRCC_MASTER_POWERDOWN 0x80
+#define IRCC_MASTER_RESET 0x40
+#define IRCC_MASTER_INT_EN 0x20
+#define IRCC_MASTER_ERROR_RESET 0x10
/* Register block 0 */
-#define IRCC_IIR 0x01
-#define IRCC_IER 0x02
-#define IRCC_LSR 0x03
-#define IRCC_LCR_A 0x04
-#define IRCC_LCR_B 0x05
-#define IRCC_BSR 0x06
-
-#define IRCC_IIR_ACTIVE_FRAME 1<<7
-#define IRCC_IIR_EOM 1<<6
-#define IRCC_IIR_RAW_MODE 1<<5
-#define IRCC_IIR_FIFO 1<<4
-
-#define IRCC_IER_ACTIVE_FRAME 1<<7
-#define IRCC_IER_EOM 1<<6
-#define IRCC_IER_RAW_MODE 1<<5
-#define IRCC_IER_FIFO 1<<4
-
-#define IRCC_LSR_UNDERRUN 1<<7
-#define IRCC_LSR_OVERRUN 1<<6
-#define IRCC_LSR_FRAME_ERROR 1<<5
-#define IRCC_LSR_SIZE_ERROR 1<<4
-#define IRCC_LSR_CRC_ERROR 1<<3
-#define IRCC_LSR_FRAME_ABORT 1<<2
-
-#define IRCC_LCR_A_FIFO_RESET 1<<7
-#define IRCC_LCR_A_FAST 1<<6
-#define IRCC_LCR_A_GP_DATA 1<<5
-#define IRCC_LCR_A_RAW_TX 1<<4
-#define IRCC_LCR_A_RAW_RX 1<<3
-#define IRCC_LCR_A_ABORT 1<<2
-#define IRCC_LCR_A_DATA_DONE 1<<1
-
-#define IRCC_LCR_B_SCE_DISABLED 0x00<<6
-#define IRCC_LCR_B_SCE_TRANSMIT 0x01<<6
-#define IRCC_LCR_B_SCE_RECEIVE 0x02<<6
-#define IRCC_LCR_B_SCE_UNDEFINED 0x03<<6
-#define IRCC_LCR_B_SIP_ENABLE 1<<5
-#define IRCC_LCR_B_BRICK_WALL 1<<4
-
-#define IRCC_BSR_NOT_EMPTY 1<<7
-#define IRCC_BSR_FIFO_FULL 1<<6
-#define IRCC_BSR_TIMEOUT 1<<5
+
+/* Interrupt Identification */
+#define IRCC_IIR 0x01
+#define IRCC_IIR_ACTIVE_FRAME 0x80
+#define IRCC_IIR_EOM 0x40
+#define IRCC_IIR_RAW_MODE 0x20
+#define IRCC_IIR_FIFO 0x10
+
+/* Interrupt Enable */
+#define IRCC_IER 0x02
+#define IRCC_IER_ACTIVE_FRAME 0x80
+#define IRCC_IER_EOM 0x40
+#define IRCC_IER_RAW_MODE 0x20
+#define IRCC_IER_FIFO 0x10
+
+/* Line Status Register */
+#define IRCC_LSR 0x03
+#define IRCC_LSR_UNDERRUN 0x80
+#define IRCC_LSR_OVERRUN 0x40
+#define IRCC_LSR_FRAME_ERROR 0x20
+#define IRCC_LSR_SIZE_ERROR 0x10
+#define IRCC_LSR_CRC_ERROR 0x80
+#define IRCC_LSR_FRAME_ABORT 0x40
+
+/* Line Control Register A */
+#define IRCC_LCR_A 0x04
+#define IRCC_LCR_A_FIFO_RESET 0x80
+#define IRCC_LCR_A_FAST 0x40
+#define IRCC_LCR_A_GP_DATA 0x20
+#define IRCC_LCR_A_RAW_TX 0x10
+#define IRCC_LCR_A_RAW_RX 0x08
+#define IRCC_LCR_A_ABORT 0x04
+#define IRCC_LCR_A_DATA_DONE 0x02
+
+/* Line Control Register B */
+#define IRCC_LCR_B 0x05
+#define IRCC_LCR_B_SCE_DISABLED 0x00
+#define IRCC_LCR_B_SCE_TRANSMIT 0x40
+#define IRCC_LCR_B_SCE_RECEIVE 0x80
+#define IRCC_LCR_B_SCE_UNDEFINED 0xc0
+#define IRCC_LCR_B_SIP_ENABLE 0x20
+#define IRCC_LCR_B_BRICK_WALL 0x10
+
+/* Bus Status Register */
+#define IRCC_BSR 0x06
+#define IRCC_BSR_NOT_EMPTY 0x80
+#define IRCC_BSR_FIFO_FULL 0x40
+#define IRCC_BSR_TIMEOUT 0x20
/* Register block 1 */
-#define IRCC_SCE_CFGA 0x00
-#define IRCC_SCE_CFGB 0x01
-#define IRCC_FIFO_THRESHOLD 0x02
-
-#define IRCC_CFGA_AUX_IR 0x01<<7
-#define IRCC_CFGA_HALF_DUPLEX 0x01<<2
-#define IRCC_CFGA_TX_POLARITY 0x01<<1
-#define IRCC_CFGA_RX_POLARITY 0x01
-
-#define IRCC_CFGA_COM 0x00<<3
-#define IRCC_CFGA_IRDA_SIR_A 0x01<<3
-#define IRCC_CFGA_ASK_SIR 0x02<<3
-#define IRCC_CFGA_IRDA_SIR_B 0x03<<3
-#define IRCC_CFGA_IRDA_HDLC 0x04<<3
-#define IRCC_CFGA_IRDA_4PPM 0x05<<3
-#define IRCC_CFGA_CONSUMER 0x06<<3
-#define IRCC_CFGA_RAW_IR 0x07<<3
-#define IRCC_CFGA_OTHER 0x08<<3
-
-#define IRCC_IR_HDLC 0x04
-#define IRCC_IR_4PPM 0x01
-#define IRCC_IR_CONSUMER 0x02
-
-#define IRCC_CFGB_LOOPBACK 0x01<<5
-#define IRCC_CFGB_LPBCK_TX_CRC 0x01<<4
-#define IRCC_CFGB_NOWAIT 0x01<<3
-#define IRCC_CFGB_STRING_MOVE 0x01<<2
-#define IRCC_CFGB_DMA_BURST 0x01<<1
-#define IRCC_CFGB_DMA_ENABLE 0x01
-
-#define IRCC_CFGB_COM 0x00<<6
-#define IRCC_CFGB_IR 0x01<<6
-#define IRCC_CFGB_AUX 0x02<<6
-#define IRCC_CFGB_INACTIVE 0x03<<6
+
+#define IRCC_FIFO_THRESHOLD 0x02
+
+#define IRCC_SCE_CFGA 0x00
+#define IRCC_CFGA_AUX_IR 0x80
+#define IRCC_CFGA_HALF_DUPLEX 0x04
+#define IRCC_CFGA_TX_POLARITY 0x02
+#define IRCC_CFGA_RX_POLARITY 0x01
+
+#define IRCC_CFGA_COM 0x00
+#define IRCC_CFGA_IRDA_SIR_A 0x08
+#define IRCC_CFGA_ASK_SIR 0x10
+#define IRCC_CFGA_IRDA_SIR_B 0x18
+#define IRCC_CFGA_IRDA_HDLC 0x20
+#define IRCC_CFGA_IRDA_4PPM 0x28
+#define IRCC_CFGA_CONSUMER 0x30
+#define IRCC_CFGA_RAW_IR 0x38
+#define IRCC_CFGA_OTHER 0x40
+
+#define IRCC_IR_HDLC 0x04
+#define IRCC_IR_4PPM 0x01
+#define IRCC_IR_CONSUMER 0x02
+
+#define IRCC_SCE_CFGB 0x01
+#define IRCC_CFGB_LOOPBACK 0x20
+#define IRCC_CFGB_LPBCK_TX_CRC 0x10
+#define IRCC_CFGB_NOWAIT 0x08
+#define IRCC_CFGB_STRING_MOVE 0x04
+#define IRCC_CFGB_DMA_BURST 0x02
+#define IRCC_CFGB_DMA_ENABLE 0x01
+
+#define IRCC_CFGB_MUX_COM 0x00
+#define IRCC_CFGB_MUX_IR 0x40
+#define IRCC_CFGB_MUX_AUX 0x80
+#define IRCC_CFGB_MUX_INACTIVE 0xc0
/* Register block 3 - Identification Registers! */
-#define IRCC_ID_HIGH 0x00 /* 0x10 */
-#define IRCC_ID_LOW 0x01 /* 0xB8 */
-#define IRCC_CHIP_ID 0x02 /* 0xF1 */
-#define IRCC_VERSION 0x03 /* 0x01 */
-#define IRCC_INTERFACE 0x04 /* low 4 = DMA, high 4 = IRQ */
+#define IRCC_ID_HIGH 0x00 /* 0x10 */
+#define IRCC_ID_LOW 0x01 /* 0xB8 */
+#define IRCC_CHIP_ID 0x02 /* 0xF1 */
+#define IRCC_VERSION 0x03 /* 0x01 */
+#define IRCC_INTERFACE 0x04 /* low 4 = DMA, high 4 = IRQ */
/* Register block 4 - IrDA */
-#define IRCC_CONTROL 0x00
-#define IRCC_BOF_COUNT_LO 0x01
-#define IRCC_BRICKWALL_CNT_LO 0x02
-#define IRCC_BRICKWALL_TX_CNT_HI 0x03
-#define IRCC_TX_SIZE_LO 0x04
-#define IRCC_RX_SIZE_HI 0x05
-#define IRCC_RX_SIZE_LO 0x06
-
-#define IRCC_1152 0x01<<7
-#define IRCC_CRC 0x01<<6
-
-/* For storing entries in the status FIFO */
-struct st_fifo_entry {
- int status;
- int len;
-};
-
-struct st_fifo {
- struct st_fifo_entry entries[10];
- int head;
- int tail;
- int len;
+#define IRCC_CONTROL 0x00
+#define IRCC_BOF_COUNT_LO 0x01 /* Low byte */
+#define IRCC_BOF_COUNT_HI 0x00 /* High nibble (bit 0-3) */
+#define IRCC_BRICKWALL_CNT_LO 0x02 /* Low byte */
+#define IRCC_BRICKWALL_CNT_HI 0x03 /* High nibble (bit 4-7) */
+#define IRCC_TX_SIZE_LO 0x04 /* Low byte */
+#define IRCC_TX_SIZE_HI 0x03 /* High nibble (bit 0-3) */
+#define IRCC_RX_SIZE_HI 0x05 /* High nibble (bit 0-3) */
+#define IRCC_RX_SIZE_LO 0x06 /* Low byte */
+
+#define IRCC_1152 0x80
+#define IRCC_CRC 0x40
+
+struct smc_chip {
+ char *name;
+ unsigned char entr1;
+ unsigned char entr2;
+ unsigned char cid_index;
+ unsigned char cid_value;
+ int (*probe)(struct smc_chip *chip, chipio_t *info);
};
+typedef struct smc_chip smc_chip_t;
/* Private data for each instance */
struct ircc_cb {
- struct net_device *netdev; /* Yes! we are some kind of netdevice */
+ struct net_device *netdev; /* Yes! we are some kind of netdevice */
struct irlap_cb *irlap; /* The link layer we are binded to */
- struct chipio_t io; /* IrDA controller information */
- struct iobuff_t tx_buff; /* Transmit buffer */
- struct iobuff_t rx_buff; /* Receive buffer */
+ chipio_t io; /* IrDA controller information */
+ iobuff_t tx_buff; /* Transmit buffer */
+ iobuff_t rx_buff; /* Receive buffer */
struct irport_cb *irport;
@@ -172,8 +179,6 @@ struct ircc_cb {
__u32 new_speed;
__u32 flags; /* Interface flags */
- struct st_fifo st_fifo;
-
int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
int tx_len; /* Number of frames in tx_buff */
};
diff --git a/include/net/irda/toshoboe.h b/include/net/irda/toshoboe.h
index 96d9f2ec5..9bf4fb9c3 100644
--- a/include/net/irda/toshoboe.h
+++ b/include/net/irda/toshoboe.h
@@ -8,7 +8,7 @@
* Author: James McKenzie <james@fishsoup.dhs.org>
* Created at: Sat May 8 12:35:27 1999
*
- * Copyright (c) 1999 James McKenzie, All Rights Reserved.
+ * Copyright (c) 1999-2000 James McKenzie, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -23,22 +23,6 @@
*
********************************************************************/
-/*
- * $Log: toshoboe.h,v $
- * Revision 1.4 1999/06/29 13:46:42 root
- * ls
- *
- * Revision 1.3 1999/06/29 12:31:03 root
- * *** empty log message ***
- *
- * Revision 1.2 1999/05/09 01:43:08 root
- * *** empty log message ***
- *
- * Revision 1.1 1999/05/09 01:25:58 root
- * Initial revision
- *
- */
-
#ifndef TOSHOBOE_H
#define TOSHOBOE_H
@@ -154,15 +138,15 @@ struct OboeTaskFile
struct toshoboe_cb
{
- struct net_device *netdev; /* Yes! we are some kind of netdevice */
+ struct net_device *netdev; /* Yes! we are some kind of netdevice */
struct net_device_stats stats;
- struct irlap_cb *irlap; /* The link layer we are binded to */
+ struct irlap_cb *irlap; /* The link layer we are binded to */
+ struct qos_info qos; /* QoS capabilities for this device */
- struct chipio_t io; /* IrDA controller information */
- struct qos_info qos; /* QoS capabilities for this device */
+ chipio_t io; /* IrDA controller information */
- __u32 flags; /* Interface flags */
+ __u32 flags; /* Interface flags */
__u32 new_speed;
struct pci_dev *pdev; /*PCI device */
diff --git a/include/net/irda/w83977af_ir.h b/include/net/irda/w83977af_ir.h
index afd04bf86..795f24fb9 100644
--- a/include/net/irda/w83977af_ir.h
+++ b/include/net/irda/w83977af_ir.h
@@ -6,10 +6,10 @@
* Status: Experimental.
* Author: Paul VanderSpek
* Created at: Thu Nov 19 13:55:34 1998
- * Modified at: Mon Nov 8 10:00:40 1999
+ * Modified at: Tue Jan 11 13:08:19 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
- * Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 1998-2000 Dag Brattli, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -174,11 +174,11 @@ struct w83977af_ir {
struct net_device_stats stats;
struct irlap_cb *irlap; /* The link layer we are binded to */
+ struct qos_info qos; /* QoS capabilities for this device */
- struct chipio_t io; /* IrDA controller information */
- struct iobuff_t tx_buff; /* Transmit buffer */
- struct iobuff_t rx_buff; /* Receive buffer */
- struct qos_info qos; /* QoS capabilities for this device */
+ chipio_t io; /* IrDA controller information */
+ iobuff_t tx_buff; /* Transmit buffer */
+ iobuff_t rx_buff; /* Receive buffer */
__u32 flags; /* Interface flags */
__u32 new_speed;
diff --git a/include/net/irda/wrapper.h b/include/net/irda/wrapper.h
index 3d931b353..5dc0b0d16 100644
--- a/include/net/irda/wrapper.h
+++ b/include/net/irda/wrapper.h
@@ -6,10 +6,10 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Mon Aug 4 20:40:53 1997
- * Modified at: Thu Nov 4 14:25:54 1999
+ * Modified at: Tue Jan 11 12:37:29 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
- * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
+ * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
@@ -55,6 +55,6 @@ int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize);
void async_bump(struct net_device *dev, struct net_device_stats *stats,
__u8 *buf, int len);
void async_unwrap_char(struct net_device *dev, struct net_device_stats *stats,
- struct iobuff_t *buf, __u8 byte);
+ iobuff_t *buf, __u8 byte);
#endif
diff --git a/ipc/shm.c b/ipc/shm.c
index 1b3855450..508b6a3c9 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -840,6 +840,15 @@ static struct page * shm_nopage(struct vm_area_struct * shmd, unsigned long addr
idx = (address - shmd->vm_start) >> PAGE_SHIFT;
idx += shmd->vm_pgoff;
+ /*
+ * A shared mapping past the last page of the file is an error
+ * and results in a SIGBUS, so logically a shared mapping past
+ * the end of a shared memory segment should result in SIGBUS
+ * as well.
+ */
+ if (idx >= shp->shm_npages) {
+ return NULL;
+ }
down(&shp->sem);
if(shp != shm_lock(shp->id))
BUG();
diff --git a/kernel/exit.c b/kernel/exit.c
index 0537ff06d..80280e821 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -405,9 +405,6 @@ fake_volatile:
task_lock(tsk);
sem_exit();
__exit_mm(tsk);
-#if CONFIG_AP1000
- exit_msc(tsk);
-#endif
__exit_files(tsk);
__exit_fs(tsk);
__exit_sighand(tsk);
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 2941951df..f39e19d41 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -1313,7 +1313,7 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct
int lv;
int addr_len = msg->msg_namelen;
- if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR))
+ if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR))
return -EINVAL;
if (sk->zapped)
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index d4d556cb5..82e443d4d 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -1,5 +1,5 @@
/*
- * $Id: ipconfig.c,v 1.25 2000/01/09 02:19:31 davem Exp $
+ * $Id: ipconfig.c,v 1.26 2000/01/29 07:42:08 davem Exp $
*
* Automatic Configuration of IP -- use BOOTP or RARP or user-supplied
* information to configure own IP address and routes.
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index e01892326..aa890aef3 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp.c,v 1.160 2000/01/24 18:40:32 davem Exp $
+ * Version: $Id: tcp.c,v 1.161 2000/01/31 01:21:16 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1119,7 +1119,7 @@ static void cleanup_rbuf(struct sock *sk, int copied)
/* Delayed ACKs frequently hit locked sockets during bulk receive. */
time_to_ack = tp->ack.blocked && tp->ack.pending;
-#if 1/*def CONFIG_TCP_MORE_COARSE_ACKS*/
+#ifdef CONFIG_TCP_MORE_COARSE_ACKS
if (tp->ack.pending &&
(tp->rcv_nxt - tp->rcv_wup) > tp->ack.rcv_mss)
time_to_ack = 1;
@@ -1344,7 +1344,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg,
tp->ucopy.len = len;
- BUG_TRAP(tp->copied_seq == tp->rcv_nxt);
+ BUG_TRAP(tp->copied_seq == tp->rcv_nxt || (flags&MSG_PEEK));
/* Ugly... If prequeue is not empty, we have to
* process it before releasing socket, otherwise
@@ -1408,7 +1408,7 @@ do_prequeue:
copied += chunk;
}
}
-#if 1/*def CONFIG_TCP_MORE_COARSE_ACKS*/
+#ifdef CONFIG_TCP_MORE_COARSE_ACKS
if (tp->ack.pending &&
(tp->rcv_nxt - tp->rcv_wup) > tp->ack.rcv_mss)
tcp_send_ack(sk);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index d61a5df02..366dddc89 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_input.c,v 1.183 2000/01/24 18:40:33 davem Exp $
+ * Version: $Id: tcp_input.c,v 1.186 2000/01/31 20:26:13 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1346,7 +1346,8 @@ tcp_timewait_state_process(struct tcp_tw_bucket *tw, struct sk_buff *skb,
goto kill_with_rst;
/* Dup ACK? */
- if (!after(TCP_SKB_CB(skb)->end_seq, tw->rcv_nxt)) {
+ if (!after(TCP_SKB_CB(skb)->end_seq, tw->rcv_nxt) ||
+ TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq) {
tcp_tw_put(tw);
return TCP_TW_SUCCESS;
}
@@ -1912,6 +1913,8 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
!tp->urg_data) {
int chunk = min(skb->len, tp->ucopy.len);
+ __set_current_state(TASK_RUNNING);
+
local_bh_enable();
if (memcpy_toiovec(tp->ucopy.iov, skb->data, chunk)) {
sk->err = EFAULT;
@@ -1948,10 +1951,9 @@ queue_and_out:
!tp->urg_data)
tcp_fast_path_on(tp);
- if (eaten)
+ if (eaten) {
kfree_skb(skb);
-
- if (!sk->dead) {
+ } else if (!sk->dead) {
wake_up_interruptible(sk->sleep);
sock_wake_async(sk->socket,1, POLL_IN);
}
@@ -2296,29 +2298,7 @@ static int prune_queue(struct sock *sk)
* fails? -ANK
*/
- /* F.e. one possible tactics is: */
- do {
- u32 new_clamp = (tp->rcv_nxt-tp->copied_seq) + pruned;
-
- /* This guy is not a good guy. I bet, he martirized cats,
- * when was child and grew up to finished sadist. Clamp him!
- */
- if (new_clamp > 3*tp->ack.rcv_mss)
- new_clamp -= tp->ack.rcv_mss;
- else
- new_clamp = 2*tp->ack.rcv_mss;
- tp->window_clamp = min(tp->window_clamp, new_clamp);
- } while (0);
- /* Though it should be made earlier, when we are still not
- * congested. This header prediction logic sucks
- * without true implementation of VJ algorithm.
- * I am really anxious. How was it possible to combine
- * header prediction and sending ACKs outside of recvmsg() context?
- * They _are_ incompatible. We should not advance window so
- * brainlessly and we should not advertise so huge window from the very
- * beginning. BTW window "prediction" does not speedup anything!
- * SIlly, silly, silly.
- */
+ tp->ack.quick = 0;
if(atomic_read(&sk->rmem_alloc) < (sk->rcvbuf << 1))
return 0;
@@ -2525,10 +2505,14 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
NET_INC_STATS_BH(TCPHPHitsToUser);
+ __set_current_state(TASK_RUNNING);
+
if (tcp_copy_to_iovec(sk, skb, tcp_header_len))
goto csum_error;
__skb_pull(skb,tcp_header_len);
+
+ tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
} else {
if (tcp_checksum_complete_user(sk, skb))
goto csum_error;
@@ -2548,15 +2532,15 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb,
*/
__skb_queue_tail(&sk->receive_queue, skb);
skb_set_owner_r(skb, sk);
- }
- tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
+ tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq;
- /* FIN bit check is not done since if FIN is set in
- * this frame, the pred_flags won't match up. -DaveM
- */
- wake_up_interruptible(sk->sleep);
- sock_wake_async(sk->socket,1, POLL_IN);
+ /* FIN bit check is not done since if FIN is set in
+ * this frame, the pred_flags won't match up. -DaveM
+ */
+ wake_up_interruptible(sk->sleep);
+ sock_wake_async(sk->socket,1, POLL_IN);
+ }
tcp_event_data_recv(tp, skb);
@@ -3467,7 +3451,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb,
int tmo;
if (tp->linger2 < 0 ||
- after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) {
+ (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
+ after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt))) {
tcp_done(sk);
return 1;
}
@@ -3526,7 +3511,8 @@ step6:
* BSD 4.4 also does reset.
*/
if (sk->shutdown & RCV_SHUTDOWN) {
- if (after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) {
+ if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq &&
+ after(TCP_SKB_CB(skb)->end_seq - th->fin, tp->rcv_nxt)) {
tcp_reset(sk);
return 1;
}
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 7420e268f..e54ce2ec2 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_ipv4.c,v 1.197 2000/01/21 06:37:28 davem Exp $
+ * Version: $Id: tcp_ipv4.c,v 1.198 2000/01/31 01:21:20 davem Exp $
*
* IPv4 specific functions
*
@@ -598,6 +598,7 @@ unique:
*skp = sk;
sk->pprev = skp;
+ sk->hashent = hash;
sock_prot_inc_use(sk->prot);
write_unlock_bh(&head->lock);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index d6bc8a205..5583ea6cb 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_output.c,v 1.119 2000/01/19 04:06:15 davem Exp $
+ * Version: $Id: tcp_output.c,v 1.120 2000/01/31 01:21:22 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1005,7 +1005,7 @@ int tcp_connect(struct sock *sk, struct sk_buff *buff)
struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
/* Reserve space for headers. */
- skb_reserve(buff, MAX_TCP_HEADER + 15);
+ skb_reserve(buff, MAX_TCP_HEADER);
/* We'll fix this up when we get a response from the other end.
* See tcp_input.c:tcp_rcv_state_process case TCP_SYN_SENT.
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index 873d22c3d..9f13435fa 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -7,7 +7,7 @@
*
* Based on linux/net/ipv4/ip_sockglue.c
*
- * $Id: ipv6_sockglue.c,v 1.31 2000/01/16 05:11:38 davem Exp $
+ * $Id: ipv6_sockglue.c,v 1.32 2000/01/31 01:21:25 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -183,6 +183,7 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, char *optval,
local_bh_enable();
sk->prot = &udp_prot;
sk->socket->ops = &inet_dgram_ops;
+ sk->family = PF_INET;
}
opt = xchg(&np->opt, NULL);
if (opt)
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 420b81f4a..47dcf8ce0 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -5,7 +5,7 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
- * $Id: tcp_ipv6.c,v 1.118 2000/01/18 08:24:22 davem Exp $
+ * $Id: tcp_ipv6.c,v 1.119 2000/01/31 01:21:26 davem Exp $
*
* Based on:
* linux/net/ipv4/tcp.c
@@ -450,6 +450,7 @@ unique:
*skp = sk;
sk->pprev = skp;
+ sk->hashent = hash;
sock_prot_inc_use(sk->prot);
write_unlock_bh(&head->lock);
diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c
index 0e272947d..d1d89b1e4 100644
--- a/net/irda/irda_device.c
+++ b/net/irda/irda_device.c
@@ -6,7 +6,7 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Oct 9 09:22:27 1999
- * Modified at: Wed Jan 5 14:17:16 2000
+ * Modified at: Sun Jan 23 17:41:24 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999-2000 Dag Brattli, All Rights Reserved.
@@ -55,7 +55,8 @@
#include <net/irda/wrapper.h>
extern int irtty_init(void);
-extern int pc87108_init(void);
+extern int nsc_ircc_init(void);
+extern int ircc_init(void);
extern int w83977af_init(void);
extern int esi_init(void);
extern int tekram_init(void);
@@ -121,7 +122,7 @@ int __init irda_device_init( void)
w83977af_init();
#endif
#ifdef CONFIG_NSC_FIR
- pc87108_init();
+ nsc_ircc_init();
#endif
#ifdef CONFIG_TOSHIBA_FIR
toshoboe_init();
@@ -144,9 +145,6 @@ int __init irda_device_init( void)
#ifdef CONFIG_LITELINK_DONGLE
litelink_init();
#endif
-#ifdef CONFIG_AIRPORT_DONGLE
- airport_init();
-#endif
#ifdef CONFIG_OLD_BELKIN
old_belkin_init();
#endif
diff --git a/net/irda/wrapper.c b/net/irda/wrapper.c
index 13e4d0465..623328af1 100644
--- a/net/irda/wrapper.c
+++ b/net/irda/wrapper.c
@@ -6,12 +6,12 @@
* Status: Stable
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Mon Aug 4 20:40:53 1997
- * Modified at: Sun Dec 12 13:46:40 1999
+ * Modified at: Fri Jan 28 13:21:09 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Modified at: Fri May 28 3:11 CST 1999
* Modified by: Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
*
- * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
+ * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>,
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
@@ -41,19 +41,19 @@ static inline int stuff_byte(__u8 byte, __u8 *buf);
static void state_outside_frame(struct net_device *dev,
struct net_device_stats *stats,
- struct iobuff_t *rx_buff, __u8 byte);
+ iobuff_t *rx_buff, __u8 byte);
static void state_begin_frame(struct net_device *dev,
struct net_device_stats *stats,
- struct iobuff_t *rx_buff, __u8 byte);
+ iobuff_t *rx_buff, __u8 byte);
static void state_link_escape(struct net_device *dev,
struct net_device_stats *stats,
- struct iobuff_t *rx_buff, __u8 byte);
+ iobuff_t *rx_buff, __u8 byte);
static void state_inside_frame(struct net_device *dev,
struct net_device_stats *stats,
- struct iobuff_t *rx_buff, __u8 byte);
+ iobuff_t *rx_buff, __u8 byte);
static void (*state[])(struct net_device *dev, struct net_device_stats *stats,
- struct iobuff_t *rx_buff, __u8 byte) =
+ iobuff_t *rx_buff, __u8 byte) =
{
state_outside_frame,
state_begin_frame,
@@ -180,7 +180,7 @@ inline void async_bump(struct net_device *dev, struct net_device_stats *stats,
return;
}
- /* Align IP header to 20 bytes */
+ /* Align IP header to 20 bytes */
skb_reserve(skb, 1);
/* Copy data without CRC */
@@ -205,7 +205,7 @@ inline void async_bump(struct net_device *dev, struct net_device_stats *stats,
*/
inline void async_unwrap_char(struct net_device *dev,
struct net_device_stats *stats,
- struct iobuff_t *rx_buff, __u8 byte)
+ iobuff_t *rx_buff, __u8 byte)
{
(*state[rx_buff->state])(dev, stats, rx_buff, byte);
}
@@ -218,7 +218,7 @@ inline void async_unwrap_char(struct net_device *dev,
*/
static void state_outside_frame(struct net_device *dev,
struct net_device_stats *stats,
- struct iobuff_t *rx_buff, __u8 byte)
+ iobuff_t *rx_buff, __u8 byte)
{
switch (byte) {
case BOF:
@@ -245,7 +245,7 @@ static void state_outside_frame(struct net_device *dev,
*/
static void state_begin_frame(struct net_device *dev,
struct net_device_stats *stats,
- struct iobuff_t *rx_buff, __u8 byte)
+ iobuff_t *rx_buff, __u8 byte)
{
/* Time to initialize receive buffer */
rx_buff->data = rx_buff->head;
@@ -276,14 +276,14 @@ static void state_begin_frame(struct net_device *dev,
}
/*
- * Function state_link_escape (idev, byte)
+ * Function state_link_escape (dev, byte)
*
* Found link escape character
*
*/
static void state_link_escape(struct net_device *dev,
struct net_device_stats *stats,
- struct iobuff_t *rx_buff, __u8 byte)
+ iobuff_t *rx_buff, __u8 byte)
{
switch (byte) {
case BOF: /* New frame? */
@@ -315,14 +315,14 @@ static void state_link_escape(struct net_device *dev,
}
/*
- * Function state_inside_frame (idev, byte)
+ * Function state_inside_frame (dev, byte)
*
* Handle bytes received within a frame
*
*/
static void state_inside_frame(struct net_device *dev,
struct net_device_stats *stats,
- struct iobuff_t *rx_buff, __u8 byte)
+ iobuff_t *rx_buff, __u8 byte)
{
int ret = 0;
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c
index f378632ac..acdea4c9c 100644
--- a/net/netrom/af_netrom.c
+++ b/net/netrom/af_netrom.c
@@ -978,7 +978,7 @@ static int nr_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct s
unsigned char *asmptr;
int size;
- if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR))
+ if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR))
return -EINVAL;
if (sk->zapped)
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c
index e43573991..93f1a40ab 100644
--- a/net/rose/af_rose.c
+++ b/net/rose/af_rose.c
@@ -1010,7 +1010,7 @@ static int rose_sendmsg(struct socket *sock, struct msghdr *msg, int len,
unsigned char *asmptr;
int n, size, qbit = 0;
- if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR))
+ if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR))
return -EINVAL;
if (sk->zapped)
diff --git a/net/sched/sch_dsmark.c b/net/sched/sch_dsmark.c
index bb98653e1..1c1a48582 100644
--- a/net/sched/sch_dsmark.c
+++ b/net/sched/sch_dsmark.c
@@ -1,6 +1,6 @@
/* net/sched/sch_dsmark.c - Differentiated Services field marker */
-/* Written 1998,1999 by Werner Almesberger, EPFL ICA */
+/* Written 1998-2000 by Werner Almesberger, EPFL ICA */
#include <linux/config.h>
@@ -82,7 +82,7 @@ static struct Qdisc *dsmark_leaf(struct Qdisc *sch, unsigned long arg)
static unsigned long dsmark_get(struct Qdisc *sch,u32 classid)
{
- struct dsmark_qdisc_data *p = PRIV(sch);
+ struct dsmark_qdisc_data *p __attribute__((unused)) = PRIV(sch);
DPRINTK("dsmark_get(sch %p,[qdisc %p],classid %x)\n",sch,p,classid);
return TC_H_MIN(classid)+1;
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index a9f05e20f..e463b33ca 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -10,9 +10,10 @@
* Authors: J Hadi Salim (hadi@nortelnetworks.com) 1998,1999
*
* 991129: - Bug fix with grio mode
- * - a better sing. AvgQ mode with Grio
+ * - a better sing. AvgQ mode with Grio(WRED)
* - A finer grained VQ dequeue based on sugestion
* from Ren Liu
+ * - More error checks
*
*
*
@@ -134,17 +135,10 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch)
"general backlog %d\n",skb->tc_index&0xf,sch->handle,q->backlog,
sch->stats.backlog);
/* sum up all the qaves of prios <= to ours to get the new qave*/
- if (t->grio) {
+ if (!t->eqp && t->grio) {
for (i=0;i<t->DPs;i++) {
if ((!t->tab[i]) || (i==q->DP))
continue;
- if (t->tab[i]->prio == q->prio ){
- qave=0;
- t->eqp=1;
- q->qave=t->tab[t->def]->qave;
- q->qidlestart=t->tab[t->def]->qidlestart;
- break;
- }
if ((t->tab[i]->prio < q->prio) && (PSCHED_IS_PASTPERFECT(t->tab[i]->qidlestart)))
qave +=t->tab[i]->qave;
@@ -155,6 +149,12 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch)
q->packetsin++;
q->bytesin+=skb->len;
+ if (t->eqp && t->grio) {
+ qave=0;
+ q->qave=t->tab[t->def]->qave;
+ q->qidlestart=t->tab[t->def]->qidlestart;
+ }
+
if (!PSCHED_IS_PASTPERFECT(q->qidlestart)) {
long us_idle;
PSCHED_GET_TIME(now);
@@ -163,7 +163,12 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch)
q->qave >>= q->Stab[(us_idle>>q->Scell_log)&0xFF];
} else {
- q->qave += q->backlog - (q->qave >> q->Wlog);
+ if (t->eqp) {
+ q->qave += sch->stats.backlog - (q->qave >> q->Wlog);
+ } else {
+ q->qave += q->backlog - (q->qave >> q->Wlog);
+ }
+
}
@@ -232,18 +237,22 @@ gred_dequeue(struct Qdisc* sch)
skb = __skb_dequeue(&sch->q);
if (skb) {
- q= t->tab[(skb->tc_index&0xf)];
sch->stats.backlog -= skb->len;
- q->backlog -= skb->len;
- if (!q->backlog && !t->eqp)
- PSCHED_GET_TIME(q->qidlestart);
+ q= t->tab[(skb->tc_index&0xf)];
+ if (q) {
+ q->backlog -= skb->len;
+ if (!q->backlog && !t->eqp)
+ PSCHED_GET_TIME(q->qidlestart);
+ } else {
+ D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",skb->tc_index&0xf);
+ }
return skb;
}
if (t->eqp) {
q= t->tab[t->def];
if (!q)
- printk("no default VQ set: Results will be "
+ D2PRINTK("no default VQ set: Results will be "
"screwed up\n");
else
PSCHED_GET_TIME(q->qidlestart);
@@ -256,31 +265,37 @@ static int
gred_drop(struct Qdisc* sch)
{
struct sk_buff *skb;
- int i;
struct gred_sched_data *q;
struct gred_sched *t= (struct gred_sched *)sch->data;
skb = __skb_dequeue_tail(&sch->q);
if (skb) {
- q= t->tab[(skb->tc_index&0xf)];
sch->stats.backlog -= skb->len;
sch->stats.drops++;
- q->backlog -= skb->len;
- q->other++;
+ q= t->tab[(skb->tc_index&0xf)];
+ if (q) {
+ q->backlog -= skb->len;
+ q->other++;
+ if (!q->backlog && !t->eqp)
+ PSCHED_GET_TIME(q->qidlestart);
+ } else {
+ D2PRINTK("gred_dequeue: skb has bad tcindex %x\n",skb->tc_index&0xf);
+ }
+
kfree_skb(skb);
return 1;
}
-/* could probably do it for a single VQ before freeing the skb */
- for (i=0;i<t->DPs;i++) {
- q= t->tab[i];
- if (!q)
- continue;
- PSCHED_GET_TIME(q->qidlestart);
- }
+ q=t->tab[t->def];
+ if (!q) {
+ D2PRINTK("no default VQ set: Results might be screwed up\n");
+ return 0;
+ }
+ PSCHED_GET_TIME(q->qidlestart);
return 0;
+
}
static void gred_reset(struct Qdisc* sch)
@@ -295,7 +310,6 @@ static void gred_reset(struct Qdisc* sch)
kfree_skb(skb);
sch->stats.backlog = 0;
-/* could probably do it for a single VQ before freeing the skb */
for (i=0;i<t->DPs;i++) {
q= t->tab[i];
if (!q)
@@ -319,6 +333,7 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt)
struct tc_gred_sopt *sopt;
struct rtattr *tb[TCA_GRED_STAB];
struct rtattr *tb2[TCA_GRED_STAB];
+ int i;
if (opt == NULL ||
rtattr_parse(tb, TCA_GRED_STAB, RTA_DATA(opt), RTA_PAYLOAD(opt)) )
@@ -340,13 +355,13 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt)
}
- if (!table->DPs || tb[TCA_GRED_PARMS-1] == 0 || tb[TCA_GRED_STAB-1] == 0 ||
+ if (!table->DPs || tb[TCA_GRED_PARMS-1] == 0 || tb[TCA_GRED_STAB-1] == 0 ||
RTA_PAYLOAD(tb[TCA_GRED_PARMS-1]) < sizeof(*ctl) ||
RTA_PAYLOAD(tb[TCA_GRED_STAB-1]) < 256)
- return -EINVAL;
+ return -EINVAL;
- ctl = RTA_DATA(tb[TCA_GRED_PARMS-1]);
- if (ctl->DP > MAX_DPs-1 || ctl->DP <0) {
+ ctl = RTA_DATA(tb[TCA_GRED_PARMS-1]);
+ if (ctl->DP > MAX_DPs-1 || ctl->DP <0) {
/* misbehaving is punished! Put in the default drop probability */
DPRINTK("\nGRED: DP %u not in the proper range fixed. New DP "
"set to default at %d\n",ctl->DP,table->def);
@@ -356,8 +371,8 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt)
if (table->tab[ctl->DP] == NULL) {
table->tab[ctl->DP]=kmalloc(sizeof(struct gred_sched_data),
GFP_KERNEL);
- memset(table->tab[ctl->DP], 0, (sizeof(struct gred_sched_data)));
- }
+ memset(table->tab[ctl->DP], 0, (sizeof(struct gred_sched_data)));
+ }
q= table->tab[ctl->DP];
if (table->grio) {
@@ -400,6 +415,19 @@ static int gred_change(struct Qdisc *sch, struct rtattr *opt)
PSCHED_SET_PASTPERFECT(q->qidlestart);
memcpy(q->Stab, RTA_DATA(tb[TCA_GRED_STAB-1]), 256);
+ if ( table->initd && table->grio) {
+ /* this looks ugly but its not in the fast path */
+ for (i=0;i<table->DPs;i++) {
+ if ((!table->tab[i]) || (i==q->DP) )
+ continue;
+ if (table->tab[i]->prio == q->prio ){
+ /* WRED mode detected */
+ table->eqp=1;
+ break;
+ }
+ }
+ }
+
if (!table->initd) {
table->initd=1;
/*