E: knan@mo.himolde.no
D: Misc kernel hacks
-N: Zoltan Boszormenyi
-E: zboszor@mol.hu
-D: MTRR emulation with Cyrix style ARR registers
+N: Zoltán Böszörményi
+E: zboszor@mail.externet.hu
+D: MTRR emulation with Cyrix style ARR registers, Athlon MTRR support
N: John Boyd
E: boyd@cis.ohio-state.edu
read the Token-Ring mini-HOWTO, available from
http://metalab.unc.edu/mdw/linux.html#howto .
- Also read the file linux/Documentation/networking/sktr.txt or check
+ Also read the file linux/Documentation/networking/tms380tr.txt or check
http://www.auk.cx/tms380tr/
+SMC ISA TokenRing adapter support
+CONFIG_SMCTR
+ This is support for the ISA 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
+ read the Token-Ring mini-HOWTO, available from
+ http://metalab.unc.edu/mdw/linux.html#howto .
+
Traffic Shaper (EXPERIMENTAL)
CONFIG_SHAPER
The traffic shaper is a virtual network device that allows you to
- kmod reports errors through the normal kernel mechanisms, which avoids
the chicken and egg problem of kerneld and modular Unix domain sockets
+
+
+Keith Owens <kaos@ocs.com.au> December 1999
+
+The combination of kmod and modprobe can loop, especially if modprobe uses a
+system call that requires a module. If modules.dep does not exist and modprobe
+was started with the -s option (kmod does this), modprobe tries to syslog() a
+message. syslog() needs Unix sockets, if Unix sockets are modular then kmod
+runs "modprobe -s net-pf-1". This runs a second copy of modprobe which
+complains that modules.dep does not exist, tries to use syslog() and starts yet
+another copy of modprobe. This is not the only possible kmod/modprobe loop,
+just the most common.
+
+To detect loops caused by "modprobe needs a service which is in a module", kmod
+limits the number of concurrent kmod issued modprobes. See MAX_KMOD_CONCURRENT
+in kernel/kmod.c. When this limit is exceeded, the kernel issues message "kmod:
+runaway modprobe loop assumed and stopped".
+
+Note for users building a heavily modularised system. It is a good idea to
+create modules.dep after installing the modules and before booting a kernel for
+the first time. "depmod -ae m.n.p" where m.n.p is the new kernel version.
Text File for the COPS LocalTalk Linux driver (cops.c).
- By Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ By Jay Schulist <jschlst@turbolinux.com>
This driver has two modes and they are: Dayna mode and Tangent mode.
Each mode corresponds with the type of card. It has been found
Documentation on setup and use of EtherTap.
-Contact Jay Schulist <Jay.Schulist@spacs.k12.wi.us> if you
+Contact Jay Schulist <jschlst@turbolinux.com> if you
have questions or need futher assistance.
Introduction
filter.txt: Linux Socket Filtering
-Written by: Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+Written by: Jay Schulist <jschlst@turbolinux.com>
Introduction
============
Text file for ipddp.c:
AppleTalk-IP Decapsulation and AppleTalk-IP Encapsulation
-This text file writen by Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+This text file writen by Jay Schulist <jschlst@turbolinux.com>
Introduction
------------
To enable AppleTalk-IP decapsulation/encapsulation you will need the
proper tools. You can get the tools for decapsulation from
-http://spacs1.spacs.k12.wi.us/~jschlst/MacGate and for encapsulation
+http://spacs1.spacs.k12.wi.us/~jschlst/index.html and for encapsulation
from http://www.maths.unm.edu/~bradford/ltpc.html
I will briefly describe the operation of the tools, but you will
Further Assistance
-------------------
-You can contact me (Jay Schulist <Jay.Schulist@spacs.k12.wi.us>) with any
+You can contact me (Jay Schulist <jschlst@turbolinux.com>) with any
questions regarding decapsulation or encapsulation. Bradford W. Johnson
<johns393@maroon.tc.umn.edu> originally wrote the ipddp.c driver for IP
encapsulation in AppleTalk.
+++ /dev/null
-Text file for the Linux SysKonnect Token Ring ISA/PCI Adapter Driver.
- Text file by: Jay Schulist <jschlst@samba.anu.edu.au>
-
-The Linux SysKonnect Token Ring driver works with the SysKonnect TR4/16(+) ISA,
-SysKonnect TR4/16(+) PCI, SysKonnect TR4/16 PCI, and older revisions of the
-SK NET TR4/16 ISA card.
-
-Latest information on this driver can be obtained on the Linux-SNA WWW site.
-Please point your browser to:
-http://samba.anu.edu.au/linux-sna/documents/drivers/SysKonnect/
-
-Many thanks to Christoph Goos for his excellent work on this driver and
-SysKonnect for donating the adapters to Linux-SNA for the testing and maintaince
-of this device driver.
-
-Important information to be noted:
-1. Adapters can be slow to open (~20 secs) and close (~5 secs), please be
- patient.
-2. This driver works very well when autoprobing for adapters. Why even
- think about those nasty io/int/dma settings of modprobe when the driver
- will do it all for you!
-
-This driver is rather simple to use. Select Y to Token Ring adapter support
-in the kernel configuration. A choice for SysKonnect Token Ring adapters will
-appear. This drives supports all SysKonnect ISA and PCI adapters. Choose this
-option. I personally recommend compiling the driver as a module (M), but if you
-you would like to compile it staticly answer Y instead.
-
-This driver supports multiple adapters without the need to load multiple copies
-of the driver. You should be able to load up to 7 adapters without any kernel
-modifications, if you are in need of more please contact the maintainer of this
-driver.
-
-Load the driver either by lilo/loadlin or as a module. When a module using the
-following command will suffice for most:
-
-# modprobe sktr
-
-This will produce output similar to the following: (Output is user specific)
-
-sktr.c: v1.01 08/29/97 by Christoph Goos
-tr0: SK NET TR 4/16 PCI found at 0x6100, using IRQ 17.
-tr1: SK NET TR 4/16 PCI found at 0x6200, using IRQ 16.
-tr2: SK NET TR 4/16 ISA found at 0xa20, using IRQ 10 and DMA 5.
-
-Now just setup the device via ifconfig and set and routes you may have. After
-this you are ready to start sending some tokens.
-
-Errata:
-For anyone wondering where to pick up the SysKonnect adapters please browse
-to http://www.syskonnect.com
-
-This driver is under the GNU General Public License. Its Firmware image is
-included as an initialized C-array and is licensed by SysKonnect to the Linux
-users of this driver. However no waranty about its fitness is expressed or
-implied by SysKonnect.
-
-Below find attached the setting for the SK NET TR 4/16 ISA adapters
--------------------------------------------------------------------
-
- ***************************
- *** C O N T E N T S ***
- ***************************
-
- 1) Location of DIP-Switch W1
- 2) Default settings
- 3) DIP-Switch W1 description
-
-
- ==============================================================
- CHAPTER 1 LOCATION OF DIP-SWITCH
- ==============================================================
-
-UÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
-þUÄÄÄÄÄÄ¿ UÄÄÄÄÄ¿ UÄÄÄ¿ þ
-þAÄÄÄÄÄÄU W1 AÄÄÄÄÄU UÄÄÄÄ¿ þ þ þ
-þUÄÄÄÄÄÄ¿ þ þ þ þ UÄÄÅ¿
-þAÄÄÄÄÄÄU UÄÄÄÄÄÄÄÄÄÄÄ¿ AÄÄÄÄU þ þ þ þþ
-þUÄÄÄÄÄÄ¿ þ þ UÄÄÄ¿ AÄÄÄU AÄÄÅU
-þAÄÄÄÄÄÄU þ TMS380C26 þ þ þ þ
-þUÄÄÄÄÄÄ¿ þ þ AÄÄÄU AÄ¿
-þAÄÄÄÄÄÄU þ þ þ þ
-þ AÄÄÄÄÄÄÄÄÄÄÄU þ þ
-þ þ þ
-þ AÄU
-þ þ
-þ þ
-þ þ
-þ þ
-AÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄU
- AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU
-
- ==============================================================
- CHAPTER 2 DEFAULT SETTINGS
- ==============================================================
-
- W1 1 2 3 4 5 6 7 8
- +------------------------------+
- | ON X |
- | OFF X X X X X X X |
- +------------------------------+
-
- W1.1 = ON Adapter drives address lines SA17..19
- W1.2 - 1.5 = OFF BootROM disabled
- W1.6 - 1.8 = OFF I/O address 0A20h
-
- ==============================================================
- CHAPTER 3 DIP SWITCH W1 DESCRIPTION
- ==============================================================
-
- UÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄ¿ ON
- þ 1 þ 2 þ 3 þ 4 þ 5 þ 6 þ 7 þ 8 þ
- AÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄU OFF
- |AD | BootROM Addr. | I/O |
- +-+-+-------+-------+-----+-----+
- | | |
- | | +------ 6 7 8
- | | ON ON ON 1900h
- | | ON ON OFF 0900h
- | | ON OFF ON 1980h
- | | ON OFF OFF 0980h
- | | OFF ON ON 1b20h
- | | OFF ON OFF 0b20h
- | | OFF OFF ON 1a20h
- | | OFF OFF OFF 0a20h (+)
- | |
- | |
- | +-------- 2 3 4 5
- | OFF x x x disabled (+)
- | ON ON ON ON C0000
- | ON ON ON OFF C4000
- | ON ON OFF ON C8000
- | ON ON OFF OFF CC000
- | ON OFF ON ON D0000
- | ON OFF ON OFF D4000
- | ON OFF OFF ON D8000
- | ON OFF OFF OFF DC000
- |
- |
- +----- 1
- OFF adapter does NOT drive SA<17..19>
- ON adapter drives SA<17..19> (+)
-
-
- (+) means default setting
-
- ********************************
--- /dev/null
+Text File for the SMC TokenCard TokenRing Linux driver (smctr.c).
+ By Jay Schulist <jschlst@turbolinux.com>
+
+The Linux SMC Token Ring driver works with the SMC TokenCard Elite (8115T)
+ISA adapters. Preliminary support for the SMC TokenCard Elite/A (8115T/A)
+MCA adapter has been started but is not complete. (Contact me for information
+if you have the proper setup to finish the MCA parts).
+
+Latest information on this driver can be obtained on the Linux-SNA WWW site.
+Please point your browser to: http://www.linux-sna.org
+
+This driver is rather simple to use. Select Y to Token Ring adapter support
+in the kernel configuration. A choice for SMC Token Ring adapters will
+appear. This drives supports all SMC ISA/MCA adapters. Choose this
+option. I personally recommend compiling the driver as a module (M), but if you
+you would like to compile it staticly answer Y instead.
+
+This driver supports multiple adapters without the need to load multiple copies
+of the driver. You should be able to load up to 7 adapters without any kernel
+modifications, if you are in need of more please contact the maintainer of this
+driver.
+
+Load the driver either by lilo/loadlin or as a module. When a module using the
+following command will suffice for most:
+
+# modprobe smctr
+smctr.c: v1.00 12/6/99 by jschlst@turbolinux.com
+tr0: SMC TokenCard 8115T at Io 0x300, Irq 10, Rom 0xd8000, Ram 0xcc000.
+
+Now just setup the device via ifconfig and set and routes you may have. After
+this you are ready to start sending some tokens.
+
+Errata:
+1). For anyone wondering where to pick up the SMC adapters please browse
+ to http://www.smc.com
+
+2). If you are the first/only Token Ring Client on a Token Ring LAN, please
+ specify the ringspeed with the ringspeed=[4/16] module option. If no
+ ringspeed is specified the driver will attempt to autodetect the ring
+ speed and/or if the adapter is the first/only station on the ring take
+ the appropriate actions.
+
+ NOTE: Default ring speed is 16MB UTP.
+
+3). PnP support for this adapter sucks. I recommend hard setting the
+ IO/MEM/IRQ by the jumpers on the adapter. If this is not possible
+ load the module with the following io=[ioaddr] mem=[mem_addr]
+ irq=[irq_num].
+
+ The following IRQ, IO, and MEM settings are supported.
+
+ IO ports:
+ 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, 0x300,
+ 0x320, 0x340, 0x360, 0x380.
+
+ IRQs:
+ 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15
+
+ Memory addresses:
+ 0xA0000, 0xA4000, 0xA8000, 0xAC000, 0xB0000, 0xB4000,
+ 0xB8000, 0xBC000, 0xC0000, 0xC4000, 0xC8000, 0xCC000,
+ 0xD0000, 0xD4000, 0xD8000, 0xDC000, 0xE0000, 0xE4000,
+ 0xE8000, 0xEC000, 0xF0000, 0xF4000, 0xF8000, 0xFC000
+
+This driver is under the GNU General Public License. Its Firmware image is
+included as an initialized C-array and is licensed by SMC to the Linux
+users of this driver. However no waranty about its fitness is expressed or
+implied by SMC.
--- /dev/null
+Text file for the Linux SysKonnect Token Ring ISA/PCI Adapter Driver.
+ Text file by: Jay Schulist <jschlst@turbolinux.com>
+
+The Linux SysKonnect Token Ring driver works with the SysKonnect TR4/16(+) ISA,
+SysKonnect TR4/16(+) PCI, SysKonnect TR4/16 PCI, and older revisions of the
+SK NET TR4/16 ISA card.
+
+Latest information on this driver can be obtained on the Linux-SNA WWW site.
+Please point your browser to:
+http://www.linux-sna.org
+
+Many thanks to Christoph Goos for his excellent work on this driver and
+SysKonnect for donating the adapters to Linux-SNA for the testing and maintaince
+of this device driver.
+
+Important information to be noted:
+1. Adapters can be slow to open (~20 secs) and close (~5 secs), please be
+ patient.
+2. This driver works very well when autoprobing for adapters. Why even
+ think about those nasty io/int/dma settings of modprobe when the driver
+ will do it all for you!
+
+This driver is rather simple to use. Select Y to Token Ring adapter support
+in the kernel configuration. A choice for SysKonnect Token Ring adapters will
+appear. This drives supports all SysKonnect ISA and PCI adapters. Choose this
+option. I personally recommend compiling the driver as a module (M), but if you
+you would like to compile it staticly answer Y instead.
+
+This driver supports multiple adapters without the need to load multiple copies
+of the driver. You should be able to load up to 7 adapters without any kernel
+modifications, if you are in need of more please contact the maintainer of this
+driver.
+
+Load the driver either by lilo/loadlin or as a module. When a module using the
+following command will suffice for most:
+
+# modprobe sktr
+
+This will produce output similar to the following: (Output is user specific)
+
+sktr.c: v1.01 08/29/97 by Christoph Goos
+tr0: SK NET TR 4/16 PCI found at 0x6100, using IRQ 17.
+tr1: SK NET TR 4/16 PCI found at 0x6200, using IRQ 16.
+tr2: SK NET TR 4/16 ISA found at 0xa20, using IRQ 10 and DMA 5.
+
+Now just setup the device via ifconfig and set and routes you may have. After
+this you are ready to start sending some tokens.
+
+Errata:
+For anyone wondering where to pick up the SysKonnect adapters please browse
+to http://www.syskonnect.com
+
+This driver is under the GNU General Public License. Its Firmware image is
+included as an initialized C-array and is licensed by SysKonnect to the Linux
+users of this driver. However no waranty about its fitness is expressed or
+implied by SysKonnect.
+
+Below find attached the setting for the SK NET TR 4/16 ISA adapters
+-------------------------------------------------------------------
+
+ ***************************
+ *** C O N T E N T S ***
+ ***************************
+
+ 1) Location of DIP-Switch W1
+ 2) Default settings
+ 3) DIP-Switch W1 description
+
+
+ ==============================================================
+ CHAPTER 1 LOCATION OF DIP-SWITCH
+ ==============================================================
+
+UÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
+þUÄÄÄÄÄÄ¿ UÄÄÄÄÄ¿ UÄÄÄ¿ þ
+þAÄÄÄÄÄÄU W1 AÄÄÄÄÄU UÄÄÄÄ¿ þ þ þ
+þUÄÄÄÄÄÄ¿ þ þ þ þ UÄÄÅ¿
+þAÄÄÄÄÄÄU UÄÄÄÄÄÄÄÄÄÄÄ¿ AÄÄÄÄU þ þ þ þþ
+þUÄÄÄÄÄÄ¿ þ þ UÄÄÄ¿ AÄÄÄU AÄÄÅU
+þAÄÄÄÄÄÄU þ TMS380C26 þ þ þ þ
+þUÄÄÄÄÄÄ¿ þ þ AÄÄÄU AÄ¿
+þAÄÄÄÄÄÄU þ þ þ þ
+þ AÄÄÄÄÄÄÄÄÄÄÄU þ þ
+þ þ þ
+þ AÄU
+þ þ
+þ þ
+þ þ
+þ þ
+AÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄAÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄAÄÄÄÄÄÄÄÄÄU
+ AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU AÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄU
+
+ ==============================================================
+ CHAPTER 2 DEFAULT SETTINGS
+ ==============================================================
+
+ W1 1 2 3 4 5 6 7 8
+ +------------------------------+
+ | ON X |
+ | OFF X X X X X X X |
+ +------------------------------+
+
+ W1.1 = ON Adapter drives address lines SA17..19
+ W1.2 - 1.5 = OFF BootROM disabled
+ W1.6 - 1.8 = OFF I/O address 0A20h
+
+ ==============================================================
+ CHAPTER 3 DIP SWITCH W1 DESCRIPTION
+ ==============================================================
+
+ UÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄ¿ ON
+ þ 1 þ 2 þ 3 þ 4 þ 5 þ 6 þ 7 þ 8 þ
+ AÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄAÄÄÄU OFF
+ |AD | BootROM Addr. | I/O |
+ +-+-+-------+-------+-----+-----+
+ | | |
+ | | +------ 6 7 8
+ | | ON ON ON 1900h
+ | | ON ON OFF 0900h
+ | | ON OFF ON 1980h
+ | | ON OFF OFF 0980h
+ | | OFF ON ON 1b20h
+ | | OFF ON OFF 0b20h
+ | | OFF OFF ON 1a20h
+ | | OFF OFF OFF 0a20h (+)
+ | |
+ | |
+ | +-------- 2 3 4 5
+ | OFF x x x disabled (+)
+ | ON ON ON ON C0000
+ | ON ON ON OFF C4000
+ | ON ON OFF ON C8000
+ | ON ON OFF OFF CC000
+ | ON OFF ON ON D0000
+ | ON OFF ON OFF D4000
+ | ON OFF OFF ON D8000
+ | ON OFF OFF OFF DC000
+ |
+ |
+ +----- 1
+ OFF adapter does NOT drive SA<17..19>
+ ON adapter drives SA<17..19> (+)
+
+
+ (+) means default setting
+
+ ********************************
--- /dev/null
+ Via motherboard audio driver
+ Copyright 1999,2000 Jeff Garzik <jgarzik@mandrakesoft.com>
+
+Driver software and documentation distributed under the GNU GENERAL
+PUBLIC LICENSE (GPL) Version 2. See the "COPYING" file distributed with
+this software for more info.
+
+
+
+Introduction
+------------------------------------------------------------------------
+The via82cxxx audio driver found in the drivers/sound directory
+of the kernel source tree is a PCI audio driver for audio chips
+found on Via-based motherboards, such as the MVP4.
+
+Currently the driver provides audio via SoundBlaster Pro compatibility,
+and MIDI via MPU-401 compatibility. An AC97 mixing device is also
+supported, and is generally preferred over the SoundBlaster mixer.
+
+IMPORTANT NOTE: Some users report that the SoundBlaster mixer does
+not work at all -- use the AC97 mixer if possible.
+
+Please send bug reports to the mailing list linux-via@gtf.org.
+To subscribe, e-mail majordomo@gtf.org with "subscribe linux-via" in the
+body of the message.
+
+
+Thanks
+------------------------------------------------------------------------
+Via for providing e-mail support, specs, and NDA's source code.
+
+MandrakeSoft for providing hacking time.
+
+AC97 mixer interface fixes and debugging by Ron Cemer <roncemer@gte.net>
+
+
+
+Installation
+------------------------------------------------------------------------
+If the driver is being statically compiled into the kernel, no
+configuration should be necessary.
+
+If the driver is being compiled as a module, generally two lines must
+be added to your /etc/conf.modules (or /etc/modules.conf) file:
+
+ alias sound via82cxxx
+ options sb support=1
+
+The second line is very important: it tells the required 'sb' module
+not to load SoundBlaster support, but to instead let the Via driver
+do so at a later time.
+
+
+
+Driver notes
+------------------------------------------------------------------------
+This driver by default supports all PCI audio devices which report
+a vendor id of 0x1106, and a device id of 0x3058. Subsystem vendor
+and device ids are not examined.
+
+Only supports a single sound chip, as this is a motherboard chipset.
+Some architecture remains for multiple cards, feel free to submit
+a patch to clean some of that up. Ideally,
+
+No consideration for SMP, this chipset is not known to be found on
+any SMP motherboards. However, this will change when we start handling
+our own interrupts in "native mode."
+
+GNU indent formatting options: -kr -i8 -pcs
+
+
+
+Tested Hardware
+------------------------------------------------------------------------
+The following is an _incomplete_ list of motherboards supported by this
+audio driver. If your motherboard (or notebook) is not listed here,
+please e-mail the maintainer with details.
+
+ AOpen MX59 Pro (Apollo MVP4)
+
+
+
+The Future
+------------------------------------------------------------------------
+Via has graciously donated e-mail support and source code to help further
+the development of this driver. Their assistance has been invaluable
+in the design and coding of the next major version of this driver.
+
+This audio chip supports a DirectSound(tm)-style hardware interface,
+with a single 16-bit stereo input channel, and a single 16-bit stereo
+output channel. Data is transferred to/from the hardware using
+table-driven scatter-gather DMA buffers.
+
+Work is currently underway to support this "native mode" of the chip.
+When complete, SoundBlaster legacy mode will be completely removed.
+After a round of testing, this code will become version 2.0.0.
+
+Following the 2.0.0 release, the last major task to complete is
+MIDI support. MPU-401 legacy support is available currently, but
+not well tested at all.
+
+The Via audio chip apparently provides a second PCM scatter-gather
+DMA channel just for FM data, but does not have a full hardware MIDI
+processor. I haven't put much thought towards a solution here, but it
+might involve using SoftOSS midi wave table, or simply disabling MIDI
+support altogether and using the FM PCM channel as a second (input? output?)
+
+
+
+General To-do List (patches/suggestions welcome)
+------------------------------------------------------------------------
+Better docs
+
+Code review by sound guru(s)
+
+Native DSP audio driver using scatter-gather DMA, as described above
+
+Native MIDI driver, as described above
+
+
+
+Known bugs (patches/suggestions welcome)
+------------------------------------------------------------------------
+1) Two MIDI devices are loaded by the sound driver. Eliminate one of them.
+Sample /proc/sound output:
+
+ Midi devices:
+ 0: Sound Blaster
+ 1: VIA 82Cxxx Audio driver 1.1.2
+
+2) Two mixer devices are loaded by the sound driver. Eliminate one of
+them. At least one bug report says that SB mixer does not work at all,
+only AC97 mixer. Sample /proc/sound output:
+
+ Mixers:
+ 0: via82cxxxAC97Mixer
+ 1: Sound Blaster
+
+3) After unloading the driver, a SoundBlaster MIDI device is still
+listed in /proc/sound. Investigate what is not being unloaded,
+and fix it. Sample /proc/sound output, after 'rmmod via82cxxx':
+
+ Midi devices:
+ 0: Sound Blaster
+
+
information
<P>
<TABLE>
-<TR><TD><b>name[32]</b><TD>Cannonical name for this interface</TD>
+<TR><TD><b>name[32]</b><TD>Canonical name for this interface</TD>
<TR><TD><b>type</b><TD>Type of interface</TD>
<TR><TD><b>channels</b><TD>Number of radio/tv channels if appropriate</TD>
<TR><TD><b>audios</b><TD>Number of audio devices if appropriate</TD>
<P>
Some capture devices can capture a subfield of the image they actually see.
This is indicated when VIDEO_TYPE_SUBCAPTURE is defined.
-The video_capture describes the time and spacial subfields to capture.
+The video_capture describes the time and special subfields to capture.
The video_capture structure contains the following fields.
<P>
<TABLE>
<P>
<TABLE>
<TR><TD><b>tuner</b><TD>Number of the tuner</TD>
-<TR><TD><b>name</b><TD>Cannonical name for this tuner (eg FM/AM/TV)</TD>
+<TR><TD><b>name</b><TD>Canonical name for this tuner (eg FM/AM/TV)</TD>
<TR><TD><b>rangelow</b><TD>Lowest tunable frequency</TD>
<TR><TD><b>rangehigh</b><TD>Highest tunable frequency</TD>
<TR><TD><b>flags</b><TD>Flags describing the tuner</TD>
<P>
<TABLE>
<TR><TD><b>audio</b><TD>The channel number</TD>
-<TR><TD><b>volume</b><TD>The voume level</TD>
+<TR><TD><b>volume</b><TD>The volume level</TD>
<TR><TD><b>bass</b><TD>The bass level</TD>
<TR><TD><b>treble</b><TD>The treble level</TD>
<TR><TD><b>flags</b><TD>Flags describing the audio channel</TD>
System (RDS) data by means of a read() on the device. The data is packed in
groups of three, as follows:
<TABLE>
-<TR><TD>First Octet</TD><TD>Least Siginificant Byte of RDS Block</TD></TR>
-<TR><TD>Second Octet</TD><TD>Most Siginificant Byte of RDS Block
+<TR><TD>First Octet</TD><TD>Least Significant Byte of RDS Block</TD></TR>
+<TR><TD>Second Octet</TD><TD>Most Significant Byte of RDS Block
<TR><TD>Third Octet</TD><TD>Bit 7:</TD><TD>Error bit. Indicates that
-an uncorrectable error occured during reception of this block.</TD></TR>
+an uncorrectable error occurred during reception of this block.</TD></TR>
<TR><TD> </TD><TD>Bit 6:</TD><TD>Corrected bit. Indicates that
an error was corrected for this data block.</TD></TR>
-<TR><TD> </TD><TD>Bits 5-3:</TD><TD>Reeived Offset. Indicates the
+<TR><TD> </TD><TD>Bits 5-3:</TD><TD>Received Offset. Indicates the
offset received by the sync system.</TD></TR>
<TR><TD> </TD><TD>Bits 2-0:</TD><TD>Offset Name. Indicates the
offset applied to this data.</TD></TR>
various kernel versions floating around in the net,
you may obtain one e.g. from:
http://www.polyware.nl/~middelin/patch/bigphysarea-2.2.1.tar.gz
- You also have to compile your driber AFTER installing that patch
+ You also have to compile your driver AFTER installing that patch
in order to get it working
or
they are needed for uncompressed image grabbing only!!!
v4l_nbufs is the number of buffers to allocate, a value of 2 (the default)
-should be sufficient in allmost all cases. Only special applications
+should be sufficient in almost all cases. Only special applications
(streaming captures) will need more buffers and then mostly the
-MJPEG capturing features of the Buz will be more apropriate.
+MJPEG capturing features of the Buz will be more appropriate.
So leave this parameter at it's default unless you know what you do.
The things for v4l_bufsize are more complicated:
the necessary memory during boot time or
- start your kernel with the mem=xxx option, where xxx is your
real memory minus the memory needed for the buffers.
-In that case, usefull settings for v4l_bufsize are
+In that case, useful settings for v4l_bufsize are
- 1296 [Kb] for grabbing 24 bit images of max size 768*576
- 1728 [Kb] for 32bit images of same size (4*768*576 = 1728 Kb!)
You may reduce these numbers accordingly if you know you are only
--------------
The driver tries to detect if you have a triton or natome chipset
-in order to take special messures for these chipsets.
+in order to take special measures for these chipsets.
If this detection fails but you are sure you have such a chipset,
set the corresponding variable to 1.
This is a very special option and may go away in the future.
tools working with Video for Linux should work with (hopefully)
no problems.
-A description of the Video for Linux programming interace can be found at:
+A description of the Video for Linux programming interface can be found at:
http://roadrunner.swansea.linux.org.uk/v4lapi.shtml
Besides the Video for Linux interface, the driver has a "proprietary"
BUZIOC_G_PARAMS
BUZIOC_S_PARAMS
-Get and set the parameters of the buz. The user should allways
+Get and set the parameters of the buz. The user should always
do a BUZIOC_G_PARAMS (with a struct buz_params) to obtain the default
settings, change what he likes and then make a BUZIOC_S_PARAMS call.
A typical application should at least set the members
autoload=0/1 autoload helper modules (tuner, audio).
default is 1 (on).
- remap, card, radio and pll accept up to four comma-separted arguments
+ remap, card, radio and pll accept up to four comma-separated arguments
(for multiple boards).
msp3400.o
- The memory of some S3 cards is not recognized right:
- First of all, if you are not using Xfree-3.2 or newer, upgrade AT LEAST to
+ First of all, if you are not using XFree-3.2 or newer, upgrade AT LEAST to
XFree-3.2A! This solved the problem for most people.
Start up X11 like this: "XF86_S3 -probeonly" and write down where the
Make bttv work with your card
-----------------------------
-Of cource you have to load the modules as very first thing. The
+Of course you have to load the modules as very first thing. The
separate bttv bundle comes with a script called "update". I use this
one to load a new version while doing driver hacking. You can use it
too, but check the module arguments first. They work for my setup,
MAKEDEV: a script to create the special files for v4l
CARDLIST: List of all supported cards
-Loading just the bttv modules is'nt enouth for most cards. The
+Loading just the bttv modules isn't enough for most cards. The
drivers for the i2c tuner/sound chips must also be loaded. bttv tries
to load them automagically by calling request_module() now, but this
obviously works only with kmod enabled.
specified the wrong (or no) card type. A list of supported cards is
in CARDLIST.
-If your card is'nt listed in CARDLIST, you should read the Sound-FAQ.
+If your card isn't listed in CARDLIST, you should read the Sound-FAQ.
-Still does'nt work?
+Still doesn't work?
-------------------
I do NOT have a lab with 30+ different grabber boards and a
PAL/NTSC/SECAM test signal generator at home, so I often can't
-reproduce your problems. This makes debugging very difficuilt for me.
+reproduce your problems. This makes debugging very difficult for me.
If you have some knowledge and spare time, please try to fix this
yourself (patches very welcome of course...) You know: The linux
slogan is "Do it yourself".
How sound works in detail
=========================
-Still does'nt work? Looks like some driver hacking is required.
+Still doesn't work? Looks like some driver hacking is required.
Below is a do-it-yourself description for you.
The bt8xx chips have 32 general purpose pins, and registers to control
(legrang@active.co.za or legrang@cs.sun.ac.za) in 1994, and elaborations from
Frans Brinkman (brinkman@esd.nl) in 1996. The results reported here are from
experiments that the author performed on his own setup, so your mileage may
-vary... I make no guarantees, claims or warrantees to the suitability or
+vary... I make no guarantees, claims or warranties to the suitability or
validity of this information. No other documentation on the AIMS
Lab (http://www.aimslab.com/) RadioTrack card was made available to the
author. This document is offered in the hopes that it might help users who
on the I2C interface. The Zoran chip includes 2 lines SDA and SCL
which (s)he connected reversely. So we have to clock on the SDA
and r/w data on the SCL pin. Life is fun... Each cardtype now has
-a bit which signifies if you have a card with the same deficiancy.
+a bit which signifies if you have a card with the same deficiency.
-Oh, for the completness of this story I must mention that my
+Oh, for the completeness of this story I must mention that my
card delivers the VSYNC pulse of the SAA chip to GIRQ1, not
-GIRQ0 as some other cards have. This is also incorperated in
+GIRQ0 as some other cards have. This is also incorporated in
the driver be clearing/setting the 'useirq1' bit in the tvcard
description.
-Another problems of contingious capturing data with a Zoran chip
+Another problems of continuous capturing data with a Zoran chip
is something nasty inside the chip. It effectively halves the
fps we ought to get... Here is the scenario: capturing frames
to memory is done in the so-called snapshot mode. In this mode
the Zoran stops after capturing a frame worth of data and wait
-till the application set GRAB bit to indicate readyness for the
+till the application set GRAB bit to indicate readiness for the
next frame. After detecting a set bit, the chip neetly waits
till the start of a frame, captures it and it goes back to off.
Smart ppl will notice the problem here. Its the waiting on the
mknod /dev/video3 c 81 3
mknod /dev/video4 c 81 4
-After makeing/checking the devices do:
+After making/checking the devices do:
modprobe i2c
modprobe videodev
modprobe saa7110 (optional)
APPLETALK NETWORK LAYER
P: Jay Schulist
-M: Jay.Schulist@spacs.k12.wi.us
+M: jschlst@turbolinux.com
L: linux-atalk@netspace.org
S: Maintained
IPX/SPX NETWORK LAYER
P: Jay Schulist
-M: Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+M: jschlst@turbolinux.com
L: linux-net@vger.rutgers.edu
S: Maintained
S: Maintained
MODULE SUPPORT [GENERAL], KERNELD
-P: Richard Henderson
-M: richard@gnu.ai.mit.edu
+P: Keith Owens
+M: kaos@ocs.com.au
L: linux-kernel@vger.rutgers.edu
S: Maintained
SPX NETWORK LAYER
P: Jay Schulist
-M: Jay.Schulist@spacs.k12.wi.us
+M: jschlst@turbolinux.com
L: linux-net@vger.rutgers.edu
S: Supported
+SNA NETWORK LAYER
+P: Jay Schulist
+M: jschlst@turbolinux.com
+L: linux-sna@turbolinux.com
+W: http://www.linux-sna.org
+S: Supported
+
STALLION TECHNOLOGIES MULTIPORT SERIAL BOARDS
M: support@stallion.oz.au
W: http://www.stallion.com
VERSION = 2
PATCHLEVEL = 3
-SUBLEVEL = 37
+SUBLEVEL = 38
EXTRAVERSION =
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
bugs. It is *strongly* recommended that you back up the previous kernel
before installing any new 2.3.xx release.
-If you need to use a proven and stable Linux kernel, please use 2.0.37
+If you need to use a proven and stable Linux kernel, please use 2.0.38
or 2.2.xx. All features which will be in the 2.3.xx releases will be
contained in 2.4.xx when the code base has stabilized again.
bool 'ACPI support' CONFIG_ACPI
if [ "$CONFIG_ACPI" != "n" ]; then
if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
- bool ' Enter S1 for sleep' CONFIG_ACPI_S1_SLEEP
+ bool ' Enter S1 for sleep (EXPERIMENTAL)' CONFIG_ACPI_S1_SLEEP
fi
fi
Changed locking to spin with reschedule.
Made use of new <smp_call_function>.
v1.28
- 19990201 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990201 Zoltán Böszörményi <zboszor@mail.externet.hu>
Extended the driver to be able to use Cyrix style ARRs.
19990204 Richard Gooch <rgooch@atnf.csiro.au>
Restructured Cyrix support.
v1.29
- 19990204 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990204 Zoltán Böszörményi <zboszor@mail.externet.hu>
Refined ARR support: enable MAPEN in set_mtrr_prepare()
and disable MAPEN in set_mtrr_done().
19990205 Richard Gooch <rgooch@atnf.csiro.au>
Minor cleanups.
v1.30
- 19990208 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990208 Zoltán Böszörményi <zboszor@mail.externet.hu>
Protect plain 6x86s (and other processors without the
Page Global Enable feature) against accessing CR4 in
set_mtrr_prepare() and set_mtrr_done().
19990210 Richard Gooch <rgooch@atnf.csiro.au>
Turned <set_mtrr_up> and <get_mtrr> into function pointers.
v1.31
- 19990212 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990212 Zoltán Böszörményi <zboszor@mail.externet.hu>
Major rewrite of cyrix_arr_init(): do not touch ARRs,
leave them as the BIOS have set them up.
Enable usage of all 8 ARRs.
Avoid multiplications by 3 everywhere and other
code clean ups/speed ups.
- 19990213 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990213 Zoltán Böszörményi <zboszor@mail.externet.hu>
Set up other Cyrix processors identical to the boot cpu.
Since Cyrix don't support Intel APIC, this is l'art pour l'art.
Weigh ARRs by size:
If size <= 32M is given, set up ARR# we were given.
If size > 32M is given, set up ARR7 only if it is free,
fail otherwise.
- 19990214 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990214 Zoltán Böszörményi <zboszor@mail.externet.hu>
Also check for size >= 256K if we are to set up ARR7,
mtrr_add() returns the value it gets from set_mtrr()
- 19990218 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990218 Zoltán Böszörményi <zboszor@mail.externet.hu>
Remove Cyrix "coma bug" workaround from here.
Moved to linux/arch/i386/kernel/setup.c and
linux/include/asm-i386/bugs.h
19990305 Richard Gooch <rgooch@atnf.csiro.au>
Temporarily disable AMD support now MTRR capability flag is set.
v1.32
- 19990308 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990308 Zoltán Böszörményi <zboszor@mail.externet.hu>
Adjust my changes (19990212-19990218) to Richard Gooch's
latest changes. (19990228-19990305)
v1.33
19990512 Richard Gooch <rgooch@atnf.csiro.au>
Minor cleanups.
v1.35
- 19990707 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990707 Zoltán Böszörményi <zboszor@mail.externet.hu>
Check whether ARR3 is protected in cyrix_get_free_region()
and mtrr_del(). The code won't attempt to delete or change it
from now on if the BIOS protected ARR3. It silently skips ARR3
in cyrix_get_free_region() or returns with an error code from
mtrr_del().
- 19990711 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990711 Zoltán Böszörményi <zboszor@mail.externet.hu>
Reset some bits in the CCRs in cyrix_arr_init() to disable SMM
if ARR3 isn't protected. This is needed because if SMM is active
and ARR3 isn't protected then deleting and setting ARR3 again
may lock up the processor. With SMM entirely disabled, it does
not happen.
- 19990812 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990812 Zoltán Böszörményi <zboszor@mail.externet.hu>
Rearrange switch() statements so the driver accomodates to
the fact that the AMD Athlon handles its MTRRs the same way
as Intel does.
- 19990814 Zoltan Boszormenyi <zboszor@mol.hu>
+ 19990814 Zoltán Böszörményi <zboszor@mail.externet.hu>
Double check for Intel in mtrr_add()'s big switch() because
that revision check is only valid for Intel CPUs.
19990819 Alan Cox <alan@redhat.com>
wait_barrier_execute = TRUE;
wait_barrier_cache_enable = TRUE;
atomic_set (&undone_count, smp_num_cpus - 1);
- /* Flush and disable the local CPU's cache and start the ball rolling on
- other CPUs */
- set_mtrr_prepare (&ctxt);
+ /* Start the ball rolling on other CPUs */
if (smp_call_function (ipi_handler, &data, 1, 0) != 0)
panic ("mtrr: timed out waiting for other CPUs\n");
+ /* Flush and disable the local CPU's cache */
+ set_mtrr_prepare (&ctxt);
/* Wait for all other CPUs to flush and disable their caches */
while (atomic_read (&undone_count) > 0) barrier ();
/* Set up for completion wait and then release other CPUs to change MTRRs*/
* and Martin Mares, November 1997.
*
* Force Cyrix 6x86(MX) and M II processors to report MTRR capability
- * and fix against Cyrix "coma bug" by
- * Zoltan Boszormenyi <zboszor@mol.hu> February 1999.
+ * and Cyrix "coma bug" recognition by
+ * Zoltán Böszörményi <zboszor@mail.externet.hu> February 1999.
*
* Force Centaur C6 processors to report MTRR capability.
* Bart Hartgers <bart@etpmod.phys.tue.nl>, May 1999.
-/* $Id: sys_sunos.c,v 1.107 1999/12/27 06:08:37 anton Exp $
+/* $Id: sys_sunos.c,v 1.108 2000/01/06 23:51:46 davem Exp $
* sys_sunos.c: SunOS specific syscall compatibility support.
*
* Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
-/* $Id: rwsem.S,v 1.1 1999/12/28 11:50:39 jj Exp $
+/* $Id: rwsem.S,v 1.2 2000/01/05 01:00:38 davem Exp $
* Assembly part of rw semaphores.
*
* Copyright (C) 1999 Jakub Jelinek (jakub@redhat.com)
-/* $Id: pci.c,v 1.12 2000/01/01 03:32:50 davem Exp $
+/* $Id: pci.c,v 1.13 2000/01/06 23:51:49 davem Exp $
* pci.c: UltraSparc PCI controller support.
*
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@redhat.com)
*/
static void __init pci_reorder_devs(void)
{
- struct pci_dev **pci_onboard = &pci_devices;
- struct pci_dev **pci_tail = &pci_devices;
- struct pci_dev *pdev = pci_devices, *pci_other = NULL;
+ struct list_head *pci_onboard = &pci_devices;
+ struct list_head *walk = pci_onboard->next;
+
+ while (walk != pci_onboard) {
+ struct pci_dev *pdev = pci_dev_g(walk);
+ struct list_head *walk_next = walk->next;
- while (pdev) {
if (pdev->irq && (__irq_ino(pdev->irq) & 0x20)) {
- if (pci_other) {
- *pci_onboard = pdev;
- pci_onboard = &pdev->next;
- pdev = pdev->next;
- *pci_onboard = pci_other;
- *pci_tail = pdev;
- continue;
- } else
- pci_onboard = &pdev->next;
- } else if (!pci_other)
- pci_other = pdev;
- pci_tail = &pdev->next;
- pdev = pdev->next;
+ list_del(walk);
+ list_add(walk, pci_onboard);
+ }
+
+ walk = walk_next;
}
}
-/* $Id: pci_common.c,v 1.5 1999/12/20 05:02:11 davem Exp $
+/* $Id: pci_common.c,v 1.6 2000/01/06 23:51:49 davem Exp $
* pci_common.c: PCI controller common support.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
*/
static void pci_device_delete(struct pci_dev *pdev)
{
- struct pci_dev **dpp;
-
- /* First, unlink from list of all devices. */
- dpp = &pci_devices;
- while (*dpp != NULL) {
- if (*dpp == pdev) {
- *dpp = pdev->next;
- pdev->next = NULL;
- break;
- }
- dpp = &(*dpp)->next;
- }
-
- /* Next, unlink from bus sibling chain. */
- dpp = &pdev->bus->devices;
- while (*dpp != NULL) {
- if (*dpp == pdev) {
- *dpp = pdev->sibling;
- pdev->sibling = NULL;
- break;
- }
- dpp = &(*dpp)->sibling;
- }
+ list_del(&pdev->global_list);
+ list_del(&pdev->bus_list);
/* Ok, all references are gone, free it up. */
kfree(pdev);
struct pci_pbm_info *pbm,
int prom_node)
{
- struct pci_dev *pdev;
+ struct list_head *walk = &pbus->devices;
/* This loop is coded like this because the cookie
* fillin routine can delete devices from the tree.
*/
- pdev = pbus->devices;
- while (pdev != NULL) {
- struct pci_dev *next = pdev->sibling;
+ walk = walk->next;
+ while (walk != &pbus->devices) {
+ struct pci_dev *pdev = pci_dev_b(walk);
+ struct list_head *walk_next = walk->next;
pdev_cookie_fillin(pbm, pdev, prom_node);
- pdev = next;
+ walk = walk_next;
}
- for (pbus = pbus->children; pbus; pbus = pbus->next) {
- struct pcidev_cookie *pcp = pbus->self->sysdata;
- pci_fill_in_pbm_cookies(pbus, pbm, pcp->prom_node);
+ walk = &pbus->children;
+ walk = walk->next;
+ while (walk != &pbus->children) {
+ struct pci_bus *this_pbus = pci_bus_b(walk);
+ struct pcidev_cookie *pcp = this_pbus->self->sysdata;
+ struct list_head *walk_next = walk->next;
+
+ pci_fill_in_pbm_cookies(this_pbus, pbm, pcp->prom_node);
+
+ walk = walk_next;
}
}
void __init pci_record_assignments(struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
- struct pci_dev *pdev;
+ struct list_head *walk = &pbus->devices;
- for (pdev = pbus->devices; pdev; pdev = pdev->sibling)
- pdev_record_assignments(pbm, pdev);
+ for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
+ pdev_record_assignments(pbm, pci_dev_b(walk));
- for (pbus = pbus->children; pbus; pbus = pbus->next)
- pci_record_assignments(pbm, pbus);
+ walk = &pbus->children;
+ for (walk = walk->next; walk != &pbus->children; walk = walk->next)
+ pci_record_assignments(pbm, pci_bus_b(walk));
}
static void __init pdev_assign_unassigned(struct pci_pbm_info *pbm,
void __init pci_assign_unassigned(struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
- struct pci_dev *pdev;
+ struct list_head *walk = &pbus->devices;
- for (pdev = pbus->devices; pdev; pdev = pdev->sibling)
- pdev_assign_unassigned(pbm, pdev);
+ for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
+ pdev_assign_unassigned(pbm, pci_dev_b(walk));
- for (pbus = pbus->children; pbus; pbus = pbus->next)
- pci_assign_unassigned(pbm, pbus);
+ walk = &pbus->children;
+ for (walk = walk->next; walk != &pbus->children; walk = walk->next)
+ pci_assign_unassigned(pbm, pci_bus_b(walk));
}
static int __init pci_intmap_match(struct pci_dev *pdev, unsigned int *interrupt)
void __init pci_fixup_irq(struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
- struct pci_dev *pdev;
+ struct list_head *walk = &pbus->devices;
- for (pdev = pbus->devices; pdev; pdev = pdev->sibling)
- pdev_fixup_irq(pdev);
+ for (walk = walk->next; walk != &pbus->devices; walk = walk->next)
+ pdev_fixup_irq(pci_dev_b(walk));
- for (pbus = pbus->children; pbus; pbus = pbus->next)
- pci_fixup_irq(pbm, pbus);
+ walk = &pbus->children;
+ for (walk = walk->next; walk != &pbus->children; walk = walk->next)
+ pci_fixup_irq(pbm, pci_bus_b(walk));
}
/* Generic helper routines for PCI error reporting. */
struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
- struct pci_dev *pdev;
+ struct list_head *walk = &pbus->devices;
- for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
+ for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
+ struct pci_dev *pdev = pci_dev_b(walk);
u16 status, error_bits;
pci_read_config_word(pdev, PCI_STATUS, &status);
}
}
- for (pbus = pbus->children; pbus; pbus = pbus->next)
- pci_scan_for_target_abort(p, pbm, pbus);
+ walk = &pbus->children;
+ for (walk = walk->next; walk != &pbus->children; walk = walk->next)
+ pci_scan_for_target_abort(p, pbm, pci_bus_b(walk));
}
void pci_scan_for_master_abort(struct pci_controller_info *p,
struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
- struct pci_dev *pdev;
+ struct list_head *walk = &pbus->devices;
- for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
+ for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
+ struct pci_dev *pdev = pci_dev_b(walk);
u16 status, error_bits;
pci_read_config_word(pdev, PCI_STATUS, &status);
}
}
- for (pbus = pbus->children; pbus; pbus = pbus->next)
- pci_scan_for_master_abort(p, pbm, pbus);
+ walk = &pbus->children;
+ for (walk = walk->next; walk != &pbus->children; walk = walk->next)
+ pci_scan_for_master_abort(p, pbm, pci_bus_b(walk));
}
void pci_scan_for_parity_error(struct pci_controller_info *p,
struct pci_pbm_info *pbm,
struct pci_bus *pbus)
{
- struct pci_dev *pdev;
+ struct list_head *walk = &pbus->devices;
- for (pdev = pbus->devices; pdev; pdev = pdev->sibling) {
+ for (walk = walk->next; walk != &pbus->devices; walk = walk->next) {
+ struct pci_dev *pdev = pci_dev_b(walk);
u16 status, error_bits;
pci_read_config_word(pdev, PCI_STATUS, &status);
}
}
- for (pbus = pbus->children; pbus; pbus = pbus->next)
- pci_scan_for_parity_error(p, pbm, pbus);
+ walk = &pbus->children;
+ for (walk = walk->next; walk != &pbus->children; walk = walk->next)
+ pci_scan_for_parity_error(p, pbm, pci_bus_b(walk));
}
-/* $Id: pci_sabre.c,v 1.7 1999/12/19 09:17:51 davem Exp $
+/* $Id: pci_sabre.c,v 1.8 2000/01/06 23:51:49 davem Exp $
* pci_sabre.c: Sabre specific PCI controller support.
*
* Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
static void __init apb_init(struct pci_controller_info *p, struct pci_bus *sabre_bus)
{
- struct pci_dev *pdev;
- u16 word;
+ struct list_head *walk = &sabre_bus->devices;
+
+ for (walk = walk->next; walk != &sabre_bus->devices; walk = walk->next) {
+ struct pci_dev *pdev = pci_dev_b(walk);
- for (pdev = sabre_bus->devices; pdev; pdev = pdev->sibling) {
if (pdev->vendor == PCI_VENDOR_ID_SUN &&
pdev->device == PCI_DEVICE_ID_SUN_SIMBA) {
+ u16 word;
+
sabre_read_word(pdev, PCI_COMMAND, &word);
word |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY |
static void __init sabre_scan_bus(struct pci_controller_info *p)
{
static int once = 0;
- struct pci_bus *sabre_bus, *pbus;
+ struct pci_bus *sabre_bus;
+ struct list_head *walk;
/* Unlike for PSYCHO, we can only have one SABRE
* in a system. Having multiple SABREs is thus
&p->pbm_A);
apb_init(p, sabre_bus);
- for (pbus = sabre_bus->children; pbus; pbus = pbus->next) {
+ walk = &sabre_bus->children;
+ for (walk = walk->next; walk != &sabre_bus->children; walk = walk->next) {
+ struct pci_bus *pbus = pci_bus_b(walk);
struct pci_pbm_info *pbm;
if (pbus->number == p->pbm_A.pci_first_busno) {
-/* $Id: sparc64_ksyms.c,v 1.68 1999/12/17 12:32:05 jj Exp $
+/* $Id: sparc64_ksyms.c,v 1.69 2000/01/04 23:54:44 davem Exp $
* arch/sparc64/kernel/sparc64_ksyms.c: Sparc64 specific ksyms support.
*
* Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
extern int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
extern int sys32_ioctl(unsigned int fd, unsigned int cmd, u32 arg);
extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *);
+extern long sparc32_open(const char * filename, int flags, int mode);
extern void bcopy (const char *, char *, int);
extern int __ashrdi3(int, int);
EXPORT_SYMBOL(prom_cpu_nodes);
EXPORT_SYMBOL(sys_ioctl);
EXPORT_SYMBOL(sys32_ioctl);
+EXPORT_SYMBOL(sparc32_open);
EXPORT_SYMBOL(move_addr_to_kernel);
EXPORT_SYMBOL(move_addr_to_user);
#endif
-/* $Id: sys_sparc.c,v 1.31 1999/12/21 14:09:25 jj Exp $
+/* $Id: sys_sparc.c,v 1.32 2000/01/05 01:00:40 davem Exp $
* linux/arch/sparc64/kernel/sys_sparc.c
*
* This file contains various random system calls that
-/* $Id: sys_sparc32.c,v 1.126 1999/12/21 14:09:21 jj Exp $
+/* $Id: sys_sparc32.c,v 1.127 2000/01/04 23:54:41 davem Exp $
* sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
return ret;
}
+
+/* This is just a version for 32-bit applications which does
+ * not force O_LARGEFILE on.
+ */
+
+asmlinkage long sparc32_open(const char * filename, int flags, int mode)
+{
+ char * tmp;
+ int fd, error;
+
+ tmp = getname(filename);
+ fd = PTR_ERR(tmp);
+ if (!IS_ERR(tmp)) {
+ fd = get_unused_fd();
+ if (fd >= 0) {
+ struct file * f;
+ lock_kernel();
+ f = filp_open(tmp, flags, mode);
+ unlock_kernel();
+ error = PTR_ERR(f);
+ if (IS_ERR(f))
+ goto out_error;
+ fd_install(fd, f);
+ }
+out:
+ putname(tmp);
+ }
+ return fd;
+
+out_error:
+ put_unused_fd(fd);
+ fd = error;
+ goto out;
+}
-/* $Id: sys_sunos32.c,v 1.33 1999/12/15 14:24:25 davem Exp $
+/* $Id: sys_sunos32.c,v 1.35 2000/01/06 23:51:50 davem Exp $
* sys_sunos32.c: SunOS binary compatability layer on sparc64.
*
* Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
/* XXXXXXXXXXXXXXXXXXXX */
asmlinkage int sunos_nfs_mount(char *dir_name, int linux_flags, void *data)
{
- int ret = -ENODEV;
int server_fd;
char *the_name;
struct nfs_mount_data linux_nfs_mount;
return rval;
}
-asmlinkage int sunos_open(u32 filename, int flags, int mode)
+extern asmlinkage long sparc32_open(const char * filename, int flags, int mode);
+
+asmlinkage int sunos_open(u32 fname, int flags, int mode)
{
- int ret;
+ const char *filename = (const char *)(long)fname;
- lock_kernel();
current->personality |= PER_BSD;
- ret = sys_open ((char *)A(filename), flags, mode);
- unlock_kernel();
- return ret;
+ return sparc32_open(filename, flags, mode);
}
#define SUNOS_EWOULDBLOCK 35
-/* $Id: systbls.S,v 1.61 1999/12/21 14:09:15 jj Exp $
+/* $Id: systbls.S,v 1.62 2000/01/04 23:54:43 davem Exp $
* systbls.S: System call entry point tables for OS compatibility.
* The native Linux system call table lives here also.
*
.globl sys_call_table32
sys_call_table32:
/*0*/ .word sys_nis_syscall, sparc_exit, sys_fork, sys_read, sys_write
-/*5*/ .word sys_open, sys_close, sys32_wait4, sys_creat, sys_link
+/*5*/ .word sparc32_open, sys_close, sys32_wait4, sys_creat, sys_link
/*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys32_chown, sys32_mknod
/*15*/ .word sys32_chmod, sys32_lchown, sparc_brk, sys_perfctr, sys32_lseek
/*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid, sys_getuid
-/* $Id: fs.c,v 1.14 1999/09/22 09:28:49 davem Exp $
+/* $Id: fs.c,v 1.15 2000/01/04 23:54:47 davem Exp $
* fs.c: fs related syscall emulation for Solaris
*
* Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
return error;
}
-asmlinkage int solaris_open(u32 filename, int flags, u32 mode)
+extern asmlinkage long sparc32_open(const char * filename, int flags, int mode);
+
+asmlinkage int solaris_open(u32 fname, int flags, u32 mode)
{
- int (*sys_open)(const char *,int,int) =
- (int (*)(const char *,int,int))SYS(open);
+ const char *filename = (const char *)(long)fname;
int fl = flags & 0xf;
-/* if (flags & 0x2000) - allow LFS */
+ /* Translate flags first. */
+ if (flags & 0x2000) fl |= O_LARGEFILE;
if (flags & 0x8050) fl |= O_SYNC;
if (flags & 0x80) fl |= O_NONBLOCK;
if (flags & 0x100) fl |= O_CREAT;
if (flags & 0x200) fl |= O_TRUNC;
if (flags & 0x400) fl |= O_EXCL;
if (flags & 0x800) fl |= O_NOCTTY;
- return sys_open((const char *)A(filename), fl, mode);
+ flags = fl;
+
+ return sparc32_open(filename, flags, mode);
}
#define SOL_F_SETLK 6
if [ "$CONFIG_IDEDMA_PCI_EXPERIMENTAL" = "y" ]; then
bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290
if [ "$CONFIG_X86" = "y" ]; then
- bool ' VIA82CXXX chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82CXXX
+ bool ' VIA82CXXX chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82CXXX
fi
fi
fi
extern int ibmtr_probe(struct net_device *);
extern int olympic_probe(struct net_device *);
extern int tms380tr_probe(struct net_device *);
+extern int smctr_probe(struct net_device *);
static int
trif_probe(struct net_device *dev)
/* cops.c: LocalTalk driver for Linux.
*
* Authors:
- * - Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ * - Jay Schulist <jschlst@turbolinux.com>
*
* With more than a little help from;
* - Alan Cox <Alan.Cox@linux.org>
*/
static const char *version =
-"cops.c:v0.04 6/7/98 Jay Schulist <Jay.Schulist@spacs.k12.wi.us>\n";
+"cops.c:v0.04 6/7/98 Jay Schulist <jschlst@turbolinux.com>\n";
/*
* Sources:
* COPS Localtalk SDK. This provides almost all of the information
/* cops.h: LocalTalk driver for Linux.
*
* Authors:
- * - Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ * - Jay Schulist <jschlst@turbolinux.com>
*/
#ifndef __LINUX_COPSLTALK_H
/* cops_ffdrv.h: LocalTalk driver firmware dump for Linux.
*
* Authors:
- * - Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ * - Jay Schulist <jschlst@turbolinux.com>
*/
#include <linux/config.h>
/* cops_ltdrv.h: LocalTalk driver firmware dump for Linux.
*
* Authors:
- * - Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ * - Jay Schulist <jschlst@turbolinux.com>
*/
#include <linux/config.h>
u_long iobase = 0; /* Clear upper 32 bits in Alphas */
int i, j;
struct bus_type *lp = &bus;
+ struct list_head *walk = &dev->bus_list;
- for (; (dev=dev->sibling)!= NULL;) {
- pb = dev->bus->number;
- vendor = dev->vendor;
- device = dev->device << 8;
+ for (walk = walk->next; walk != &dev->bus_list; walk = walk->next) {
+ struct pci_dev *this_dev = pci_dev_b(walk);
+
+ pb = this_dev->bus->number;
+ vendor = this_dev->vendor;
+ device = this_dev->device << 8;
if (!(is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x)) continue;
/* Get the chip configuration revision register */
- pcibios_read_config_dword(pb, dev->devfn, PCI_REVISION_ID, &cfrv);
+ pcibios_read_config_dword(pb, this_dev->devfn, PCI_REVISION_ID, &cfrv);
/* Set the device number information */
- lp->device = PCI_SLOT(dev->devfn);
+ lp->device = PCI_SLOT(this_dev->devfn);
lp->bus_num = pb;
/* Set the chipset information */
lp->chipset = device;
/* Get the board I/O address (64 bits on sparc64) */
- iobase = dev->resource[0].start;
+ iobase = this_dev->resource[0].start;
/* Fetch the IRQ to be used */
- irq = dev->irq;
+ irq = this_dev->irq;
if ((irq == 0) || (irq == 0xff) || ((int)irq == -1)) continue;
/* Check if I/O accesses are enabled */
- pcibios_read_config_word(pb, dev->devfn, PCI_COMMAND, &status);
+ pcibios_read_config_word(pb, this_dev->devfn, PCI_COMMAND, &status);
if (!(status & PCI_COMMAND_IO)) continue;
/* Search for a valid SROM attached to this DECchip */
*
* Authors:
* - DDP-IP Encap by: Bradford W. Johnson <johns393@maroon.tc.umn.edu>
- * - DDP-IP Decap by: Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ * - DDP-IP Decap by: Jay Schulist <jschlst@turbolinux.com>
*
* Derived from:
* - Almost all code already existed in net/appletalk/ddp.c I just
* Written 1993-94 by Donald Becker.
* - dummy.c: A dummy net driver. By Nick Holloway.
* - MacGate: A user space Daemon for Appletalk-IP Decap for
- * Linux by Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ * Linux by Jay Schulist <jschlst@turbolinux.com>
*
* Copyright 1993 United States Government as represented by the
* Director, National Security Agency.
printk("%s: Appletalk-IP Encap. mode by Bradford W. Johnson <johns393@maroon.tc.umn.edu>\n",
dev->name);
if(ipddp_mode == IPDDP_DECAP)
- printk("%s: Appletalk-IP Decap. mode by Jay Schulist <Jay.Schulist@spacs.k12.wi.us>\n",
+ printk("%s: Appletalk-IP Decap. mode by Jay Schulist <jschlst@turbolinux.com>\n",
dev->name);
/* Fill in the device structure with ethernet-generic values. */
dep_tristate 'IrPORT (IrDA serial driver)' CONFIG_IRPORT_SIR $CONFIG_IRDA
comment 'FIR device drivers'
-dep_tristate 'NSC PC87108' CONFIG_NSC_FIR $CONFIG_IRDA
+dep_tristate 'NSC PC87108/PC97338' 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
endif
ifeq ($(CONFIG_NSC_FIR),y)
-L_OBJS += pc87108.o
+L_OBJS += nsc_fir.o
else
ifeq ($(CONFIG_NSC_FIR),m)
- M_OBJS += pc87108.o
+ M_OBJS += nsc_fir.o
endif
endif
* Authors: Dag Brattli <dagb@cs.uit.no> (initially)
* Jean Tourrilhes <jt@hpl.hp.com> (new version)
* Created at: Wed Oct 21 20:02:35 1998
- * Modified at: Fri Dec 17 09:16:09 1999
+ * Modified at: Fri Dec 17 09:10:43 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Feb 21 18:54:38 1998
- * Modified at: Fri Dec 17 09:17:05 1999
+ * Modified at: Fri Dec 17 09:14:04 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, <dagb@cs.uit.no>,
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Feb 6 21:02:33 1999
- * Modified at: Fri Dec 17 09:16:52 1999
+ * Modified at: Fri Dec 17 09:13:20 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 3 13:49:59 1997
- * Modified at: Tue Dec 21 21:51:23 1999
+ * Modified at: Wed Jan 5 13:59:38 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: serial.c by Linus Torvalds
*
- * Copyright (c) 1997, 1998, 1999 Dag Brattli, All Rights Reserved.
+ * Copyright (c) 1997, 1998, 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
return NULL;
}
memset(self, 0, sizeof(struct irport_cb));
-
spin_lock_init(&self->lock);
/* Need to store self somewhere */
dev_self[i] = self;
self->priv = self;
+ self->index = i;
/* Initialize IO */
- self->io.iobase = iobase;
- self->io.irq = irq;
+ self->io.iobase = iobase;
+ self->io.irq = irq;
self->io.io_ext = IO_EXTENT;
self->io.fifo_size = 16;
ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
return NULL;
}
+
self->netdev = dev;
/* May be overridden by piggyback drivers */
if (self->rx_buff.head)
kfree(self->rx_buff.head);
-
+
+ /* Remove ourselves */
+ dev_self[self->index] = NULL;
kfree(self);
return 0;
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Dec 9 21:18:38 1997
- * Modified at: Tue Dec 21 21:50:59 1999
+ * Modified at: Wed Jan 5 14:00:13 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>
*
- * 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
* Status: Stable
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Fri May 7 12:50:33 1999
- * Modified at: Fri Dec 17 09:16:23 1999
+ * Modified at: Fri Dec 17 09:14:23 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
--- /dev/null
+/*********************************************************************
+ *
+ * Filename: nsc_fir.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 by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
+ * Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
+ * Copyright (c) 1998 Actisys Corp., www.actisys.com
+ * 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 Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ * Notice that all functions that needs to access the chip in _any_
+ * way, must save BSR register on entry, and restore it on exit.
+ * It is _very_ important to follow this policy!
+ *
+ * __u8 bank;
+ *
+ * bank = inb(iobase+BSR);
+ *
+ * do_your_stuff_here();
+ *
+ * outb(bank, iobase+BSR);
+ *
+ * If you find bugs in this file, its very likely that the same bug
+ * will also be in w83977af_ir.c since the implementations are quite
+ * similar.
+ *
+ ********************************************************************/
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/init.h>
+#include <linux/rtnetlink.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>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/irda_device.h>
+
+#include <net/irda/nsc_fir.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";
+
+/* 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 };
+
+static struct nsc_fir_cb *dev_self[] = { NULL, NULL, NULL, NULL, NULL };
+
+static char *dongle_types[] = {
+ "Differential serial interface",
+ "Differential serial interface",
+ "Reserved",
+ "Reserved",
+ "Sharp RY5HD01",
+ "Reserved",
+ "Single-ended serial interface",
+ "Consumer-IR only",
+ "HP HSDL-2300, HP HSDL-3600/HSDL-3610",
+ "IBM31T1100 or Temic TFDS6000/TFDS6500",
+ "Reserved",
+ "Reserved",
+ "HP HSDL-1100/HSDL-2100",
+ "HP HSDL-1100/HSDL-2100"
+ "Supports SIR Mode only",
+ "No dongle connected",
+};
+
+/* Some prototypes */
+static int nsc_fir_open(int i, unsigned int iobase, unsigned int board_addr,
+ unsigned int irq, unsigned int dma);
+#ifdef MODULE
+static int nsc_fir_close(struct nsc_fir_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);
+#ifdef CONFIG_APM
+static int nsc_fir_apmproc(apm_event_t event);
+#endif /* CONFIG_APM */
+/*
+ * Function nsc_fir_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 ret = -ENODEV;
+ int ioaddr;
+ int i;
+
+#ifdef CONFIG_APM
+ apm_register_callback(nsc_fir_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 ()
+ *
+ * Close all configured chips
+ *
+ */
+#ifdef MODULE
+static void nsc_fir_cleanup(void)
+{
+ int i;
+
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+#ifdef CONFIG_APM
+ apm_unregister_callback(nsc_fir_apmproc);
+#endif /* CONFIG_APM */
+
+
+ for (i=0; i < 5; i++) {
+ if (dev_self[i])
+ nsc_fir_close(dev_self[i]);
+ }
+}
+#endif /* MODULE */
+
+/*
+ * Function nsc_fir_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)
+{
+ struct net_device *dev;
+ struct nsc_fir_cb *self;
+ int dongle_id;
+ int ret;
+ int err;
+
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+ if ((dongle_id = nsc_fir_probe(iobase, board_addr, irq, dma)) == -1)
+ return -1;
+
+ /*
+ * Allocate new instance of the driver
+ */
+ self = kmalloc(sizeof(struct nsc_fir_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));
+ spin_lock_init(&self->lock);
+
+ /* Need to store self somewhere */
+ dev_self[i] = self;
+
+ /* Initialize IO */
+ self->io.iobase = iobase;
+ self->io.irq = irq;
+ self->io.io_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);
+ if (ret < 0) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+ self->io.iobase);
+ /* nsc_fir_cleanup(self->self); */
+ return -ENODEV;
+ }
+ request_region(self->io.iobase, self->io.io_ext, driver_name);
+
+ /* Initialize QoS for this device */
+ irda_init_max_qos_capabilies(&self->qos);
+
+ /* The only value we must override it the baudrate */
+ self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+ IR_115200|IR_576000|IR_1152000 |(IR_4000000 << 8);
+
+ self->qos.min_turn_time.bits = qos_mtt_bits;
+ irda_qos_bits_to_value(&self->qos);
+
+ self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
+
+ /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+ self->rx_buff.truesize = 14384;
+ self->tx_buff.truesize = 14384;
+
+ /* Allocate memory if needed */
+ self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+ GFP_KERNEL|GFP_DMA);
+ if (self->rx_buff.head == NULL)
+ 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->rx_buff.head);
+ return -ENOMEM;
+ }
+ memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+
+ self->rx_buff.in_frame = FALSE;
+ self->rx_buff.state = OUTSIDE_FRAME;
+ self->tx_buff.data = self->tx_buff.head;
+ self->rx_buff.data = self->rx_buff.head;
+
+ /* Reset Tx queue info */
+ self->tx_fifo.len = self->tx_fifo.ptr = self->tx_fifo.free = 0;
+ self->tx_fifo.tail = self->tx_buff.head;
+
+ if (!(dev = dev_alloc("irda%d", &err))) {
+ ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
+ return -ENOMEM;
+ }
+
+ dev->priv = (void *) self;
+ 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;
+
+ rtnl_lock();
+ err = register_netdevice(dev);
+ rtnl_unlock();
+ if (err) {
+ ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
+ return -1;
+ }
+
+ MESSAGE("IrDA: Registered device %s\n", dev->name);
+
+ self->io.dongle_id = dongle_id;
+ nsc_fir_init_dongle_interface(iobase, dongle_id);
+
+ return 0;
+}
+
+#ifdef MODULE
+/*
+ * Function nsc_fir_close (self)
+ *
+ * Close driver instance
+ *
+ */
+static int nsc_fir_close(struct nsc_fir_cb *self)
+{
+ int iobase;
+
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+ ASSERT(self != NULL, return -1;);
+
+ iobase = self->io.iobase;
+
+ /* Remove netdevice */
+ if (self->netdev) {
+ rtnl_lock();
+ unregister_netdevice(self->netdev);
+ rtnl_unlock();
+ }
+
+ /* 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);
+
+ if (self->tx_buff.head)
+ kfree(self->tx_buff.head);
+
+ if (self->rx_buff.head)
+ kfree(self->rx_buff.head);
+
+ kfree(self);
+
+ return 0;
+}
+#endif /* MODULE */
+
+/*
+ * Function nsc_fir_init_807 (iobase, board_addr, irq, dma)
+ *
+ * Initialize the NSC '108 chip
+ *
+ */
+static void nsc_fir_init_807(int iobase, int board_addr, int irq, int dma)
+{
+ __u8 temp=0;
+
+ outb(2, board_addr); /* Mode Control Register (MCTL) */
+ outb(0x00, board_addr+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;
+ default: ERROR(__FUNCTION__ "(), invalid base_address");
+ }
+
+ /* Control Signal Routing Register (CSRT) */
+ switch (irq) {
+ case 3: temp = 0x01; break;
+ case 4: temp = 0x02; break;
+ case 5: temp = 0x03; break;
+ case 7: temp = 0x04; break;
+ case 9: temp = 0x05; break;
+ case 11: temp = 0x06; break;
+ case 15: temp = 0x07; break;
+ default: ERROR(__FUNCTION__ "(), invalid irq");
+ }
+ outb(1, board_addr);
+
+ 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;
+ default: ERROR(__FUNCTION__ "(), invalid dma");
+ }
+
+ outb(2, board_addr); /* Mode Control Register (MCTL) */
+ outb(0x03, board_addr+1); /* Enable device */
+}
+
+/*
+ * Function nsc_fir_init_338 (iobase, board_addr, irq, dma)
+ *
+ * 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)
+{
+ /* No init yet */
+}
+
+static int nsc_fir_find_chip(int board_addr)
+{
+ __u8 index, id;
+
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+ /* Read index register */
+ index = inb(board_addr);
+ if (index == 0xff) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), no chip at 0x%03x\n",
+ board_addr);
+ return -1;
+ }
+
+ /* 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;
+ }
+
+ return -1;
+}
+
+/*
+ * Function nsc_fir_probe (iobase, board_addr, irq, dma)
+ *
+ * Returns non-negative on success.
+ *
+ */
+static int nsc_fir_probe(int iobase, int board_addr, int irq, int dma)
+{
+ 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;
+ }
+
+ /* Read the Module ID */
+ switch_bank(iobase, BANK3);
+ version = inb(iobase+MID);
+
+ /* Should be 0x2? */
+ if (0x20 != (version & 0xf0)) {
+ 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);
+
+ /* 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);
+ outb(FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
+
+ /* Set FIFO size to 32 */
+ switch_bank(iobase, BANK2);
+ outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
+
+ /* IRCR2: FEND_MD is set */
+ switch_bank(iobase, BANK5);
+ outb(0x2a, iobase+4);
+
+ /* Make sure that some defaults are OK */
+ switch_bank(iobase, BANK6);
+ outb(0x20, iobase+0); /* Set 32 bits FIR CRC */
+ outb(0x0a, iobase+1); /* Set MIR pulse width */
+ outb(0x0d, iobase+2); /* Set SIR pulse width */
+ outb(0x2a, iobase+4); /* Set beginning frag, and preamble length */
+
+ MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name);
+
+ /* Enable receive interrupts */
+ switch_bank(iobase, BANK0);
+ outb(IER_RXHDL_IE, iobase+IER);
+
+ return dongle_id;
+}
+
+/*
+ * Function nsc_fir_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)
+{
+ int dongle_id;
+ __u8 bank;
+
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+ bank = inb(iobase+BSR);
+
+ /* Select Bank 7 */
+ switch_bank(iobase, BANK7);
+
+ /* IRCFG4: IRSL0_DS and IRSL21_DS are cleared */
+ outb(0x00, iobase+7);
+
+ /* ID0, 1, and 2 are pulled up/down very slowly */
+ udelay(50);
+
+ /* IRCFG1: read the ID bits */
+ dongle_id = inb(iobase+4) & 0x0f;
+
+#ifdef BROKEN_DONGLE_ID
+ if (dongle_id == 0x0a)
+ dongle_id = 0x09;
+#endif
+
+ /* Go back to bank 0 before returning */
+ switch_bank(iobase, BANK0);
+
+ outb(bank, iobase+BSR);
+
+ return dongle_id;
+}
+
+/*
+ * Function nsc_fir_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)
+{
+ int bank;
+
+ /* Save current bank */
+ bank = inb(iobase+BSR);
+
+ /* Select Bank 7 */
+ switch_bank(iobase, BANK7);
+
+ /* IRCFG4: set according to dongle_id */
+ switch (dongle_id) {
+ case 0x00: /* same as */
+ case 0x01: /* Differential serial interface */
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x02: /* same as */
+ case 0x03: /* Reserved */
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x04: /* Sharp RY5HD01 */
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x05: /* Reserved, but this is what the Thinkpad reports */
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x06: /* Single-ended serial interface */
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x07: /* Consumer-IR only */
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+ 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]);
+ break;
+ case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
+ outb_p(0x28, iobase+7); /* Set irsl[0-2] as output */
+ break;
+ case 0x0A: /* same as */
+ case 0x0B: /* Reserved */
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x0C: /* same as */
+ case 0x0D: /* HP HSDL-1100/HSDL-2100 */
+ /*
+ * Set irsl0 as input, irsl[1-2] as output, and separate
+ * inputs are used for SIR and MIR/FIR
+ */
+ outb(0x48, iobase+7);
+ break;
+ case 0x0E: /* Supports SIR Mode only */
+ outb(0x28, iobase+7); /* Set irsl[0-2] as output */
+ break;
+ case 0x0F: /* No dongle connected */
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s\n",
+ dongle_types[dongle_id]);
+
+ switch_bank(iobase, BANK0);
+ outb(0x62, iobase+MCR);
+ break;
+ default:
+ IRDA_DEBUG(0, __FUNCTION__ "(), invalid dongle_id %#x",
+ dongle_id);
+ }
+
+ /* IRCFG1: IRSL1 and 2 are set to IrDA mode */
+ outb(0x00, iobase+4);
+
+ /* Restore bank register */
+ outb(bank, iobase+BSR);
+
+} /* set_up_dongle_interface */
+
+/*
+ * Function nsc_fir_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)
+{
+ unsigned long flags;
+ __u8 bank;
+
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+ /* Save current bank */
+ bank = inb(iobase+BSR);
+
+ /* Select Bank 7 */
+ switch_bank(iobase, BANK7);
+
+ /* IRCFG1: set according to dongle_id */
+ switch (dongle_id) {
+ case 0x00: /* same as */
+ case 0x01: /* Differential serial interface */
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x02: /* same as */
+ case 0x03: /* Reserved */
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x04: /* Sharp RY5HD01 */
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
+ dongle_types[dongle_id]);
+ case 0x05: /* Reserved */
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x06: /* Single-ended serial interface */
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x07: /* Consumer-IR only */
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+ 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]);
+ case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
+ switch_bank(iobase, BANK7);
+ outb_p(0x01, iobase+4);
+
+ if (speed == 4000000) {
+ save_flags(flags);
+ cli();
+ outb(0x81, iobase+4);
+ outb(0x80, iobase+4);
+ restore_flags(flags);
+ } else
+ outb_p(0x00, iobase+4);
+ break;
+ case 0x0A: /* same as */
+ case 0x0B: /* Reserved */
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
+ dongle_types[dongle_id]);
+ break;
+ case 0x0C: /* same as */
+ case 0x0D: /* HP HSDL-1100/HSDL-2100 */
+ break;
+ case 0x0E: /* Supports SIR Mode only */
+ break;
+ case 0x0F: /* No dongle connected */
+ IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
+ dongle_types[dongle_id]);
+
+ switch_bank(iobase, BANK0);
+ outb(0x62, iobase+MCR);
+ break;
+ default:
+ IRDA_DEBUG(0, __FUNCTION__ "(), invalid data_rate\n");
+ }
+ /* Restore bank register */
+ outb(bank, iobase+BSR);
+}
+
+/*
+ * Function nsc_fir_change_speed (self, baud)
+ *
+ * Change the speed of the device
+ *
+ */
+static void nsc_fir_change_speed(struct nsc_fir_cb *self, __u32 speed)
+{
+ struct net_device *dev = self->netdev;
+ __u8 mcr = MCR_SIR;
+ int iobase;
+ __u8 bank;
+
+ IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d\n", speed);
+
+ ASSERT(self != NULL, return;);
+
+ iobase = self->io.iobase;
+
+ /* Update accounting for new speed */
+ self->io.speed = speed;
+
+ /* Save current bank */
+ bank = inb(iobase+BSR);
+
+ /* Disable interrupts */
+ switch_bank(iobase, BANK0);
+ outb(0, iobase+IER);
+
+ /* Select Bank 2 */
+ switch_bank(iobase, BANK2);
+
+ outb(0x00, iobase+BGDH);
+ switch (speed) {
+ case 9600: outb(0x0c, iobase+BGDL); break;
+ case 19200: outb(0x06, iobase+BGDL); break;
+ case 38400: outb(0x03, iobase+BGDL); break;
+ case 57600: outb(0x02, iobase+BGDL); break;
+ case 115200: outb(0x01, iobase+BGDL); break;
+ case 576000:
+ switch_bank(iobase, BANK5);
+
+ /* IRCR2: MDRS is set */
+ outb(inb(iobase+4) | 0x04, iobase+4);
+
+ mcr = MCR_MIR;
+ IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+ break;
+ case 1152000:
+ mcr = MCR_MIR;
+ IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+ break;
+ case 4000000:
+ mcr = MCR_FIR;
+ IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+ break;
+ default:
+ mcr = MCR_FIR;
+ IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n",
+ speed);
+ break;
+ }
+
+ /* Set appropriate speed mode */
+ switch_bank(iobase, BANK0);
+ outb(mcr | MCR_TX_DFR, iobase+MCR);
+
+ /* Give some hits to the transceiver */
+ nsc_fir_change_dongle_speed(iobase, speed, self->io.dongle_id);
+
+ /* Set FIFO threshold to TX17, RX16 */
+ switch_bank(iobase, BANK0);
+ outb(0x00, iobase+FCR);
+ outb(FCR_FIFO_EN, iobase+FCR);
+ outb(FCR_RXTH| /* Set Rx FIFO threshold */
+ FCR_TXTH| /* Set Tx FIFO threshold */
+ FCR_TXSR| /* Reset Tx FIFO */
+ FCR_RXSR| /* Reset Rx FIFO */
+ FCR_FIFO_EN, /* Enable FIFOs */
+ iobase+FCR);
+
+ /* Set FIFO size to 32 */
+ switch_bank(iobase, BANK2);
+ outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
+
+ self->netdev->tbusy = 0;
+
+ /* Enable some interrupts so we can receive frames */
+ switch_bank(iobase, BANK0);
+ if (speed > 115200) {
+ /* Install FIR xmit handler */
+ dev->hard_start_xmit = nsc_fir_hard_xmit_fir;
+ outb(IER_SFIF_IE, iobase+IER);
+ nsc_fir_dma_receive(self);
+ } else {
+ /* Install SIR xmit handler */
+ dev->hard_start_xmit = nsc_fir_hard_xmit_sir;
+ outb(IER_RXHDL_IE, iobase+IER);
+ }
+
+ /* Restore BSR */
+ outb(bank, iobase+BSR);
+}
+
+/*
+ * Function nsc_fir_hard_xmit (skb, dev)
+ *
+ * Transmit the frame!
+ *
+ */
+static int nsc_fir_hard_xmit_sir(struct sk_buff *skb, struct net_device *dev)
+{
+ struct nsc_fir_cb *self;
+ unsigned long flags;
+ int iobase;
+ __u32 speed;
+ __u8 bank;
+
+ self = (struct nsc_fir_cb *) dev->priv;
+
+ ASSERT(self != NULL, return 0;);
+
+ iobase = self->io.iobase;
+
+ /* Lock transmit buffer */
+ if (irda_lock((void *) &dev->tbusy) == FALSE)
+ return -EBUSY;
+
+ /* Check if we need to change the speed */
+ if ((speed = irda_get_speed(skb)) != self->io.speed)
+ self->new_speed = speed;
+
+ spin_lock_irqsave(&self->lock, flags);
+
+ /* Save current bank */
+ bank = inb(iobase+BSR);
+
+ self->tx_buff.data = self->tx_buff.head;
+
+ self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
+ self->tx_buff.truesize);
+
+ /* Add interrupt on tx low level (will fire immediately) */
+ switch_bank(iobase, BANK0);
+ outb(IER_TXLDL_IE, iobase+IER);
+
+ /* Restore bank register */
+ outb(bank, iobase+BSR);
+
+ spin_unlock_irqrestore(&self->lock, flags);
+
+ dev_kfree_skb(skb);
+
+ return 0;
+}
+
+static int nsc_fir_hard_xmit_fir(struct sk_buff *skb, struct net_device *dev)
+{
+ struct nsc_fir_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;
+
+ /* Lock transmit buffer */
+ if (irda_lock((void *) &dev->tbusy) == FALSE)
+ return -EBUSY;
+
+ /* Check if we need to change the speed */
+ if ((speed = irda_get_speed(skb)) != self->io.speed)
+ self->new_speed = speed;
+
+ spin_lock_irqsave(&self->lock, flags);
+
+ /* Save current bank */
+ bank = inb(iobase+BSR);
+
+ /* Register and copy this frame to DMA memory */
+ self->tx_fifo.queue[self->tx_fifo.free].start = self->tx_fifo.tail;
+ self->tx_fifo.queue[self->tx_fifo.free].len = skb->len;
+ self->tx_fifo.tail += skb->len;
+
+ memcpy(self->tx_fifo.queue[self->tx_fifo.free].start, skb->data,
+ skb->len);
+
+ self->tx_fifo.len++;
+ self->tx_fifo.free++;
+
+ /* Start transmit only if there is currently no transmit going on */
+ if (self->tx_fifo.len == 1) {
+ mtt = irda_get_mtt(skb);
+ if (mtt) {
+ /* Check how much time we have used already */
+ do_gettimeofday(&self->now);
+ diff = self->now.tv_usec - self->stamp.tv_usec;
+ if (diff < 0)
+ diff += 1000000;
+
+ /* Check if the mtt is larger than the time we have
+ * already used by all the protocol processing
+ */
+ if (mtt > diff) {
+ mtt -= diff;
+ if (mtt > 125) {
+ /* Adjust for timer resolution */
+ mtt = mtt / 125 + 1;
+
+ /* Setup timer */
+ switch_bank(iobase, BANK4);
+ outb(mtt & 0xff, iobase+TMRL);
+ outb((mtt >> 8) & 0x0f, iobase+TMRH);
+
+ /* Start timer */
+ outb(IRCR1_TMR_EN, iobase+IRCR1);
+ self->io.direction = IO_XMIT;
+
+ /* Enable timer interrupt */
+ switch_bank(iobase, BANK0);
+ outb(IER_TMR_IE, iobase+IER);
+
+ /* Timer will take care of the rest */
+ goto out;
+ } else
+ udelay(mtt);
+ }
+ }
+
+ /* Enable DMA interrupt */
+ switch_bank(iobase, BANK0);
+ outb(IER_DMA_IE, iobase+IER);
+ nsc_fir_dma_xmit(self, iobase);
+ }
+ /* Not busy transmitting anymore if window is not full */
+ if (self->tx_fifo.len < MAX_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)
+ *
+ * Transmit data using DMA
+ *
+ */
+static void nsc_fir_dma_xmit(struct nsc_fir_cb *self, int iobase)
+{
+ int bsr;
+
+ /* Save current bank */
+ bsr = inb(iobase+BSR);
+
+ /* Disable DMA */
+ switch_bank(iobase, BANK0);
+ outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+
+ self->io.direction = IO_XMIT;
+
+ /* Choose transmit DMA channel */
+ switch_bank(iobase, BANK2);
+ outb(ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1);
+
+ setup_dma(self->io.dma,
+ self->tx_fifo.queue[self->tx_fifo.ptr].start,
+ self->tx_fifo.queue[self->tx_fifo.ptr].len,
+ DMA_TX_MODE);
+
+ /* Enable DMA and SIR interaction pulse */
+ switch_bank(iobase, BANK0);
+ outb(inb(iobase+MCR)|MCR_TX_DFR|MCR_DMA_EN|MCR_IR_PLS, iobase+MCR);
+
+ /* Restore bank register */
+ outb(bsr, iobase+BSR);
+}
+
+/*
+ * Function nsc_fir_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)
+{
+ int actual = 0;
+ __u8 bank;
+
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+ /* Save current bank */
+ bank = inb(iobase+BSR);
+
+ switch_bank(iobase, BANK0);
+ if (!(inb_p(iobase+LSR) & LSR_TXEMP)) {
+ IRDA_DEBUG(4, __FUNCTION__
+ "(), warning, FIFO not empty yet!\n");
+
+ fifo_size -= 17;
+ }
+
+ /* Fill FIFO with current frame */
+ while ((fifo_size-- > 0) && (actual < len)) {
+ /* Transmit next byte */
+ outb(buf[actual++], iobase+TXD);
+ }
+
+ IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n",
+ fifo_size, actual, len);
+
+ /* Restore bank */
+ outb(bank, iobase+BSR);
+
+ return actual;
+}
+
+/*
+ * Function nsc_fir_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)
+{
+ int iobase;
+ __u8 bank;
+ int ret = TRUE;
+
+ IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+ iobase = self->io.iobase;
+
+ /* Save current bank */
+ bank = inb(iobase+BSR);
+
+ /* Disable DMA */
+ switch_bank(iobase, BANK0);
+ outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+
+ /* Check for underrrun! */
+ if (inb(iobase+ASCR) & ASCR_TXUR) {
+ self->stats.tx_errors++;
+ self->stats.tx_fifo_errors++;
+
+ /* Clear bit, by writing 1 into it */
+ outb(ASCR_TXUR, iobase+ASCR);
+ } else {
+ self->stats.tx_packets++;
+ self->stats.tx_bytes += self->tx_buff.len;
+ }
+
+ if (self->new_speed) {
+ nsc_fir_change_speed(self, self->new_speed);
+ self->new_speed = 0;
+ }
+
+ /* Finished with this frame, so prepare for next */
+ self->tx_fifo.ptr++;
+ self->tx_fifo.len--;
+
+ /* Any frames to be sent back-to-back? */
+ if (self->tx_fifo.len) {
+ nsc_fir_dma_xmit(self, iobase);
+
+ /* Not finished yet! */
+ ret = FALSE;
+ }
+
+ /* Not busy transmitting anymore */
+ self->netdev->tbusy = 0;
+
+ /* Tell the network layer, that we can accept more frames */
+ mark_bh(NET_BH);
+
+ /* Restore bank */
+ outb(bank, iobase+BSR);
+
+ return ret;
+}
+
+/*
+ * Function nsc_fir_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)
+{
+ int iobase;
+ __u8 bsr;
+
+ ASSERT(self != NULL, return -1;);
+
+ iobase = self->io.iobase;
+
+ /* 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;
+
+ /* Save current bank */
+ bsr = inb(iobase+BSR);
+
+ /* Disable DMA */
+ switch_bank(iobase, BANK0);
+ outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
+
+ /* Choose DMA Rx, DMA Fairness, and Advanced mode */
+ switch_bank(iobase, BANK2);
+ outb(ECR1_DMANF|ECR1_EXT_SL, iobase+ECR1);
+
+ self->io.direction = IO_RECV;
+ self->rx_buff.data = self->rx_buff.head;
+
+ /* 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;
+
+ setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize,
+ DMA_RX_MODE);
+
+ /* Enable DMA */
+ switch_bank(iobase, BANK0);
+ outb(inb(iobase+MCR)|MCR_DMA_EN, iobase+MCR);
+
+ /* Restore bank register */
+ outb(bsr, iobase+BSR);
+
+ return 0;
+}
+
+/*
+ * Function nsc_fir_dma_receive_complete (self)
+ *
+ * Finished with receiving frames
+ *
+ *
+ */
+static int nsc_fir_dma_receive_complete(struct nsc_fir_cb *self, int iobase)
+{
+ struct sk_buff *skb;
+ struct st_fifo *st_fifo;
+ __u8 bank;
+ __u8 status;
+ int len;
+
+ st_fifo = &self->st_fifo;
+
+ /* Save current bank */
+ bank = inb(iobase+BSR);
+
+ /* Read status FIFO */
+ switch_bank(iobase, BANK5);
+ while ((status = inb(iobase+FRM_ST)) & FRM_ST_VLD) {
+ st_fifo->entries[st_fifo->tail].status = status;
+
+ st_fifo->entries[st_fifo->tail].len = inb(iobase+RFLFL);
+ st_fifo->entries[st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
+
+ st_fifo->tail++;
+ st_fifo->len++;
+ }
+ /* Try to process all entries in status FIFO */
+ while (st_fifo->len) {
+ /* Get first entry */
+ status = st_fifo->entries[st_fifo->head].status;
+ len = st_fifo->entries[st_fifo->head].len;
+ st_fifo->head++;
+ st_fifo->len--;
+
+ /* Check for errors */
+ if (status & FRM_ST_ERR_MSK) {
+ if (status & FRM_ST_LOST_FR) {
+ /* Add number of lost frames to stats */
+ self->stats.rx_errors += len;
+ } else {
+ /* Skip frame */
+ self->stats.rx_errors++;
+
+ self->rx_buff.data += len;
+
+ if (status & FRM_ST_MAX_LEN)
+ self->stats.rx_length_errors++;
+
+ if (status & FRM_ST_PHY_ERR)
+ self->stats.rx_frame_errors++;
+
+ if (status & FRM_ST_BAD_CRC)
+ self->stats.rx_crc_errors++;
+ }
+ /* The errors below can be reported in both cases */
+ if (status & FRM_ST_OVR1)
+ self->stats.rx_fifo_errors++;
+
+ 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);
+
+ return FALSE; /* I'll be back! */
+ }
+
+ /*
+ * Remember when 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);
+
+ skb = dev_alloc_skb(len+1);
+ if (skb == NULL) {
+ WARNING(__FUNCTION__ "(), memory squeeze, "
+ "dropping frame.\n");
+
+ /* Restore bank register */
+ outb(bank, iobase+BSR);
+
+ return FALSE;
+ }
+
+ /* Make sure IP header gets aligned */
+ skb_reserve(skb, 1);
+
+ /* Copy frame without CRC */
+ if (self->io.speed < 4000000) {
+ skb_put(skb, len-2);
+ memcpy(skb->data, self->rx_buff.data, len-2);
+ } else {
+ skb_put(skb, len-4);
+ memcpy(skb->data, self->rx_buff.data, len-4);
+ }
+
+ /* Move to next frame */
+ self->rx_buff.data += len;
+ self->stats.rx_packets++;
+
+ skb->dev = self->netdev;
+ skb->mac.raw = skb->data;
+ skb->protocol = htons(ETH_P_IRDA);
+ netif_rx(skb);
+ }
+ }
+ /* Restore bank register */
+ outb(bank, iobase+BSR);
+
+ return TRUE;
+}
+
+/*
+ * Function nsc_fir_pio_receive (self)
+ *
+ * Receive all data in receiver FIFO
+ *
+ */
+static void nsc_fir_pio_receive(struct nsc_fir_cb *self)
+{
+ __u8 byte = 0x00;
+ int iobase;
+
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+ ASSERT(self != NULL, return;);
+
+ iobase = self->io.iobase;
+
+ /* Receive all characters in Rx FIFO */
+ do {
+ byte = inb(iobase+RXD);
+ async_unwrap_char(self->netdev, &self->stats, &self->rx_buff,
+ byte);
+ } while (inb(iobase+LSR) & LSR_RXDA); /* Data available */
+}
+
+/*
+ * Function nsc_fir_sir_interrupt (self, eir)
+ *
+ * Handle SIR interrupt
+ *
+ */
+static __u8 nsc_fir_sir_interrupt(struct nsc_fir_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,
+ self->tx_buff.data,
+ self->tx_buff.len,
+ self->io.fifo_size);
+ self->tx_buff.data += actual;
+ self->tx_buff.len -= actual;
+
+ self->io.direction = IO_XMIT;
+
+ /* Check if finished */
+ if (self->tx_buff.len > 0)
+ new_ier |= IER_TXLDL_IE;
+ else {
+ self->netdev->tbusy = 0; /* Unlock */
+ self->stats.tx_packets++;
+
+ mark_bh(NET_BH);
+
+ new_ier |= IER_TXEMP_IE;
+ }
+
+ }
+ /* Check if transmission has completed */
+ if (eir & EIR_TXEMP_EV) {
+ /* 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);
+ self->new_speed = 0;
+ }
+
+ /* Turn around and get ready to receive some data */
+ self->io.direction = IO_RECV;
+ new_ier |= IER_RXHDL_IE;
+ }
+
+ /* Rx FIFO threshold or timeout */
+ if (eir & EIR_RXHDL_EV) {
+ nsc_fir_pio_receive(self);
+
+ /* Keep receiving */
+ new_ier |= IER_RXHDL_IE;
+ }
+ return new_ier;
+}
+
+/*
+ * Function nsc_fir_fir_interrupt (self, eir)
+ *
+ * Handle MIR/FIR interrupt
+ *
+ */
+static __u8 nsc_fir_fir_interrupt(struct nsc_fir_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)) {
+
+ /* Wait for next status FIFO interrupt */
+ new_ier |= IER_SFIF_IE;
+ } else {
+ /* DMA not finished yet */
+
+ /* Set timer value, resolution 125 us */
+ switch_bank(iobase, BANK4);
+ outb(0x0f, iobase+TMRL); /* 125 us * 15 */
+ outb(0x00, iobase+TMRH);
+
+ /* Start timer */
+ outb(IRCR1_TMR_EN, iobase+IRCR1);
+
+ new_ier |= IER_TMR_IE;
+ }
+ } else if (eir & EIR_TMR_EV) { /* Timer finished */
+ /* Disable timer */
+ switch_bank(iobase, BANK4);
+ outb(0, iobase+IRCR1);
+
+ /* Clear timer event */
+ switch_bank(iobase, BANK0);
+ outb(ASCR_CTE, iobase+ASCR);
+
+ /* Check if this is a TX timer interrupt */
+ if (self->io.direction == IO_XMIT) {
+ nsc_fir_dma_xmit(self, iobase);
+
+ /* Interrupt on DMA */
+ new_ier |= IER_DMA_IE;
+ } else {
+ /* Check if DMA has now finished */
+ nsc_fir_dma_receive_complete(self, iobase);
+
+ new_ier |= IER_SFIF_IE;
+ }
+ } else if (eir & EIR_DMA_EV) { /* Finished with transmission */
+ if (nsc_fir_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);
+
+ new_ier = IER_LS_IE|IER_SFIF_IE;
+ }
+ } else {
+ /* Not finished yet, so interrupt on DMA again */
+ new_ier |= IER_DMA_IE;
+ }
+ }
+ outb(bank, iobase+BSR);
+
+ return new_ier;
+}
+
+/*
+ * Function nsc_fir_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)
+{
+ struct net_device *dev = (struct net_device *) dev_id;
+ struct nsc_fir_cb *self;
+ __u8 bsr, eir, ier;
+ int iobase;
+
+ if (!dev) {
+ printk(KERN_WARNING "%s: irq %d for unknown device.\n",
+ driver_name, irq);
+ return;
+ }
+ self = (struct nsc_fir_cb *) dev->priv;
+
+ spin_lock(&self->lock);
+ dev->interrupt = 1;
+
+ iobase = self->io.iobase;
+
+ 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 */
+
+ 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);
+ else
+ ier = nsc_fir_sir_interrupt(self, eir);
+ }
+
+ outb(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)
+ *
+ * Return TRUE is we are currently receiving a frame
+ *
+ */
+static int nsc_fir_is_receiving(struct nsc_fir_cb *self)
+{
+ int status = FALSE;
+ int iobase;
+ __u8 bank;
+
+ ASSERT(self != NULL, return FALSE;);
+
+ if (self->io.speed > 115200) {
+ iobase = self->io.iobase;
+
+ /* Check if rx FIFO is not empty */
+ bank = inb(iobase+BSR);
+ switch_bank(iobase, BANK2);
+ if ((inb(iobase+RXFLV) & 0x3f) != 0) {
+ /* We are receiving something */
+ status = TRUE;
+ }
+ outb(bank, iobase+BSR);
+ } else
+ status = (self->rx_buff.state != OUTSIDE_FRAME);
+
+ return status;
+}
+
+/*
+ * Function nsc_fir_net_init (dev)
+ *
+ * Initialize network device
+ *
+ */
+static int nsc_fir_net_init(struct net_device *dev)
+{
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+ /* Setup to be a normal IrDA network device driver */
+ irda_device_setup(dev);
+
+ /* Insert overrides below this line! */
+
+ return 0;
+}
+
+/*
+ * Function nsc_fir_net_open (dev)
+ *
+ * Start the device
+ *
+ */
+static int nsc_fir_net_open(struct net_device *dev)
+{
+ struct nsc_fir_cb *self;
+ int iobase;
+ __u8 bank;
+
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+ ASSERT(dev != NULL, return -1;);
+ self = (struct nsc_fir_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))
+ {
+ return -EAGAIN;
+ }
+ /*
+ * Always allocate the DMA channel after the IRQ, and clean up on
+ * failure.
+ */
+ if (request_dma(self->io.dma, dev->name)) {
+ free_irq(self->io.irq, self);
+ return -EAGAIN;
+ }
+
+ /* Save current bank */
+ bank = inb(iobase+BSR);
+
+ /* turn on interrupts */
+ switch_bank(iobase, BANK0);
+ outb(IER_LS_IE | IER_RXHDL_IE, iobase+IER);
+
+ /* Restore bank register */
+ outb(bank, iobase+BSR);
+
+ /* Ready to play! */
+ dev->tbusy = 0;
+ dev->interrupt = 0;
+ dev->start = 1;
+
+ /*
+ * Open new IrLAP layer instance, now that everything should be
+ * initialized properly
+ */
+ self->irlap = irlap_open(dev, &self->qos);
+
+ MOD_INC_USE_COUNT;
+
+ return 0;
+}
+
+/*
+ * Function nsc_fir_net_close (dev)
+ *
+ * Stop the device
+ *
+ */
+static int nsc_fir_net_close(struct net_device *dev)
+{
+ struct nsc_fir_cb *self;
+ int iobase;
+ __u8 bank;
+
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+ ASSERT(dev != NULL, return -1;);
+ self = (struct nsc_fir_cb *) dev->priv;
+
+ ASSERT(self != NULL, return 0;);
+
+ /* Stop device */
+ dev->tbusy = 1;
+ dev->start = 0;
+
+ /* Stop and remove instance of IrLAP */
+ if (self->irlap)
+ irlap_close(self->irlap);
+ self->irlap = NULL;
+
+ iobase = self->io.iobase;
+
+ disable_dma(self->io.dma);
+
+ /* Save current bank */
+ bank = inb(iobase+BSR);
+
+ /* Disable interrupts */
+ switch_bank(iobase, BANK0);
+ outb(0, iobase+IER);
+
+ free_irq(self->io.irq, dev);
+ free_dma(self->io.dma);
+
+ /* Restore bank register */
+ outb(bank, iobase+BSR);
+
+ MOD_DEC_USE_COUNT;
+
+ return 0;
+}
+
+/*
+ * Function nsc_fir_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)
+{
+ struct if_irda_req *irq = (struct if_irda_req *) rq;
+ struct nsc_fir_cb *self;
+ unsigned long flags;
+ int ret = 0;
+
+ ASSERT(dev != NULL, return -1;);
+
+ self = dev->priv;
+
+ ASSERT(self != NULL, return -1;);
+
+ IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
+
+ /* Disable interrupts & save flags */
+ save_flags(flags);
+ cli();
+
+ switch (cmd) {
+ case SIOCSBANDWIDTH: /* Set bandwidth */
+ nsc_fir_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);
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ }
+
+ restore_flags(flags);
+
+ return ret;
+}
+
+static struct net_device_stats *nsc_fir_net_get_stats(struct net_device *dev)
+{
+ struct nsc_fir_cb *self = (struct nsc_fir_cb *) dev->priv;
+
+ return &self->stats;
+}
+
+#ifdef CONFIG_APM
+static void nsc_fir_suspend(struct nsc_fir_cb *self)
+{
+ int i = 10;
+
+ MESSAGE("%s, Suspending\n", driver_name);
+
+ if (self->suspend)
+ return;
+
+ self->suspend = 1;
+}
+
+
+static void nsc_fir_wakeup(struct nsc_fir_cb *self)
+{
+ struct net_device *dev = self->netdev;
+ unsigned long flags;
+
+ if (!self->suspend)
+ return;
+
+ save_flags(flags);
+ cli();
+
+ restore_flags(flags);
+ MESSAGE("%s, Waking up\n", driver_name);
+}
+
+static int nsc_fir_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])
+ nsc_fir_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])
+ nsc_fir_wakeup(dev_self[i]);
+ }
+ }
+ down = 0;
+ break;
+ }
+ return 0;
+}
+#endif /* CONFIG_APM */
+
+#ifdef MODULE
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("NSC FIR IrDA Device Driver");
+
+MODULE_PARM(qos_mtt_bits, "i");
+MODULE_PARM(io, "1-4i");
+MODULE_PARM(io2, "1-4i");
+MODULE_PARM(irq, "1-4i");
+MODULE_PARM(dongle_id, "i");
+
+int init_module(void)
+{
+ return nsc_fir_init();
+}
+
+void cleanup_module(void)
+{
+ nsc_fir_cleanup();
+}
+#endif /* MODULE */
+
* Status: Experimental...
* Author: Jean Tourrilhes <jt@hpl.hp.com>
* Created at: 22/11/99
- * Modified at: Fri Dec 17 09:17:30 1999
+ * Modified at: Fri Dec 17 09:13:32 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Jean Tourrilhes, All Rights Reserved.
+++ /dev/null
-/*********************************************************************
- *
- * Filename: pc87108.c
- * Version: 0.8
- * Description: FIR/MIR driver for the NS PC87108 chip
- * Status: Experimental.
- * Author: Dag Brattli <dagb@cs.uit.no>
- * Created at: Sat Nov 7 21:43:15 1998
- * Modified at: Tue Dec 21 21:51:54 1999
- * Modified by: Dag Brattli <dagb@cs.uit.no>
- *
- * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
- * Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
- * Copyright (c) 1998 Actisys Corp., www.actisys.com
- * 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 Dag Brattli nor University of Tromsø admit liability nor
- * provide warranty for any of this software. This material is
- * provided "AS-IS" and at no charge.
- *
- * Notice that all functions that needs to access the chip in _any_
- * way, must save BSR register on entry, and restore it on exit.
- * It is _very_ important to follow this policy!
- *
- * __u8 bank;
- *
- * bank = inb(iobase+BSR);
- *
- * do_your_stuff_here();
- *
- * outb(bank, iobase+BSR);
- *
- * If you find bugs in this file, its very likely that the same bug
- * will also be in w83977af_ir.c since the implementations are quite
- * similar.
- *
- ********************************************************************/
-
-#include <linux/module.h>
-
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/malloc.h>
-#include <linux/init.h>
-#include <linux/rtnetlink.h>
-
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <asm/byteorder.h>
-
-#include <net/irda/wrapper.h>
-#include <net/irda/irda.h>
-#include <net/irda/irmod.h>
-#include <net/irda/irlap_frame.h>
-#include <net/irda/irda_device.h>
-
-#include <net/irda/pc87108.h>
-
-#define BROKEN_DONGLE_ID
-
-static char *driver_name = "pc87108";
-static int qos_mtt_bits = 0x07; /* 1 ms or more */
-
-#define CHIP_IO_EXTENT 8
-
-static unsigned int io[] = { 0x2f8, ~0, ~0, ~0 };
-static unsigned int io2[] = { 0x150, 0, 0, 0 };
-static unsigned int irq[] = { 3, 0, 0, 0 };
-static unsigned int dma[] = { 0, 0, 0, 0 };
-
-static struct pc87108 *dev_self[] = { NULL, NULL, NULL, NULL};
-
-static char *dongle_types[] = {
- "Differential serial interface",
- "Differential serial interface",
- "Reserved",
- "Reserved",
- "Sharp RY5HD01",
- "Reserved",
- "Single-ended serial interface",
- "Consumer-IR only",
- "HP HSDL-2300, HP HSDL-3600/HSDL-3610",
- "IBM31T1100 or Temic TFDS6000/TFDS6500",
- "Reserved",
- "Reserved",
- "HP HSDL-1100/HSDL-2100",
- "HP HSDL-1100/HSDL-2100"
- "Supports SIR Mode only",
- "No dongle connected",
-};
-
-/* Some prototypes */
-static int pc87108_open(int i, unsigned int iobase, unsigned int board_addr,
- unsigned int irq, unsigned int dma);
-#ifdef MODULE
-static int pc87108_close(struct pc87108 *self);
-#endif /* MODULE */
-static int pc87108_probe(int iobase, int board_addr, int irq, int dma);
-static void pc87108_pio_receive(struct pc87108 *self);
-static int pc87108_dma_receive(struct pc87108 *self);
-static int pc87108_dma_receive_complete(struct pc87108 *self, int iobase);
-static int pc87108_hard_xmit(struct sk_buff *skb, struct net_device *dev);
-static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size);
-static void pc87108_dma_write(struct pc87108 *self, int iobase);
-static void pc87108_change_speed(struct pc87108 *self, __u32 baud);
-static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-static int pc87108_is_receiving(struct pc87108 *self);
-static int pc87108_read_dongle_id (int iobase);
-static void pc87108_init_dongle_interface (int iobase, int dongle_id);
-
-static int pc87108_net_init(struct net_device *dev);
-static int pc87108_net_open(struct net_device *dev);
-static int pc87108_net_close(struct net_device *dev);
-static int pc87108_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-
-/*
- * Function pc87108_init ()
- *
- * Initialize chip. Just try to find out how many chips we are dealing with
- * and where they are
- */
-int __init pc87108_init(void)
-{
- int i;
-
- for (i=0; (io[i] < 2000) && (i < 4); i++) {
- int ioaddr = io[i];
- if (check_region(ioaddr, CHIP_IO_EXTENT) < 0)
- continue;
- if (pc87108_open(i, io[i], io2[i], irq[i], dma[i]) == 0)
- return 0;
- }
- return -ENODEV;
-}
-
-/*
- * Function pc87108_cleanup ()
- *
- * Close all configured chips
- *
- */
-#ifdef MODULE
-static void pc87108_cleanup(void)
-{
- int i;
-
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
- for (i=0; i < 4; i++) {
- if (dev_self[i])
- pc87108_close(dev_self[i]);
- }
-}
-#endif /* MODULE */
-
-/*
- * Function pc87108_open (iobase, irq)
- *
- * Open driver instance
- *
- */
-static int pc87108_open(int i, unsigned int iobase, unsigned int board_addr,
- unsigned int irq, unsigned int dma)
-{
- struct net_device *dev;
- struct pc87108 *self;
- int dongle_id;
- int ret;
- int err;
-
- IRDA_DEBUG(0, __FUNCTION__ "()\n");
-
- if ((dongle_id = pc87108_probe(iobase, board_addr, irq, dma)) == -1)
- return -1;
-
- /*
- * Allocate new instance of the driver
- */
- self = kmalloc(sizeof(struct pc87108), GFP_KERNEL);
- if (self == NULL) {
- printk(KERN_ERR "IrDA: Can't allocate memory for "
- "IrDA control block!\n");
- return -ENOMEM;
- }
- memset(self, 0, sizeof(struct pc87108));
-
- /* Need to store self somewhere */
- dev_self[i] = self;
-
- /* Initialize IO */
- self->io.iobase = iobase;
- self->io.irq = irq;
- self->io.io_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);
- if (ret < 0) {
- IRDA_DEBUG(0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
- self->io.iobase);
- /* pc87108_cleanup(self->self); */
- return -ENODEV;
- }
- request_region(self->io.iobase, self->io.io_ext, driver_name);
-
- /* Initialize QoS for this device */
- irda_init_max_qos_capabilies(&self->qos);
-
- /* The only value we must override it the baudrate */
- self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
- IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
-
- self->qos.min_turn_time.bits = qos_mtt_bits;
- irda_qos_bits_to_value(&self->qos);
-
- self->flags = IFF_FIR|IFF_MIR|IFF_SIR|IFF_DMA|IFF_PIO|IFF_DONGLE;
-
- /* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
- self->rx_buff.truesize = 14384;
- self->tx_buff.truesize = 4000;
-
- /* Allocate memory if needed */
- if (self->rx_buff.truesize > 0) {
- self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
- GFP_KERNEL|GFP_DMA);
- if (self->rx_buff.head == NULL)
- return -ENOMEM;
- memset(self->rx_buff.head, 0, self->rx_buff.truesize);
- }
- if (self->tx_buff.truesize > 0) {
- self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
- GFP_KERNEL|GFP_DMA);
- if (self->tx_buff.head == NULL) {
- kfree(self->rx_buff.head);
- return -ENOMEM;
- }
- memset(self->tx_buff.head, 0, self->tx_buff.truesize);
- }
-
- self->rx_buff.in_frame = FALSE;
- self->rx_buff.state = OUTSIDE_FRAME;
- self->tx_buff.data = self->tx_buff.head;
- self->rx_buff.data = self->rx_buff.head;
-
- if (!(dev = dev_alloc("irda%d", &err))) {
- ERROR(__FUNCTION__ "(), dev_alloc() failed!\n");
- return -ENOMEM;
- }
- dev->priv = (void *) self;
- self->netdev = dev;
-
- /* Override the network functions we need to use */
- dev->init = pc87108_net_init;
- dev->hard_start_xmit = pc87108_hard_xmit;
- dev->open = pc87108_net_open;
- dev->stop = pc87108_net_close;
- dev->do_ioctl = pc87108_net_ioctl;
-
- rtnl_lock();
- err = register_netdevice(dev);
- rtnl_unlock();
- if (err) {
- ERROR(__FUNCTION__ "(), register_netdev() failed!\n");
- return -1;
- }
-
- MESSAGE("IrDA: Registered device %s\n", dev->name);
-
- self->io.dongle_id = dongle_id;
- pc87108_init_dongle_interface(iobase, dongle_id);
-
- return 0;
-}
-
-#ifdef MODULE
-/*
- * Function pc87108_close (self)
- *
- * Close driver instance
- *
- */
-static int pc87108_close(struct pc87108 *self)
-{
- int iobase;
-
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
- ASSERT(self != NULL, return -1;);
-
- iobase = self->io.iobase;
-
- /* Remove netdevice */
- if (self->netdev) {
- rtnl_lock();
- unregister_netdevice(self->netdev);
- rtnl_unlock();
- }
-
- /* 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);
-
- if (self->tx_buff.head)
- kfree(self->tx_buff.head);
-
- if (self->rx_buff.head)
- kfree(self->rx_buff.head);
-
- kfree(self);
-
- return 0;
-}
-#endif /* MODULE */
-
-/*
- * Function pc87108_probe (iobase, board_addr, irq, dma)
- *
- * Returns non-negative on success.
- *
- */
-static int pc87108_probe(int iobase, int board_addr, int irq, int dma)
-{
- int version;
- __u8 temp=0;
- int dongle_id;
-
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
- /* 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;
- default: ERROR(__FUNCTION__ "(), invalid base_address");
- }
-
- /* Control Signal Routing Register CSRT */
- switch (irq) {
- case 3: temp = 0x01; break;
- case 4: temp = 0x02; break;
- case 5: temp = 0x03; break;
- case 7: temp = 0x04; break;
- case 9: temp = 0x05; break;
- case 11: temp = 0x06; break;
- case 15: temp = 0x07; break;
- default: ERROR(__FUNCTION__ "(), invalid irq");
- }
- outb(1, board_addr);
-
- 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;
- default: IRDA_DEBUG(0, __FUNCTION__ "(), invalid dma");
- }
-
- /* Mode Control Register MCTL */
- outb(2, board_addr);
- outb(0x03, board_addr+1);
-
- /* read the Module ID */
- switch_bank(iobase, BANK3);
- version = inb(iobase+MID);
-
- /* should be 0x2? */
- if (0x20 != (version & 0xf0)) {
- ERROR(__FUNCTION__ "(), Wrong chip version %02x\n", version);
- return -1;
- }
-
- /* Switch to advanced mode */
- switch_bank(iobase, BANK2);
- outb(ECR1_EXT_SL, iobase+ECR1);
- switch_bank(iobase, BANK0);
-
- dongle_id = pc87108_read_dongle_id(iobase);
- IRDA_DEBUG(0, __FUNCTION__ "(), Found dongle: %s\n",
- dongle_types[dongle_id]);
-
- /* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */
- switch_bank(iobase, BANK0);
- outb(FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
-
- /* Set FIFO size to 32 */
- switch_bank(iobase, BANK2);
- outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
-
- /* IRCR2: FEND_MD is set */
- switch_bank(iobase, BANK5);
- outb(0x2a, iobase+4);
-
- /* Make sure that some defaults are OK */
- switch_bank(iobase, BANK6);
- outb(0x20, iobase+0); /* Set 32 bits FIR CRC */
- outb(0x0a, iobase+1); /* Set MIR pulse width */
- outb(0x0d, iobase+2); /* Set SIR pulse width */
- outb(0x2a, iobase+4); /* Set beginning frag, and preamble length */
-
- /* Receiver frame length */
- switch_bank(iobase, BANK4);
- outb(2048 & 0xff, iobase+6);
- outb((2048 >> 8) & 0x1f, iobase+7);
-
- /* Transmitter frame length */
- outb(2048 & 0xff, iobase+4);
- outb((2048 >> 8) & 0x1f, iobase+5);
-
- IRDA_DEBUG(0, "PC87108 driver loaded. Version: 0x%02x\n", version);
-
- /* Enable receive interrupts */
- switch_bank(iobase, BANK0);
- outb(IER_RXHDL_IE, iobase+IER);
-
- return dongle_id;
-}
-
-/*
- * Function pc87108_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 pc87108_read_dongle_id (int iobase)
-{
- int dongle_id;
- __u8 bank;
-
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
- bank = inb(iobase+BSR);
-
- /* Select Bank 7 */
- switch_bank(iobase, BANK7);
-
- /* IRCFG4: IRSL0_DS and IRSL21_DS are cleared */
- outb(0x00, iobase+7);
-
- /* ID0, 1, and 2 are pulled up/down very slowly */
- udelay(50);
-
- /* IRCFG1: read the ID bits */
- dongle_id = inb(iobase+4) & 0x0f;
-
-#ifdef BROKEN_DONGLE_ID
- if (dongle_id == 0x0a)
- dongle_id = 0x09;
-#endif
-
- /* Go back to bank 0 before returning */
- switch_bank(iobase, BANK0);
-
- IRDA_DEBUG(0, __FUNCTION__ "(), Dongle = %#x\n", dongle_id);
-
- outb(bank, iobase+BSR);
-
- return dongle_id;
-}
-
-/*
- * Function pc87108_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 pc87108_init_dongle_interface (int iobase, int dongle_id)
-{
- int bank;
-
- /* Save current bank */
- bank = inb(iobase+BSR);
-
- /* Select Bank 7 */
- switch_bank(iobase, BANK7);
-
- /* IRCFG4: set according to dongle_id */
- switch (dongle_id) {
- case 0x00: /* same as */
- case 0x01: /* Differential serial interface */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
- dongle_types[dongle_id]);
- break;
- case 0x02: /* same as */
- case 0x03: /* Reserved */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
- dongle_types[dongle_id]);
- break;
- case 0x04: /* Sharp RY5HD01 */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
- dongle_types[dongle_id]);
- break;
- case 0x05: /* Reserved */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet",
- dongle_types[dongle_id]);
- break;
- case 0x06: /* Single-ended serial interface */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
- dongle_types[dongle_id]);
- break;
- case 0x07: /* Consumer-IR only */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
- 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]);
- break;
- case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
- outb_p(0x28, iobase+7); /* Set irsl[0-2] as output */
- break;
- case 0x0A: /* same as */
- case 0x0B: /* Reserved */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
- dongle_types[dongle_id]);
- break;
- case 0x0C: /* same as */
- case 0x0D: /* HP HSDL-1100/HSDL-2100 */
- /*
- * Set irsl0 as input, irsl[1-2] as output, and separate
- * inputs are used for SIR and MIR/FIR
- */
- outb(0x48, iobase+7);
- break;
- case 0x0E: /* Supports SIR Mode only */
- outb(0x28, iobase+7); /* Set irsl[0-2] as output */
- break;
- case 0x0F: /* No dongle connected */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s\n",
- dongle_types[dongle_id]);
- IRDA_DEBUG(0, "***\n");
-
- switch_bank(iobase, BANK0);
- outb(0x62, iobase+MCR);
- break;
- default:
- IRDA_DEBUG(0, __FUNCTION__ "(), invalid dongle_id %#x",
- dongle_id);
- }
-
- /* IRCFG1: IRSL1 and 2 are set to IrDA mode */
- outb(0x00, iobase+4);
-
- /* Restore bank register */
- outb(bank, iobase+BSR);
-
-} /* set_up_dongle_interface */
-
-/*
- * Function pc87108_change_dongle_speed (iobase, speed, dongle_id)
- *
- * Change speed of the attach dongle
- *
- */
-static void pc87108_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);
-
- /* Select Bank 7 */
- switch_bank(iobase, BANK7);
-
- /* IRCFG1: set according to dongle_id */
- switch (dongle_id) {
- case 0x00: /* same as */
- case 0x01: /* Differential serial interface */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
- dongle_types[dongle_id]);
- break;
- case 0x02: /* same as */
- case 0x03: /* Reserved */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
- dongle_types[dongle_id]);
- break;
- case 0x04: /* Sharp RY5HD01 */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n",
- dongle_types[dongle_id]);
- case 0x05: /* Reserved */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
- dongle_types[dongle_id]);
- break;
- case 0x06: /* Single-ended serial interface */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
- dongle_types[dongle_id]);
- break;
- case 0x07: /* Consumer-IR only */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
- 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]);
- case 0x09: /* IBM31T1100 or Temic TFDS6000/TFDS6500 */
- switch_bank(iobase, BANK7);
- outb_p(0x01, iobase+4);
-
- if (speed == 4000000) {
- save_flags(flags);
- cli();
- outb(0x81, iobase+4);
- outb(0x80, iobase+4);
- restore_flags(flags);
- }
- else
- outb_p(0x00, iobase+4);
- break;
- case 0x0A: /* same as */
- case 0x0B: /* Reserved */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n",
- dongle_types[dongle_id]);
- break;
- case 0x0C: /* same as */
- case 0x0D: /* HP HSDL-1100/HSDL-2100 */
- break;
- case 0x0E: /* Supports SIR Mode only */
- break;
- case 0x0F: /* No dongle connected */
- IRDA_DEBUG(0, __FUNCTION__ "(), %s is not for IrDA mode\n",
- dongle_types[dongle_id]);
-
- switch_bank(iobase, BANK0);
- outb(0x62, iobase+MCR);
- break;
- default:
- IRDA_DEBUG(0, __FUNCTION__ "(), invalid data_rate\n");
- }
- /* Restore bank register */
- outb(bank, iobase+BSR);
-}
-
-/*
- * Function pc87108_change_speed (self, baud)
- *
- * Change the speed of the device
- *
- */
-static void pc87108_change_speed(struct pc87108 *self, __u32 speed)
-{
- __u8 mcr = MCR_SIR;
- __u8 bank;
- int iobase;
-
- IRDA_DEBUG(2, __FUNCTION__ "(), speed=%d\n", speed);
-
- ASSERT(self != NULL, return;);
-
- iobase = self->io.iobase;
-
- /* Update accounting for new speed */
- self->io.speed = speed;
-
- /* Save current bank */
- bank = inb(iobase+BSR);
-
- /* Disable interrupts */
- switch_bank(iobase, BANK0);
- outb(0, iobase+IER);
-
- /* Select Bank 2 */
- switch_bank(iobase, BANK2);
-
- outb(0x00, iobase+BGDH);
- switch (speed) {
- case 9600: outb(0x0c, iobase+BGDL); break;
- case 19200: outb(0x06, iobase+BGDL); break;
- case 37600: outb(0x03, iobase+BGDL); break;
- case 57600: outb(0x02, iobase+BGDL); break;
- case 115200: outb(0x01, iobase+BGDL); break;
- case 576000:
- switch_bank(iobase, BANK5);
-
- /* IRCR2: MDRS is set */
- outb(inb(iobase+4) | 0x04, iobase+4);
-
- mcr = MCR_MIR;
- IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
- break;
- case 1152000:
- mcr = MCR_MIR;
- IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
- break;
- case 4000000:
- mcr = MCR_FIR;
- IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
- break;
- default:
- mcr = MCR_FIR;
- IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n",
- speed);
- break;
- }
-
- /* Set appropriate speed mode */
- switch_bank(iobase, BANK0);
- outb(mcr | MCR_TX_DFR, iobase+MCR);
-
- /* Give some hits to the transceiver */
- pc87108_change_dongle_speed(iobase, speed, self->io.dongle_id);
-
- /* Set FIFO threshold to TX17, RX16 */
- switch_bank(iobase, BANK0);
- outb(FCR_RXTH| /* Set Rx FIFO threshold */
- FCR_TXTH| /* Set Tx FIFO threshold */
- FCR_TXSR| /* Reset Tx FIFO */
- FCR_RXSR| /* Reset Rx FIFO */
- FCR_FIFO_EN, /* Enable FIFOs */
- iobase+FCR);
- /* outb(0xa7, iobase+FCR); */
-
- /* Set FIFO size to 32 */
- switch_bank(iobase, BANK2);
- outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2);
-
- self->netdev->tbusy = 0;
-
- /* Enable some interrupts so we can receive frames */
- switch_bank(iobase, BANK0);
- if (speed > 115200) {
- outb(IER_SFIF_IE, iobase+IER);
- pc87108_dma_receive(self);
- } else
- outb(IER_RXHDL_IE, iobase+IER);
-
- /* Restore BSR */
- outb(bank, iobase+BSR);
-}
-
-/*
- * Function pc87108_hard_xmit (skb, dev)
- *
- * Transmit the frame!
- *
- */
-static int pc87108_hard_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct pc87108 *self;
- int iobase;
- __u32 speed;
- __u8 bank;
- int mtt;
-
- self = (struct pc87108 *) dev->priv;
-
- ASSERT(self != NULL, return 0;);
-
- iobase = self->io.iobase;
-
- IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies,
- (int) skb->len);
-
- /* Lock transmit buffer */
- if (irda_lock((void *) &dev->tbusy) == FALSE)
- return -EBUSY;
-
- /* Check if we need to change the speed */
- if ((speed = irda_get_speed(skb)) != self->io.speed)
- self->new_speed = speed;
-
- /* Save current bank */
- bank = inb(iobase+BSR);
-
- /* Decide if we should use PIO or DMA transfer */
- if (self->io.speed > 115200) {
- self->tx_buff.data = self->tx_buff.head;
- memcpy(self->tx_buff.data, skb->data, skb->len);
- self->tx_buff.len = skb->len;
-
- mtt = irda_get_mtt(skb);
- if (mtt > 50) {
- /* Adjust for timer resolution */
- mtt = mtt / 125 + 1;
-
- /* Setup timer */
- switch_bank(iobase, BANK4);
- outb(mtt & 0xff, iobase+TMRL);
- outb((mtt >> 8) & 0x0f, iobase+TMRH);
-
- /* Start timer */
- outb(IRCR1_TMR_EN, iobase+IRCR1);
- self->io.direction = IO_XMIT;
-
- /* Enable timer interrupt */
- switch_bank(iobase, BANK0);
- outb(IER_TMR_IE, iobase+IER);
- } else {
- /* Use udelay for delays less than 50 us. */
- if (mtt)
- udelay(mtt);
-
- /* Enable DMA interrupt */
- switch_bank(iobase, BANK0);
- outb(IER_DMA_IE, iobase+IER);
- pc87108_dma_write(self, iobase);
- }
- } else {
- self->tx_buff.data = self->tx_buff.head;
-
- self->tx_buff.len = async_wrap_skb(skb, self->tx_buff.data,
- self->tx_buff.truesize);
-
- /* Add interrupt on tx low level (will fire immediately) */
- switch_bank(iobase, BANK0);
- outb(IER_TXLDL_IE, iobase+IER);
- }
- dev_kfree_skb(skb);
-
- /* Restore bank register */
- outb(bank, iobase+BSR);
-
- return 0;
-}
-
-/*
- * Function pc87108_dma_xmit (self, iobase)
- *
- * Transmit data using DMA
- *
- */
-static void pc87108_dma_write(struct pc87108 *self, int iobase)
-{
- int bsr;
-
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
- /* Save current bank */
- bsr = inb(iobase+BSR);
-
- /* Disable DMA */
- switch_bank(iobase, BANK0);
- outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
-
- setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len,
- DMA_MODE_WRITE);
-
- self->io.direction = IO_XMIT;
-
- /* Choose transmit DMA channel */
- switch_bank(iobase, BANK2);
- outb(inb(iobase+ECR1) | ECR1_DMASWP|ECR1_DMANF|ECR1_EXT_SL,
- iobase+ECR1);
-
- /* Enable DMA */
- switch_bank(iobase, BANK0);
- outb(inb(iobase+MCR)|MCR_DMA_EN, iobase+MCR);
-
- /* Restore bank register */
- outb(bsr, iobase+BSR);
-}
-
-/*
- * Function pc87108_pio_xmit (self, iobase)
- *
- * Transmit data using PIO. Returns the number of bytes that actually
- * got transfered
- *
- */
-static int pc87108_pio_write(int iobase, __u8 *buf, int len, int fifo_size)
-{
- int actual = 0;
- __u8 bank;
-
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
- /* Save current bank */
- bank = inb(iobase+BSR);
-
- switch_bank(iobase, BANK0);
- if (!(inb_p(iobase+LSR) & LSR_TXEMP)) {
- IRDA_DEBUG(4, __FUNCTION__
- "(), warning, FIFO not empty yet!\n");
-
- fifo_size -= 17;
- IRDA_DEBUG(4, __FUNCTION__ "(), %d bytes left in tx fifo\n",
- fifo_size);
- }
-
- /* Fill FIFO with current frame */
- while ((fifo_size-- > 0) && (actual < len)) {
- /* Transmit next byte */
- outb(buf[actual++], iobase+TXD);
- }
-
- IRDA_DEBUG(4, __FUNCTION__ "(), fifo_size %d ; %d sent of %d\n",
- fifo_size, actual, len);
-
- /* Restore bank */
- outb(bank, iobase+BSR);
-
- return actual;
-}
-
-/*
- * Function pc87108_dma_xmit_complete (self)
- *
- * The transfer of a frame in finished. This function will only be called
- * by the interrupt handler
- *
- */
-static void pc87108_dma_xmit_complete(struct pc87108 *self)
-{
- int iobase;
- __u8 bank;
-
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
- ASSERT(self != NULL, return;);
-
- iobase = self->io.iobase;
-
- /* Save current bank */
- bank = inb(iobase+BSR);
-
- /* Disable DMA */
- switch_bank(iobase, BANK0);
- outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
-
- /* Check for underrrun! */
- if (inb(iobase+ASCR) & ASCR_TXUR) {
- self->stats.tx_errors++;
- self->stats.tx_fifo_errors++;
-
- /* Clear bit, by writing 1 into it */
- outb(ASCR_TXUR, iobase+ASCR);
- } else {
- self->stats.tx_packets++;
- self->stats.tx_bytes += self->tx_buff.len;
- }
-
- if (self->new_speed) {
- pc87108_change_speed(self, self->new_speed);
- self->new_speed = 0;
- }
-
- /* Unlock tx_buff and request another frame */
- self->netdev->tbusy = 0; /* Unlock */
-
- /* Tell the network layer, that we can accept more frames */
- mark_bh(NET_BH);
-
- /* Restore bank */
- outb(bank, iobase+BSR);
-}
-
-/*
- * Function pc87108_dma_receive (self)
- *
- * Get ready for receiving a frame. The device will initiate a DMA
- * if it starts to receive a frame.
- *
- */
-static int pc87108_dma_receive(struct pc87108 *self)
-{
- int iobase;
- __u8 bsr;
-
- ASSERT(self != NULL, return -1;);
-
- IRDA_DEBUG(4, __FUNCTION__ "\n");
-
- iobase = self->io.iobase;
-
- /* Save current bank */
- bsr = inb(iobase+BSR);
-
- /* Disable DMA */
- switch_bank(iobase, BANK0);
- outb(inb(iobase+MCR) & ~MCR_DMA_EN, iobase+MCR);
-
- self->rx_buff.data = self->rx_buff.head;
-
- setup_dma(self->io.dma, self->rx_buff.data,
- self->rx_buff.truesize, DMA_MODE_READ);
-
- /* driver->media_busy = FALSE; */
- self->io.direction = IO_RECV;
-
- /* Reset Rx FIFO. This will also flush the ST_FIFO */
- outb(FCR_RXTH|FCR_TXTH|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
- self->st_fifo.len = self->st_fifo.tail = self->st_fifo.head = 0;
-
- /* Choose DMA Rx, DMA Fairness, and Advanced mode */
- switch_bank(iobase, BANK2);
- outb((inb(iobase+ECR1) & ~ECR1_DMASWP)|ECR1_DMANF|ECR1_EXT_SL,
- iobase+ECR1);
-
- /* enable DMA */
- switch_bank(iobase, BANK0);
- outb(inb(iobase+MCR)|MCR_DMA_EN, iobase+MCR);
-
- /* Restore bank register */
- outb(bsr, iobase+BSR);
-
- IRDA_DEBUG(4, __FUNCTION__ "(), done!\n");
-
- return 0;
-}
-
-/*
- * Function pc87108_dma_receive_complete (self)
- *
- * Finished with receiving frames
- *
- *
- */
-static int pc87108_dma_receive_complete(struct pc87108 *self, int iobase)
-{
- struct sk_buff *skb;
- struct st_fifo *st_fifo;
- __u8 bank;
- __u8 status;
- int len;
-
- st_fifo = &self->st_fifo;
-
- /* Save current bank */
- bank = inb(iobase+BSR);
-
- /* Read status FIFO */
- switch_bank(iobase, BANK5);
- while ((status = inb(iobase+FRM_ST)) & FRM_ST_VLD) {
- st_fifo->entries[st_fifo->tail].status = status;
-
- st_fifo->entries[st_fifo->tail].len = inb(iobase+RFLFL);
- st_fifo->entries[st_fifo->tail].len |= inb(iobase+RFLFH) << 8;
-
- st_fifo->tail++;
- st_fifo->len++;
- }
-
- /* Try to process all entries in status FIFO */
- switch_bank(iobase, BANK0);
- while (st_fifo->len) {
-
- /* Get first entry */
- status = st_fifo->entries[st_fifo->head].status;
- len = st_fifo->entries[st_fifo->head].len;
- st_fifo->head++;
- st_fifo->len--;
-
- /* Check for errors */
- if (status & FRM_ST_ERR_MSK) {
- if (status & FRM_ST_LOST_FR) {
- /* Add number of lost frames to stats */
- self->stats.rx_errors += len;
- } else {
- /* Skip frame */
- self->stats.rx_errors++;
-
- self->rx_buff.data += len;
-
- if (status & FRM_ST_MAX_LEN)
- self->stats.rx_length_errors++;
-
- if (status & FRM_ST_PHY_ERR)
- self->stats.rx_frame_errors++;
-
- if (status & FRM_ST_BAD_CRC)
- self->stats.rx_crc_errors++;
- }
- /* The errors below can be reported in both cases */
- if (status & FRM_ST_OVR1)
- self->stats.rx_fifo_errors++;
-
- if (status & FRM_ST_OVR2)
- self->stats.rx_fifo_errors++;
-
- } else {
- /* Check if we have transfered all data to memory */
- 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);
-
- return FALSE; /* I'll be back! */
- }
-
- /* Should be OK then */
- skb = dev_alloc_skb(len+1);
- if (skb == NULL) {
- printk(KERN_INFO __FUNCTION__
- "(), memory squeeze, dropping frame.\n");
- /* Restore bank register */
- outb(bank, iobase+BSR);
-
- return FALSE;
- }
-
- /* Make sure IP header gets aligned */
- skb_reserve(skb, 1);
-
- /* Copy frame without CRC */
- if (self->io.speed < 4000000) {
- skb_put(skb, len-2);
- memcpy(skb->data, self->rx_buff.data, len-2);
- } else {
- skb_put(skb, len-4);
- memcpy(skb->data, self->rx_buff.data, len-4);
- }
-
- /* Move to next frame */
- self->rx_buff.data += len;
- self->stats.rx_packets++;
-
- skb->dev = self->netdev;
- skb->mac.raw = skb->data;
- skb->protocol = htons(ETH_P_IRDA);
- netif_rx(skb);
- }
- }
- /* Restore bank register */
- outb(bank, iobase+BSR);
-
- return TRUE;
-}
-
-/*
- * Function pc87108_pio_receive (self)
- *
- * Receive all data in receiver FIFO
- *
- */
-static void pc87108_pio_receive(struct pc87108 *self)
-{
- __u8 byte = 0x00;
- int iobase;
-
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
- ASSERT(self != NULL, return;);
-
- iobase = self->io.iobase;
-
- /* Receive all characters in Rx FIFO */
- do {
- byte = inb(iobase+RXD);
- async_unwrap_char(self->netdev, &self->stats, &self->rx_buff, byte);
- } while (inb(iobase+LSR) & LSR_RXDA); /* Data available */
-}
-
-/*
- * Function pc87108_sir_interrupt (self, eir)
- *
- * Handle SIR interrupt
- *
- */
-static __u8 pc87108_sir_interrupt(struct pc87108 *self, int eir)
-{
- int actual;
- __u8 new_ier = 0;
-
- /* Transmit FIFO low on data */
- if (eir & EIR_TXLDL_EV) {
- /* Write data left in transmit buffer */
- actual = pc87108_pio_write(self->io.iobase,
- self->tx_buff.data,
- self->tx_buff.len,
- self->io.fifo_size);
- self->tx_buff.data += actual;
- self->tx_buff.len -= actual;
-
- self->io.direction = IO_XMIT;
-
- /* Check if finished */
- if (self->tx_buff.len > 0)
- new_ier |= IER_TXLDL_IE;
- else {
- self->netdev->tbusy = 0; /* Unlock */
- self->stats.tx_packets++;
-
- /* Check if we need to change the speed? */
- if (self->new_speed) {
- IRDA_DEBUG(2, __FUNCTION__
- "(), Changing speed!\n");
- pc87108_change_speed(self, self->new_speed);
- self->new_speed = 0;
- }
-
- mark_bh(NET_BH);
-
- new_ier |= IER_TXEMP_IE;
- }
-
- }
- /* Check if transmission has completed */
- if (eir & EIR_TXEMP_EV) {
- /* Check if we need to change the speed? */
- if (self->new_speed) {
- IRDA_DEBUG(2, __FUNCTION__
- "(), Changing speed!\n");
- pc87108_change_speed(self, self->new_speed);
- self->new_speed = 0;
- }
-
- /* Turn around and get ready to receive some data */
- self->io.direction = IO_RECV;
- new_ier |= IER_RXHDL_IE;
- }
-
- /* Rx FIFO threshold or timeout */
- if (eir & EIR_RXHDL_EV) {
- pc87108_pio_receive(self);
-
- /* Keep receiving */
- new_ier |= IER_RXHDL_IE;
- }
- return new_ier;
-}
-
-/*
- * Function pc87108_fir_interrupt (self, eir)
- *
- * Handle MIR/FIR interrupt
- *
- */
-static __u8 pc87108_fir_interrupt(struct pc87108 *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 (pc87108_dma_receive_complete(self, iobase)) {
-
- /* Wait for next status FIFO interrupt */
- new_ier |= IER_SFIF_IE;
- } else {
- /* DMA not finished yet */
-
- /* Set timer value, resolution 125 us */
- switch_bank(iobase, BANK4);
- outb(0x0f, iobase+TMRL); /* 125 us */
- outb(0x00, iobase+TMRH);
-
- /* Start timer */
- outb(IRCR1_TMR_EN, iobase+IRCR1);
-
- new_ier |= IER_TMR_IE;
- }
- }
- /* Timer finished */
- if (eir & EIR_TMR_EV) {
- /* Disable timer */
- switch_bank(iobase, BANK4);
- outb(0, iobase+IRCR1);
-
- /* Clear timer event */
- switch_bank(iobase, BANK0);
- outb(ASCR_CTE, iobase+ASCR);
-
- /* Check if this is a TX timer interrupt */
- if (self->io.direction == IO_XMIT) {
- pc87108_dma_write(self, iobase);
-
- /* Interrupt on DMA */
- new_ier |= IER_DMA_IE;
- } else {
- /* Check if DMA has now finished */
- pc87108_dma_receive_complete(self, iobase);
-
- new_ier |= IER_SFIF_IE;
- }
- }
- /* Finished with transmission */
- if (eir & EIR_DMA_EV) {
- pc87108_dma_xmit_complete(self);
-
- /* Check if there are more frames to be transmitted */
- if (irda_device_txqueue_empty(self->netdev)) {
- /* Prepare for receive */
- pc87108_dma_receive(self);
-
- new_ier = IER_LS_IE|IER_SFIF_IE;
- }
- }
- outb(bank, iobase+BSR);
-
- return new_ier;
-}
-
-/*
- * Function pc87108_interrupt (irq, dev_id, regs)
- *
- * An interrupt from the chip has arrived. Time to do some work
- *
- */
-static void pc87108_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct net_device *dev = (struct net_device *) dev_id;
- struct pc87108 *self;
- __u8 bsr, eir, ier;
- int iobase;
-
- if (!dev) {
- printk(KERN_WARNING "%s: irq %d for unknown device.\n",
- driver_name, irq);
- return;
- }
- self = (struct pc87108 *) dev->priv;
-
- dev->interrupt = 1;
-
- iobase = self->io.iobase;
-
- /* Save current bank */
- bsr = inb(iobase+BSR);
-
- switch_bank(iobase, BANK0);
- ier = inb(iobase+IER);
- eir = inb(iobase+EIR) & 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 = pc87108_fir_interrupt(self, iobase, eir);
- else
- ier = pc87108_sir_interrupt(self, eir);
- }
-
- outb(ier, iobase+IER); /* Restore interrupts */
- outb(bsr, iobase+BSR); /* Restore bank register */
-
- dev->interrupt = 0;
-}
-
-/*
- * Function pc87108_is_receiving (self)
- *
- * Return TRUE is we are currently receiving a frame
- *
- */
-static int pc87108_is_receiving(struct pc87108 *self)
-{
- int status = FALSE;
- int iobase;
- __u8 bank;
-
- ASSERT(self != NULL, return FALSE;);
-
- if (self->io.speed > 115200) {
- iobase = self->io.iobase;
-
- /* Check if rx FIFO is not empty */
- bank = inb(iobase+BSR);
- switch_bank(iobase, BANK2);
- if ((inb(iobase+RXFLV) & 0x3f) != 0) {
- /* We are receiving something */
- status = TRUE;
- }
- outb(bank, iobase+BSR);
- } else
- status = (self->rx_buff.state != OUTSIDE_FRAME);
-
- return status;
-}
-
-/*
- * Function pc87108_net_init (dev)
- *
- * Initialize network device
- *
- */
-static int pc87108_net_init(struct net_device *dev)
-{
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
- /* Setup to be a normal IrDA network device driver */
- irda_device_setup(dev);
-
- /* Insert overrides below this line! */
-
- return 0;
-}
-
-
-/*
- * Function pc87108_net_open (dev)
- *
- * Start the device
- *
- */
-static int pc87108_net_open(struct net_device *dev)
-{
- struct pc87108 *self;
- int iobase;
- __u8 bank;
-
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
- ASSERT(dev != NULL, return -1;);
- self = (struct pc87108 *) dev->priv;
-
- ASSERT(self != NULL, return 0;);
-
- iobase = self->io.iobase;
-
- if (request_irq(self->io.irq, pc87108_interrupt, 0, dev->name,
- (void *) dev))
- {
- return -EAGAIN;
- }
- /*
- * Always allocate the DMA channel after the IRQ,
- * and clean up on failure.
- */
- if (request_dma(self->io.dma, dev->name)) {
- free_irq(self->io.irq, self);
- return -EAGAIN;
- }
-
- /* Save current bank */
- bank = inb(iobase+BSR);
-
- /* turn on interrupts */
- switch_bank(iobase, BANK0);
- outb(IER_LS_IE | IER_RXHDL_IE, iobase+IER);
-
- /* Restore bank register */
- outb(bank, iobase+BSR);
-
- /* Ready to play! */
- dev->tbusy = 0;
- dev->interrupt = 0;
- dev->start = 1;
-
- /*
- * Open new IrLAP layer instance, now that everything should be
- * initialized properly
- */
- self->irlap = irlap_open(dev, &self->qos);
-
- MOD_INC_USE_COUNT;
-
- return 0;
-}
-
-/*
- * Function pc87108_net_close (dev)
- *
- * Stop the device
- *
- */
-static int pc87108_net_close(struct net_device *dev)
-{
- struct pc87108 *self;
- int iobase;
- __u8 bank;
-
- IRDA_DEBUG(4, __FUNCTION__ "()\n");
-
- ASSERT(dev != NULL, return -1;);
- self = (struct pc87108 *) dev->priv;
-
- ASSERT(self != NULL, return 0;);
-
- /* Stop device */
- dev->tbusy = 1;
- dev->start = 0;
-
- /* Stop and remove instance of IrLAP */
- if (self->irlap)
- irlap_close(self->irlap);
- self->irlap = NULL;
-
- iobase = self->io.iobase;
-
- disable_dma(self->io.dma);
-
- /* Save current bank */
- bank = inb(iobase+BSR);
-
- /* Disable interrupts */
- switch_bank(iobase, BANK0);
- outb(0, iobase+IER);
-
- free_irq(self->io.irq, dev);
- free_dma(self->io.dma);
-
- /* Restore bank register */
- outb(bank, iobase+BSR);
-
- MOD_DEC_USE_COUNT;
-
- return 0;
-}
-
-/*
- * Function pc87108_net_ioctl (dev, rq, cmd)
- *
- * Process IOCTL commands for this device
- *
- */
-static int pc87108_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- struct if_irda_req *irq = (struct if_irda_req *) rq;
- struct pc87108 *self;
- unsigned long flags;
- int ret = 0;
-
- ASSERT(dev != NULL, return -1;);
-
- self = dev->priv;
-
- ASSERT(self != NULL, return -1;);
-
- IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd);
-
- /* Disable interrupts & save flags */
- save_flags(flags);
- cli();
-
- switch (cmd) {
- case SIOCSBANDWIDTH: /* Set bandwidth */
- pc87108_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 = pc87108_is_receiving(self);
- break;
- default:
- ret = -EOPNOTSUPP;
- }
-
- restore_flags(flags);
-
- return ret;
-}
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
-MODULE_DESCRIPTION("NSC PC87108 IrDA Device Driver");
-
-MODULE_PARM(qos_mtt_bits, "i");
-MODULE_PARM(io, "1-4i");
-MODULE_PARM(io2, "1-4i");
-MODULE_PARM(irq, "1-4i");
-
-/*
- * Function init_module (void)
- *
- *
- *
- */
-int init_module(void)
-{
- return pc87108_init();
-}
-
-/*
- * Function cleanup_module (void)
- *
- *
- *
- */
-void cleanup_module(void)
-{
- pc87108_cleanup();
-}
-#endif /* MODULE */
-
/*********************************************************************
*
* Filename: smc-ircc.c
- * Version: 0.1
- * Description: Driver for the SMC Infrared Communications Controller (SMC)
+ * Version: 0.3
+ * Description: Driver for the SMC Infrared Communications Controller
* Status: Experimental.
* Author: Thomas Davis (tadavis@jps.net)
* Created at:
- * Modified at: Sat Dec 11 14:38:26 1999
+ * Modified at: Wed Jan 5 12:38:06 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
- * Copyright (c) 1998-1999 Thomas Davis, All Rights Reserved.
+ * Copyright (c) 1999-2000 Dag Brattli
+ * Copyright (c) 1998-1999 Thomas Davis,
+ * 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.
- *
- * I, Thomas Davis, admit no liability nor provide warranty for any
- * of this software. This material is provided "AS-IS" and at no charge.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
*
- * Applicable Models : Fujitsu Lifebook 635t
- * Sony PCG-505TX (gets DMA wrong.)
+ * SIO's: SMC FDC37N869, FDC37C669
+ * Applicable Models : Fujitsu Lifebook 635t, Sony PCG-505TX
*
********************************************************************/
#define CHIP_IO_EXTENT 8
-static unsigned int io[] = { 0x2e8, 0x140, 0x118, ~0 };
-static unsigned int io2[] = { 0x2f8, 0x3e8, 0x2e8, 0};
+static unsigned int io[] = { 0x2e8, 0x140, 0x118, 0x240 };
+static unsigned int io2[] = { 0x2f8, 0x3e8, 0x2e8, 0x3e8 };
static struct ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL};
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_hard_xmit(struct sk_buff *skb, struct net_device *dev);
-static void ircc_dma_write(struct ircc_cb *self, int iobase);
+static void ircc_dma_xmit(struct ircc_cb *self, int iobase);
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);
-static int ircc_debug=3;
static int ircc_irq=255;
static int ircc_dma=255;
-static inline void register_bank(int port, int bank)
-{
- outb(((inb(port+UART_MASTER) & 0xF0) | (bank & 0x07)),
- port+UART_MASTER);
-}
-
-static inline unsigned int serial_in(int port, int offset)
+static inline void register_bank(int iobase, int bank)
{
- return inb(port+offset);
-}
-
-static inline void serial_out(int port, int offset, int value)
-{
- outb(value, port+offset);
+ outb(((inb(iobase+IRCC_MASTER) & 0xf0) | (bank & 0x07)),
+ iobase+IRCC_MASTER);
}
/*
*/
int __init ircc_init(void)
{
+ int ioaddr, ioaddr2;
int i;
- IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ 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))
if (ircc_open(i, io[i], io2[i]) == 0)
return 0;
}
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
+
+ /* 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;
+ }
return -ENODEV;
}
{
int i;
- IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(0, __FUNCTION__ "\n");
for (i=0; i < 4; i++) {
if (dev_self[i])
ircc_close(dev_self[i]);
}
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
}
#endif /* MODULE */
int config;
int ret;
- IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(0, __FUNCTION__ "\n");
if ((config = ircc_probe(iobase, iobase2)) == -1) {
- IRDA_DEBUG(ircc_debug,
- __FUNCTION__ ": addr 0x%04x - no device found!\n", iobase);
+ IRDA_DEBUG(0, __FUNCTION__
+ "(), addr 0x%04x - no device found!\n", iobase);
return -1;
}
*/
self = kmalloc(sizeof(struct ircc_cb), GFP_KERNEL);
if (self == NULL) {
- printk(KERN_ERR "IrDA: Can't allocate memory for "
- "IrDA control block!\n");
+ ERROR("%s, Can't allocate memory for control block!\n",
+ driver_name);
return -ENOMEM;
}
memset(self, 0, sizeof(struct ircc_cb));
+ spin_lock_init(&self->lock);
/* Need to store self somewhere */
dev_self[i] = self;
self->io.iobase2 = iobase2; /* Used by irport */
self->io.irq = config >> 4 & 0x0f;
if (ircc_irq < 255) {
- MESSAGE("smc_ircc: Overriding IRQ - chip says %d, using %d\n",
- self->io.irq, ircc_irq);
+ 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.dma = config & 0x0f;
if (ircc_dma < 255) {
- MESSAGE("smc: Overriding DMA - chip says %d, using %d\n",
- self->io.dma, ircc_dma);
+ 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;
ret = check_region(self->io.iobase, self->io.io_ext);
if (ret < 0) {
IRDA_DEBUG(0, __FUNCTION__ ": can't get iobase of 0x%03x\n",
- self->io.iobase);
+ self->io.iobase);
/* ircc_cleanup(self->self); */
return -ENODEV;
}
request_region(self->io.iobase, self->io.io_ext, driver_name);
/* Initialize QoS for this device */
- irda_init_max_qos_capabilies(&self->qos);
+ irda_init_max_qos_capabilies(&irport->qos);
-#if 1
/* The only value we must override it the baudrate */
- self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+ irport->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
-#else
- /* The only value we must override it the baudrate */
- self->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
- IR_115200;
-#endif
irport->qos.min_turn_time.bits = 0x07;
irda_qos_bits_to_value(&irport->qos);
self->rx_buff.truesize = 4000;
self->tx_buff.truesize = 4000;
- /* Allocate memory if needed */
- if (self->rx_buff.truesize > 0) {
- self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
- GFP_KERNEL|GFP_DMA);
- if (self->rx_buff.head == NULL)
- return -ENOMEM;
- memset(self->rx_buff.head, 0, self->rx_buff.truesize);
- }
- if (self->tx_buff.truesize > 0) {
- self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
- GFP_KERNEL|GFP_DMA);
- if (self->tx_buff.head == NULL) {
- kfree(self->rx_buff.head);
- return -ENOMEM;
- }
- memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+ self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+ GFP_KERNEL|GFP_DMA);
+ if (self->rx_buff.head == NULL)
+ 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->rx_buff.head);
+ return -ENOMEM;
}
+ memset(self->tx_buff.head, 0, self->tx_buff.truesize);
self->rx_buff.in_frame = FALSE;
self->rx_buff.state = OUTSIDE_FRAME;
/* Override the speed change function, since we must control it now */
irport->change_speed = &ircc_change_speed;
- self->netdev->open = &ircc_net_open;
- self->netdev->stop = &ircc_net_close;
+ self->netdev->open = &ircc_net_open;
+ self->netdev->stop = &ircc_net_close;
irport_start(self->irport);
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
return 0;
}
{
int iobase;
- IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(0, __FUNCTION__ "\n");
ASSERT(self != NULL, return -1;);
irport_close(self->irport);
register_bank(iobase, 0);
- serial_out(iobase, UART_IER, 0);
- serial_out(iobase, UART_MASTER, UART_MASTER_RESET);
+ outb(0, iobase+IRCC_IER);
+ outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
register_bank(iobase, 1);
- serial_out(iobase, UART_SCE_CFGA,
- UART_CFGA_IRDA_SIR_A | UART_CFGA_TX_POLARITY);
- serial_out(iobase, UART_SCE_CFGB, UART_CFGB_IR);
+ outb(IRCC_CFGA_IRDA_SIR_A|IRCC_CFGA_TX_POLARITY, iobase+IRCC_SCE_CFGA);
+ outb(IRCC_CFGB_IR, iobase+IRCC_SCE_CFGB);
/* Release the PORT that this driver is using */
- IRDA_DEBUG(ircc_debug,
- __FUNCTION__ ": releasing 0x%03x\n", self->io.iobase);
+ IRDA_DEBUG(0, __FUNCTION__ "(), releasing 0x%03x\n", self->io.iobase);
release_region(self->io.iobase, self->io.io_ext);
kfree(self);
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
-
return 0;
}
#endif /* MODULE */
+/*
+ * Function ircc_probe_smc (ioaddr, ioaddr2)
+ *
+ * Probe the SMC Chip for an IrDA port
+ *
+ */
+static int ircc_probe_smc(int *ioaddr, int *ioaddr2)
+{
+ static int smcreg[] = { 0x3f0, 0x370 };
+ __u8 devid, mode;
+ __u8 conf_reg;
+ int ret = -1;
+ 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);
+
+ /* 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;
+ }
+ }
+ }
+
+ /* Exit configuration */
+ outb(0xaa, conf_reg);
+ }
+ return ret;
+}
+
/*
* Function ircc_probe (iobase, board_addr, irq, dma)
*
int version = 1;
int low, high, chip, config, dma, irq;
- IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(0, __FUNCTION__ "\n");
+
+ /* Power on device */
+ outb(inb(iobase+IRCC_MASTER) & ~IRCC_MASTER_POWERDOWN,
+ iobase+IRCC_MASTER);
register_bank(iobase, 3);
- high = serial_in(iobase, UART_ID_HIGH);
- low = serial_in(iobase, UART_ID_LOW);
- chip = serial_in(iobase, UART_CHIP_ID);
- version = serial_in(iobase, UART_VERSION);
- config = serial_in(iobase, UART_INTERFACE);
+ 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;
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);
- } else {
+ } else
return -1;
- }
- serial_out(iobase, UART_MASTER, 0);
-
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
+ outb(0, iobase+IRCC_MASTER);
return config;
}
struct ircc_cb *self = (struct ircc_cb *) priv;
struct net_device *dev;
- IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(0, __FUNCTION__ "\n");
ASSERT(self != NULL, return;);
switch (speed) {
case 9600:
case 19200:
- case 37600:
+ case 38400:
case 57600:
case 115200:
- IRDA_DEBUG(ircc_debug+1,
- __FUNCTION__ ": using irport to change speed to %d\n",
- speed);
+ IRDA_DEBUG(0, __FUNCTION__
+ "(), using irport to change speed to %d\n", speed);
+
register_bank(iobase, 0);
- serial_out(iobase, UART_IER, 0);
- serial_out(iobase, UART_MASTER, UART_MASTER_RESET);
- serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
+ 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;
irport_change_speed(self->irport, speed);
return;
break;
-
case 576000:
- ir_mode = UART_CFGA_IRDA_HDLC;
+ ir_mode = IRCC_CFGA_IRDA_HDLC;
select = 0;
fast = 0;
- IRDA_DEBUG(ircc_debug, __FUNCTION__
- "(), handling baud of 576000\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
break;
case 1152000:
- ir_mode = UART_CFGA_IRDA_HDLC;
- select = UART_1152;
+ ir_mode = IRCC_CFGA_IRDA_HDLC;
+ select = IRCC_1152;
fast = 0;
- IRDA_DEBUG(ircc_debug, __FUNCTION__
- "(), handling baud of 1152000\n");
+ IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
break;
case 4000000:
- ir_mode = UART_CFGA_IRDA_4PPM;
+ ir_mode = IRCC_CFGA_IRDA_4PPM;
select = 0;
- fast = UART_LCR_A_FAST;
- IRDA_DEBUG(ircc_debug, __FUNCTION__
- "(), handling baud of 4000000\n");
+ fast = IRCC_LCR_A_FAST;
+ IRDA_DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
break;
default:
IRDA_DEBUG(0, __FUNCTION__ "(), unknown baud rate of %d\n",
return;
}
-#if 0
- serial_out(self->io.iobase2, 4, 0x08);
-#endif
-
- serial_out(iobase, UART_MASTER, UART_MASTER_RESET);
+ outb(IRCC_MASTER_RESET, iobase+IRCC_MASTER);
register_bank(iobase, 0);
- serial_out(iobase, UART_IER, 0);
+ outb(0, iobase+IRCC_IER);
irport_stop(self->irport);
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);
- serial_out(iobase, UART_SCE_CFGA,
- ((serial_in(iobase, UART_SCE_CFGA) & 0x87) | ir_mode));
-
- serial_out(iobase, UART_SCE_CFGB,
- ((serial_in(iobase, UART_SCE_CFGB) & 0x3f) | UART_CFGB_IR));
-
- (void) serial_in(iobase, UART_FIFO_THRESHOLD);
- serial_out(iobase, UART_FIFO_THRESHOLD, 64);
+ (void) inb(iobase+IRCC_FIFO_THRESHOLD);
+ outb(64, iobase+IRCC_FIFO_THRESHOLD);
register_bank(iobase, 4);
- serial_out(iobase, UART_CONTROL,
- (serial_in(iobase, UART_CONTROL) & 0x30)
- | select | UART_CRC );
+ outb((inb(iobase+IRCC_CONTROL) & 0x30) | select | IRCC_CRC,
+ iobase+IRCC_CONTROL);
register_bank(iobase, 0);
- serial_out(iobase, UART_LCR_A, fast);
-
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
+ outb(fast, iobase+IRCC_LCR_A);
}
/*
int mtt;
__u32 speed;
- IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
irport = (struct irport_cb *) dev->priv;
self = (struct ircc_cb *) irport->priv;
iobase = self->io.iobase;
- IRDA_DEBUG(ircc_debug+1, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies,
+ IRDA_DEBUG(2, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies,
(int) skb->len);
/* Check if we need to change the speed */
if ((speed = irda_get_speed(skb)) != self->io.speed)
self->new_speed = speed;
- IRDA_DEBUG(ircc_debug, __FUNCTION__ ": using dma; len=%d\n", skb->len);
-
/* Lock transmit buffer */
if (irda_lock((void *) &dev->tbusy) == FALSE)
return -EBUSY;
self->tx_buff.len = skb->len;
self->tx_buff.data = self->tx_buff.head;
-#if 0
- self->tx_buff.offset = 0;
-#endif
- mtt = irda_get_mtt(skb);
-
- /* Use udelay for delays less than 50 us. */
+ mtt = irda_get_mtt(skb);
if (mtt)
udelay(mtt);
- ircc_dma_write(self, iobase);
+ ircc_dma_xmit(self, iobase);
dev_kfree_skb(skb);
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
return 0;
}
* Transmit data using DMA
*
*/
-static void ircc_dma_write(struct ircc_cb *self, int iobase)
+static void ircc_dma_xmit(struct ircc_cb *self, int iobase)
{
- IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(2, __FUNCTION__ "\n");
ASSERT(self != NULL, return;);
iobase = self->io.iobase;
setup_dma(self->io.dma, self->tx_buff.data, self->tx_buff.len,
- DMA_MODE_WRITE);
+ DMA_TX_MODE);
self->io.direction = IO_XMIT;
- serial_out(self->io.iobase2, 4, 0x08);
-
+ outb(0x08, self->io.iobase2+4);
+
register_bank(iobase, 4);
- serial_out(iobase, UART_CONTROL,
- (serial_in(iobase, UART_CONTROL) & 0xF0));
-
- serial_out(iobase, UART_BOF_COUNT_LO, 2);
- serial_out(iobase, UART_BRICKWALL_CNT_LO, 0);
+ 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
- serial_out(iobase, UART_BRICKWALL_TX_CNT_HI, self->tx_buff.len >> 8);
- serial_out(iobase, UART_TX_SIZE_LO, self->tx_buff.len & 0xff);
+ outb(self->tx_buff.len >> 8, iobase+IRCC_BRICKWALL_TX_CNT_HI);
+ outb(self->tx_buff.len & 0xff, iobase+IRCC_TX_SIZE_LO);
#else
- serial_out(iobase, UART_BRICKWALL_TX_CNT_HI, 0);
- serial_out(iobase, UART_TX_SIZE_LO, 0);
+ outb(0, iobase+IRCC_BRICKWALL_TX_CNT_HI);
+ outb(0, iobase+IRCC_TX_SIZE_LO);
#endif
register_bank(iobase, 1);
- serial_out(iobase, UART_SCE_CFGB,
- serial_in(iobase, UART_SCE_CFGB) | UART_CFGB_DMA_ENABLE);
+ outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE,
+ iobase+IRCC_SCE_CFGB);
register_bank(iobase, 0);
- serial_out(iobase, UART_IER, UART_IER_ACTIVE_FRAME | UART_IER_EOM);
- serial_out(iobase, UART_LCR_B,
- UART_LCR_B_SCE_TRANSMIT|UART_LCR_B_SIP_ENABLE);
-
- serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
+ 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);
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
+ outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
}
/*
{
int iobase, d;
- IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(2, __FUNCTION__ "\n");
ASSERT(self != NULL, return;);
register_bank(self->io.iobase, 1);
- serial_out(self->io.iobase, UART_SCE_CFGB,
- serial_in(self->io.iobase, UART_SCE_CFGB) &
- ~UART_CFGB_DMA_ENABLE);
+ 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(ircc_debug, __FUNCTION__ ": dma residue = %d, len=%d, sent=%d\n",
- d, self->tx_buff.len, self->tx_buff.len - d);
+ 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;
/* Tell the network layer, that we can accept more frames */
mark_bh(NET_BH);
-
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
}
/*
{
int iobase;
- IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(2, __FUNCTION__ "\n");
ASSERT(self != NULL, return -1;);
iobase= self->io.iobase;
setup_dma(self->io.dma, self->rx_buff.data, self->rx_buff.truesize,
- DMA_MODE_READ);
+ DMA_RX_MODE);
/* driver->media_busy = FALSE; */
self->io.direction = IO_RECV;
#endif
register_bank(iobase, 4);
- serial_out(iobase, UART_CONTROL,
- (serial_in(iobase, UART_CONTROL) &0xF0));
- serial_out(iobase, UART_BOF_COUNT_LO, 2);
- serial_out(iobase, UART_BRICKWALL_CNT_LO, 0);
- serial_out(iobase, UART_BRICKWALL_TX_CNT_HI, 0);
- serial_out(iobase, UART_TX_SIZE_LO, 0);
- serial_out(iobase, UART_RX_SIZE_HI, 0);
- serial_out(iobase, UART_RX_SIZE_LO, 0);
+ 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);
register_bank(iobase, 0);
- serial_out(iobase,
- UART_LCR_B, UART_LCR_B_SCE_RECEIVE | UART_LCR_B_SIP_ENABLE);
+ outb(IRCC_LCR_B_SCE_RECEIVE | IRCC_LCR_B_SIP_ENABLE,
+ iobase+IRCC_LCR_B);
register_bank(iobase, 1);
- serial_out(iobase, UART_SCE_CFGB,
- serial_in(iobase, UART_SCE_CFGB) |
- UART_CFGB_DMA_ENABLE | UART_CFGB_DMA_BURST);
+ outb(inb(iobase+IRCC_SCE_CFGB) | IRCC_CFGB_DMA_ENABLE |
+ IRCC_CFGB_DMA_BURST, iobase+IRCC_SCE_CFGB);
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
return 0;
}
struct sk_buff *skb;
int len, msgcnt;
- IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(2, __FUNCTION__ "\n");
- msgcnt = serial_in(self->io.iobase, UART_LCR_B) & 0x08;
+ msgcnt = inb(self->io.iobase+IRCC_LCR_B) & 0x08;
- IRDA_DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n",
- get_dma_residue(self->io.dma));
+ IRDA_DEBUG(0, __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(ircc_debug, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
+ IRDA_DEBUG(0, __FUNCTION__ ": msgcnt = %d, len=%d\n", msgcnt, len);
skb = dev_alloc_skb(len+1);
-
- if (skb == NULL) {
- printk(KERN_INFO __FUNCTION__
- ": memory squeeze, dropping frame.\n");
+ if (!skb) {
+ WARNING(__FUNCTION__ "(), memory squeeze, dropping frame.\n");
return FALSE;
}
netif_rx(skb);
register_bank(self->io.iobase, 1);
- serial_out(self->io.iobase, UART_SCE_CFGB,
- serial_in(self->io.iobase, UART_SCE_CFGB) &
- ~UART_CFGB_DMA_ENABLE);
+ outb(inb(self->io.iobase+IRCC_SCE_CFGB) & ~IRCC_CFGB_DMA_ENABLE,
+ self->io.iobase+IRCC_SCE_CFGB);
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
return TRUE;
}
struct net_device *dev = (struct net_device *) dev_id;
struct ircc_cb *self;
- IRDA_DEBUG(ircc_debug+1, __FUNCTION__ " -->\n");
-
if (dev == NULL) {
printk(KERN_WARNING "%s: irq %d for unknown device.\n",
- driver_name, irq);
+ driver_name, irq);
return;
}
dev->interrupt = 1;
- serial_out(iobase, UART_MASTER, 0);
+ outb(0, iobase+IRCC_MASTER);
register_bank(iobase, 0);
+ iir = inb(iobase+IRCC_IIR);
- iir = serial_in(iobase, UART_IIR);
+ /* Disable interrupts */
+ outb(0, iobase+IRCC_IER);
- serial_out(iobase, UART_IER, 0);
+ IRDA_DEBUG(0, __FUNCTION__ "(), iir = 0x%02x\n", iir);
- IRDA_DEBUG(ircc_debug, __FUNCTION__ ": iir = 0x%02x\n", iir);
+ if (iir & IRCC_IIR_EOM) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), IRCC_IIR_EOM\n");
- if (iir & UART_IIR_EOM) {
- IRDA_DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_EOM\n");
- if (self->io.direction == IO_RECV) {
+ if (self->io.direction == IO_RECV)
ircc_dma_receive_complete(self, iobase);
- } else {
+ else
ircc_dma_xmit_complete(self, iobase);
- }
+
ircc_dma_receive(self);
}
-
- if (iir & UART_IIR_ACTIVE_FRAME) {
- IRDA_DEBUG(ircc_debug, __FUNCTION__ ": UART_IIR_ACTIVE_FRAME\n");
+ 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 & UART_IIR_RAW_MODE) {
- IRDA_DEBUG(ircc_debug, __FUNCTION__ ": IIR RAW mode interrupt.\n");
+ if (iir & IRCC_IIR_RAW_MODE) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), IIR RAW mode interrupt.\n");
}
- dev->interrupt = 0;
-
register_bank(iobase, 0);
- serial_out(iobase, UART_IER, UART_IER_ACTIVE_FRAME|UART_IER_EOM);
- serial_out(iobase, UART_MASTER, UART_MASTER_INT_EN);
+ outb(IRCC_IER_ACTIVE_FRAME|IRCC_IER_EOM, iobase+IRCC_IER);
+ outb(IRCC_MASTER_INT_EN, iobase+IRCC_MASTER);
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
+ dev->interrupt = 0;
}
/*
int status = FALSE;
/* int iobase; */
- IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(0, __FUNCTION__ "\n");
ASSERT(self != NULL, return FALSE;);
- IRDA_DEBUG(ircc_debug, __FUNCTION__ ": dma count = %d\n",
- get_dma_residue(self->io.dma));
+ IRDA_DEBUG(0, __FUNCTION__ ": dma count = %d\n",
+ get_dma_residue(self->io.dma));
status = (self->rx_buff.state != OUTSIDE_FRAME);
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
-
return status;
}
struct ircc_cb *self;
int iobase;
- IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(0, __FUNCTION__ "\n");
ASSERT(dev != NULL, return -1;);
irport = (struct irport_cb *) dev->priv;
iobase = self->io.iobase;
- irport_net_open(dev);
+ irport_net_open(dev); /* irport allocates the irq */
/*
* Always allocate the DMA channel after the IRQ,
* and clean up on failure.
*/
if (request_dma(self->io.dma, dev->name)) {
- free_irq(self->io.irq, dev);
+ irport_net_close(dev);
+
return -EAGAIN;
}
MOD_INC_USE_COUNT;
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
return 0;
}
struct ircc_cb *self;
int iobase;
- IRDA_DEBUG(ircc_debug, __FUNCTION__ " -->\n");
+ IRDA_DEBUG(0, __FUNCTION__ "\n");
ASSERT(dev != NULL, return -1;);
irport = (struct irport_cb *) dev->priv;
MOD_DEC_USE_COUNT;
- IRDA_DEBUG(ircc_debug, "--> " __FUNCTION__ "\n");
return 0;
}
#ifdef MODULE
-
MODULE_AUTHOR("Thomas Davis <tadavis@jps.net>");
MODULE_DESCRIPTION("SMC IrCC controller driver");
-MODULE_PARM(ircc_debug,"1i");
MODULE_PARM(ircc_dma, "1i");
MODULE_PARM(ircc_irq, "1i");
ircc_cleanup();
}
-#endif
+#endif /* MODULE */
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Wed Oct 21 20:02:35 1998
- * Modified at: Fri Dec 17 09:17:45 1999
+ * Modified at: Fri Dec 17 09:13:09 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
* Modified: Paul Bristow <paul.bristow@technologist.com>
* Modified: Mon Nov 11 19:10:05 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
/* No user servicable parts below here */
#include <linux/module.h>
-#include <linux/config.h>
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/skbuff.h>
* Status: Experimental.
* Author: Paul VanderSpek
* Created at: Wed Nov 4 11:46:16 1998
- * Modified at: Tue Dec 21 21:53:09 1999
+ * Modified at: Wed Jan 5 15:11:21 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>
* Copyright (c) 1998-1999 Rebel.com
*
* This program is free software; you can redistribute it and/or
********************************************************************/
#include <linux/module.h>
-#include <linux/config.h>
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/skbuff.h>
#include <net/irda/w83977af.h>
#include <net/irda/w83977af_ir.h>
-#ifdef CONFIG_ARCH_VNC /* Adjust to NetWinder differences */
-#undef CONFIG_VNC_TX_DMA_PROBLEMS /* Not needed */
-#define CONFIG_VNC_RX_DMA_PROBLEMS /* Must have this one! */
+#ifdef CONFIG_ARCH_NETWINDER /* Adjust to NetWinder differences */
+#undef CONFIG_NETWINDER_TX_DMA_PROBLEMS /* Not needed */
+#define CONFIG_NETWINDER_RX_DMA_PROBLEMS /* Must have this one! */
#endif
#undef CONFIG_USE_INTERNAL_TIMER /* Just cannot make that timer work */
#define CONFIG_USE_W977_PNP /* Currently needed */
#define CHIP_IO_EXTENT 8
static unsigned int io[] = { 0x180, ~0, ~0, ~0 };
-#ifdef CONFIG_ARCH_VNC /* Adjust to NetWinder differences */
+#ifdef CONFIG_ARCH_NETWINDER /* Adjust to NetWinder differences */
static unsigned int irq[] = { 6, 0, 0, 0 };
#else
static unsigned int irq[] = { 11, 0, 0, 0 };
static int w83977af_net_open(struct net_device *dev);
static int w83977af_net_close(struct net_device *dev);
static int w83977af_net_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static struct net_device_stats *w83977af_net_get_stats(struct net_device *dev);
/*
* Function w83977af_init ()
self->tx_buff.truesize = 4000;
/* Allocate memory if needed */
- if (self->rx_buff.truesize > 0) {
- self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
- GFP_KERNEL|GFP_DMA);
- if (self->rx_buff.head == NULL)
- return -ENOMEM;
- memset(self->rx_buff.head, 0, self->rx_buff.truesize);
- }
- if (self->tx_buff.truesize > 0) {
- self->tx_buff.head = (__u8 *) kmalloc(self->tx_buff.truesize,
- GFP_KERNEL|GFP_DMA);
- if (self->tx_buff.head == NULL) {
- kfree(self->rx_buff.head);
- return -ENOMEM;
- }
- memset(self->tx_buff.head, 0, self->tx_buff.truesize);
+ self->rx_buff.head = (__u8 *) kmalloc(self->rx_buff.truesize,
+ GFP_KERNEL|GFP_DMA);
+ if (self->rx_buff.head == NULL)
+ 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->rx_buff.head);
+ return -ENOMEM;
}
+ memset(self->tx_buff.head, 0, self->tx_buff.truesize);
self->rx_buff.in_frame = FALSE;
self->rx_buff.state = OUTSIDE_FRAME;
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;
dev->open = w83977af_net_open;
dev->stop = w83977af_net_close;
dev->do_ioctl = w83977af_net_ioctl;
+ dev->get_stats = w83977af_net_get_stats;
rtnl_lock();
err = register_netdev(dev);
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 */
w977_write_reg(0x61, (iobase) & 0xff, efbase[i]);
w977_write_reg(0x70, irq, efbase[i]);
-#ifdef CONFIG_ARCH_VNC
+#ifdef CONFIG_ARCH_NETWINDER
/* Netwinder uses 1 higher than Linux */
w977_write_reg(0x74, dma+1, efbase[i]);
#else
w977_write_reg(0x74, dma, efbase[i]);
-#endif /*CONFIG_ARCH_VNC */
+#endif /*CONFIG_ARCH_NETWINDER */
w977_write_reg(0x75, 0x04, efbase[i]); /* Disable Tx DMA */
/* Set append hardware CRC, enable IR bank selection */
switch (speed) {
case 9600: outb(0x0c, iobase+ABLL); break;
case 19200: outb(0x06, iobase+ABLL); break;
- case 37600: outb(0x03, iobase+ABLL); break;
+ case 38400: outb(0x03, iobase+ABLL); break;
case 57600: outb(0x02, iobase+ABLL); break;
case 115200: outb(0x01, iobase+ABLL); break;
case 576000:
/* set FIFO threshold to TX17, RX16 */
switch_bank(iobase, SET0);
-
outb(0x00, iobase+UFR); /* Reset */
outb(UFR_EN_FIFO, iobase+UFR); /* First we must enable FIFO */
outb(0xa7, iobase+UFR);
iobase = self->io.iobase;
- IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+ IRDA_DEBUG(4, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies,
+ (int) skb->len);
/* Lock transmit buffer */
if (irda_lock((void *) &dev->tbusy) == FALSE)
static void w83977af_dma_write(struct w83977af_ir *self, int iobase)
{
__u8 set;
-#ifdef CONFIG_VNC_TX_DMA_PROBLEMS
+#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
unsigned long flags;
__u8 hcr;
#endif
/* Choose transmit DMA channel */
switch_bank(iobase, SET2);
outb(ADCR1_D_CHSW|/*ADCR1_DMA_F|*/ADCR1_ADV_SL, iobase+ADCR1);
-#ifdef CONFIG_VNC_TX_DMA_PROBLEMS
+#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
save_flags(flags);
cli();
/* Enable DMA */
switch_bank(iobase, SET0);
-#ifdef CONFIG_VNC_TX_DMA_PROBLEMS
+#ifdef CONFIG_NETWINDER_TX_DMA_PROBLEMS
hcr = inb(iobase+HCR);
outb(hcr | HCR_EN_DMA, iobase+HCR);
enable_dma(self->io.dma);
switch_bank(iobase, SET0);
if (!(inb_p(iobase+USR) & USR_TSRE)) {
- IRDA_DEBUG(4, __FUNCTION__ "(), warning, FIFO not empty yet!\n");
+ IRDA_DEBUG(4, __FUNCTION__
+ "(), warning, FIFO not empty yet!\n");
fifo_size -= 17;
- IRDA_DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n", fifo_size);
+ IRDA_DEBUG(4, __FUNCTION__ "%d bytes left in tx fifo\n",
+ fifo_size);
}
/* Fill FIFO with current frame */
{
int iobase;
__u8 set;
-#ifdef CONFIG_VNC_RX_DMA_PROBLEMS
+#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
unsigned long flags;
__u8 hcr;
#endif
-
ASSERT(self != NULL, return -1;);
IRDA_DEBUG(4, __FUNCTION__ "\n");
self->io.direction = IO_RECV;
self->rx_buff.data = self->rx_buff.head;
-#ifdef CONFIG_VNC_RX_DMA_PROBLEMS
+#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
save_flags(flags);
cli();
/* Enable DMA */
switch_bank(iobase, SET0);
-#ifdef CONFIG_VNC_RX_DMA_PROBLEMS
+#ifdef CONFIG_NETWINDER_RX_DMA_PROBLEMS
hcr = inb(iobase+HCR);
outb(hcr | HCR_EN_DMA, iobase+HCR);
enable_dma(self->io.dma);
self->netdev->tbusy = 0; /* Unlock */
self->stats.tx_packets++;
- /* Check if we need to change the speed? */
- if (self->new_speed) {
- IRDA_DEBUG(2, __FUNCTION__
- "(), Changing speed!\n");
- w83977af_change_speed(self, self->new_speed);
- self->new_speed = 0;
- }
-
/* Schedule network layer */
mark_bh(NET_BH);
}
/*
- * Function pc87108_interrupt (irq, dev_id, regs)
+ * Function w83977af_interrupt (irq, dev_id, regs)
*
* An interrupt from the chip has arrived. Time to do some work
*
return ret;
}
+static struct net_device_stats *w83977af_net_get_stats(struct net_device *dev)
+{
+ struct w83977af_ir *self = (struct w83977af_ir *) dev->priv;
+
+ return &self->stats;
+}
+
#ifdef MODULE
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
MODULE_DESCRIPTION("Winbond W83977AF IrDA Device Driver");
MODULE_PARM(qos_mtt_bits, "i");
+MODULE_PARM(io, "1-4i");
+MODULE_PARM(io2, "1-4i");
+MODULE_PARM(irq, "1-4i");
/*
* Function init_module (void)
tristate ' IBM Tropic chipset based adapter support' CONFIG_IBMTR
tristate ' IBM Olympic chipset PCI adapter support' CONFIG_IBMOL
tristate ' Generic TMS380 Token Ring ISA/PCI adapter support' CONFIG_TMS380TR
+ tristate ' SMC ISA adapter support' CONFIG_SMCTR
fi
endmenu
endif
endif
+ifeq ($(CONFIG_SMCTR),y)
+ L_OBJS += smctr.o
+else
+ ifeq ($(CONFIG_SMCTR),m)
+ M_OBJS += smctr.o
+ endif
+endif
+
include $(TOPDIR)/Rules.make
--- /dev/null
+/*
+ * smctr.c: A network driver for the SMC Token Ring Adapters.
+ *
+ * Written by Jay Schulist <jschlst@turbolinux.com>
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU Public License, incorporated herein by reference.
+ *
+ * This device driver works with the following SMC adapters:
+ * - SMC TokenCard Elite (8115T)
+ * - SMC TokenCard Elite/A MCA (8115T/A)
+ *
+ * Source(s):
+ * - SMC TokenCard SDK.
+ *
+ * Maintainer(s):
+ * JS Jay Schulist <jschlst@turbolinux.com>
+ *
+ * To do:
+ * 1. MCA SMC TokenCard Support. (Some support is already done).
+ * 4. Multicast support.
+ */
+
+static const char *version = "smctr.c: v1.0 1/1/00 by jschlst@turbolinux.com\n";
+static const char *cardname = "smctr";
+
+#include <linux/config.h>
+#ifdef MODULE
+#include <linux/module.h>
+#include <linux/version.h>
+#endif
+
+#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/time.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/dma.h>
+#include <asm/irq.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/trdevice.h>
+
+#include "smctr.h" /* Our Stuff */
+#include "smctr_firmware.h" /* SMC adapter firmware */
+
+#define SMCTR_IO_EXTENT 20
+
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int smctr_portlist[] __initdata = {
+ 0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, 0x300,
+ 0x320, 0x340, 0x360, 0x380,
+ 0
+};
+
+static int ringspeed = 0;
+
+/* SMC Name of the Adapter. */
+static char *smctr_name = "SMC TokenCard";
+char *smctr_model = "Unknown";
+
+/* Use 0 for production, 1 for verification, 2 for debug, and
+ * 3 for very verbose debug.
+ */
+#ifndef SMCTR_DEBUG
+#define SMCTR_DEBUG 1
+#endif
+static unsigned int smctr_debug = SMCTR_DEBUG;
+
+/* smctr.c prototypes and functions are arranged alphabeticly
+ * for clearity, maintainability and pure old fashion fun.
+ */
+/* A */
+static int smctr_alloc_shared_memory(struct net_device *dev);
+
+/* B */
+static int smctr_bypass_state(struct net_device *dev);
+
+/* C */
+static int smctr_checksum_firmware(struct net_device *dev);
+static int smctr_chg_rx_mask(struct net_device *dev);
+static int smctr_clear_int(struct net_device *dev);
+static int smctr_clear_trc_reset(int ioaddr);
+static int smctr_close(struct net_device *dev);
+
+/* D */
+static int smctr_decode_firmware(struct net_device *dev);
+static int smctr_disable_16bit(struct net_device *dev);
+static int smctr_disable_adapter_ctrl_store(struct net_device *dev);
+static int smctr_disable_adapter_ram(struct net_device *dev);
+static int smctr_disable_bic_int(struct net_device *dev);
+
+/* E */
+static int smctr_enable_16bit(struct net_device *dev);
+static int smctr_enable_adapter_ctrl_store(struct net_device *dev);
+static int smctr_enable_adapter_ram(struct net_device *dev);
+static int smctr_enable_bic_int(struct net_device *dev);
+
+/* F */
+static int __init smctr_find_adapter(struct net_device *dev);
+
+/* G */
+static int __init smctr_get_boardid(struct net_device *dev);
+static int smctr_get_group_address(struct net_device *dev);
+static int smctr_get_functional_address(struct net_device *dev);
+static unsigned int smctr_get_num_rx_bdbs(struct net_device *dev);
+static int smctr_get_physical_drop_number(struct net_device *dev);
+static __u8 *smctr_get_rx_pointer(struct net_device *dev, short queue);
+static int smctr_get_station_id(struct net_device *dev);
+static struct enet_statistics *smctr_get_stats(struct net_device *dev);
+static FCBlock *smctr_get_tx_fcb(struct net_device *dev, __u16 queue,
+ __u16 bytes_count);
+static int smctr_get_upstream_neighbor_addr(struct net_device *dev);
+
+/* H */
+static int smctr_hardware_send_packet(struct net_device *dev,
+ struct net_local *tp);
+
+/* I */
+static int smctr_init_acbs(struct net_device *dev);
+static int smctr_init_adapter(struct net_device *dev);
+static int __init smctr_init_card(struct net_device *dev);
+static int smctr_init_card_real(struct net_device *dev);
+static int smctr_init_rx_bdbs(struct net_device *dev);
+static int smctr_init_rx_fcbs(struct net_device *dev);
+static int smctr_init_shared_memory(struct net_device *dev);
+static int smctr_init_tx_bdbs(struct net_device *dev);
+static int smctr_init_tx_fcbs(struct net_device *dev);
+static int smctr_internal_self_test(struct net_device *dev);
+static void smctr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static int smctr_issue_enable_int_cmd(struct net_device *dev,
+ __u16 interrupt_enable_mask);
+static int smctr_issue_int_ack(struct net_device *dev, __u16 iack_code,
+ __u16 ibits);
+static int smctr_issue_init_timers_cmd(struct net_device *dev);
+static int smctr_issue_init_txrx_cmd(struct net_device *dev);
+static int smctr_issue_insert_cmd(struct net_device *dev);
+static int smctr_issue_read_ring_status_cmd(struct net_device *dev);
+static int smctr_issue_read_word_cmd(struct net_device *dev, __u16 aword_cnt);
+static int smctr_issue_remove_cmd(struct net_device *dev);
+static int smctr_issue_resume_acb_cmd(struct net_device *dev);
+static int smctr_issue_resume_rx_bdb_cmd(struct net_device *dev, __u16 queue);
+static int smctr_issue_resume_rx_fcb_cmd(struct net_device *dev, __u16 queue);
+static int smctr_issue_resume_tx_fcb_cmd(struct net_device *dev, __u16 queue);
+static int smctr_issue_test_internal_rom_cmd(struct net_device *dev);
+static int smctr_issue_test_hic_cmd(struct net_device *dev);
+static int smctr_issue_test_mac_reg_cmd(struct net_device *dev);
+static int smctr_issue_trc_loopback_cmd(struct net_device *dev);
+static int smctr_issue_tri_loopback_cmd(struct net_device *dev);
+static int smctr_issue_write_byte_cmd(struct net_device *dev,
+ short aword_cnt, void *byte);
+static int smctr_issue_write_word_cmd(struct net_device *dev,
+ short aword_cnt, void *word);
+
+/* J */
+static int smctr_join_complete_state(struct net_device *dev);
+
+/* L */
+static int smctr_link_tx_fcbs_to_bdbs(struct net_device *dev);
+static int smctr_load_firmware(struct net_device *dev);
+static int smctr_load_node_addr(struct net_device *dev);
+static int smctr_lobe_media_test(struct net_device *dev);
+static int smctr_lobe_media_test_cmd(struct net_device *dev);
+static int smctr_lobe_media_test_state(struct net_device *dev);
+
+/* M */
+static int smctr_make_8025_hdr(struct net_device *dev,
+ MAC_HEADER *rmf, MAC_HEADER *tmf, __u16 ac_fc);
+static int smctr_make_access_pri(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+static int smctr_make_addr_mod(struct net_device *dev, MAC_SUB_VECTOR *tsv);
+static int smctr_make_auth_funct_class(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+static int smctr_make_corr(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv, __u16 correlator);
+static int smctr_make_funct_addr(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+static int smctr_make_group_addr(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+static int smctr_make_phy_drop_num(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+static int smctr_make_product_id(struct net_device *dev, MAC_SUB_VECTOR *tsv);
+static int smctr_make_station_id(struct net_device *dev, MAC_SUB_VECTOR *tsv);
+static int smctr_make_ring_station_status(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+static int smctr_make_ring_station_version(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+static int smctr_make_tx_status_code(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv, __u16 tx_fstatus);
+static int smctr_make_upstream_neighbor_addr(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+static int smctr_make_wrap_data(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv);
+
+/* O */
+static int smctr_open(struct net_device *dev);
+static int smctr_open_tr(struct net_device *dev);
+
+/* P */
+int __init smctr_probe (struct net_device *dev);
+static int __init smctr_probe1(struct net_device *dev, int ioaddr);
+static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
+ struct net_device *dev, __u16 rx_status);
+
+/* R */
+static int smctr_ram_conflict_test(struct net_device *dev);
+static int smctr_ram_memory_test(struct net_device *dev);
+static unsigned int __init smctr_read_584_chksum(int ioaddr);
+static int smctr_rcv_chg_param(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 *correlator);
+static int smctr_rcv_init(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 *correlator);
+static int smctr_rcv_tx_forward(struct net_device *dev, MAC_HEADER *rmf);
+static int smctr_rcv_rq_addr_state_attch(struct net_device *dev,
+ MAC_HEADER *rmf, __u16 *correlator);
+static int smctr_rcv_unknown(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 *correlator);
+static int smctr_reset_adapter(struct net_device *dev);
+static int smctr_restart_tx_chain(struct net_device *dev, short queue);
+static int smctr_ring_status_chg(struct net_device *dev);
+static int smctr_rom_conflict_test(struct net_device *dev);
+static int smctr_rx_frame(struct net_device *dev);
+
+/* S */
+static int smctr_send_dat(struct net_device *dev);
+static int smctr_send_packet(struct sk_buff *skb, struct net_device *dev);
+static int smctr_send_lobe_media_test(struct net_device *dev);
+static int smctr_send_rpt_addr(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 correlator);
+static int smctr_send_rpt_attch(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 correlator);
+static int smctr_send_rpt_state(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 correlator);
+static int smctr_send_rpt_tx_forward(struct net_device *dev,
+ MAC_HEADER *rmf, __u16 tx_fstatus);
+static int smctr_send_rsp(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 rcode, __u16 correlator);
+static int smctr_send_rq_init(struct net_device *dev);
+static int smctr_send_tx_forward(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 *tx_fstatus);
+static int smctr_set_auth_access_pri(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv);
+static int smctr_set_auth_funct_class(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv);
+static int smctr_set_corr(struct net_device *dev, MAC_SUB_VECTOR *rsv,
+ __u16 *correlator);
+static int smctr_set_error_timer_value(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv);
+static int smctr_set_frame_forward(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv, __u8 dc_sc);
+static int smctr_set_local_ring_num(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv);
+static unsigned short smctr_set_ctrl_attention(struct net_device *dev);
+static void smctr_set_multicast_list(struct net_device *dev);
+static int smctr_set_page(struct net_device *dev, __u8 *buf);
+static int smctr_set_phy_drop(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv);
+static int smctr_set_ring_speed(struct net_device *dev);
+static int smctr_set_rx_look_ahead(struct net_device *dev);
+static int smctr_set_trc_reset(int ioaddr);
+static int smctr_setup_single_cmd(struct net_device *dev,
+ __u16 command, __u16 subcommand);
+static int smctr_setup_single_cmd_w_data(struct net_device *dev,
+ __u16 command, __u16 subcommand);
+static char *smctr_malloc(struct net_device *dev, __u16 size);
+static int smctr_status_chg(struct net_device *dev);
+
+/* T */
+static int smctr_trc_send_packet(struct net_device *dev, FCBlock *fcb,
+ __u16 queue);
+static __u16 smctr_tx_complete(struct net_device *dev, __u16 queue);
+static unsigned short smctr_tx_move_frame(struct net_device *dev,
+ struct sk_buff *skb, __u8 *pbuff, unsigned int bytes);
+
+/* U */
+static int smctr_update_err_stats(struct net_device *dev);
+static int smctr_update_rx_chain(struct net_device *dev, __u16 queue);
+static int smctr_update_tx_chain(struct net_device *dev, FCBlock *fcb,
+ __u16 queue);
+
+/* W */
+static int smctr_wait_cmd(struct net_device *dev);
+static int smctr_wait_while_cbusy(struct net_device *dev);
+
+#define TO_256_BYTE_BOUNDRY(X) (((X + 0xff) & 0xff00) - X)
+#define TO_PARAGRAPH_BOUNDRY(X) (((X + 0x0f) & 0xfff0) - X)
+#define PARAGRAPH_BOUNDRY(X) smctr_malloc(dev, TO_PARAGRAPH_BOUNDRY(X))
+
+/* Allocate Adapter Shared Memory.
+ * IMPORTANT NOTE: Any changes to this function MUST be mirrored in the
+ * function "get_num_rx_bdbs" below!!!
+ *
+ * Order of memory allocation:
+ *
+ * 0. Initial System Configuration Block Pointer
+ * 1. System Configuration Block
+ * 2. System Control Block
+ * 3. Action Command Block
+ * 4. Interrupt Status Block
+ *
+ * 5. MAC TX FCB'S
+ * 6. NON-MAC TX FCB'S
+ * 7. MAC TX BDB'S
+ * 8. NON-MAC TX BDB'S
+ * 9. MAC RX FCB'S
+ * 10. NON-MAC RX FCB'S
+ * 11. MAC RX BDB'S
+ * 12. NON-MAC RX BDB'S
+ * 13. MAC TX Data Buffer( 1, 256 byte buffer)
+ * 14. MAC RX Data Buffer( 1, 256 byte buffer)
+ *
+ * 15. NON-MAC TX Data Buffer
+ * 16. NON-MAC RX Data Buffer
+ */
+static int smctr_alloc_shared_memory(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_alloc_shared_memory\n", dev->name);
+
+ /* Allocate initial System Control Block pointer.
+ * This pointer is located in the last page, last offset - 4.
+ */
+ tp->iscpb_ptr = (ISCPBlock *)(tp->ram_access + ((__u32)64 * 0x400)
+ - (long)ISCP_BLOCK_SIZE);
+
+ /* Allocate System Control Blocks. */
+ tp->scgb_ptr = (SCGBlock *)smctr_malloc(dev, sizeof(SCGBlock));
+ PARAGRAPH_BOUNDRY(tp->sh_mem_used);
+
+ tp->sclb_ptr = (SCLBlock *)smctr_malloc(dev, sizeof(SCLBlock));
+ PARAGRAPH_BOUNDRY(tp->sh_mem_used);
+
+ tp->acb_head = (ACBlock *)smctr_malloc(dev,
+ sizeof(ACBlock)*tp->num_acbs);
+ PARAGRAPH_BOUNDRY(tp->sh_mem_used);
+
+ tp->isb_ptr = (ISBlock *)smctr_malloc(dev, sizeof(ISBlock));
+ PARAGRAPH_BOUNDRY(tp->sh_mem_used);
+
+ tp->misc_command_data = (__u16 *)smctr_malloc(dev, MISC_DATA_SIZE);
+ PARAGRAPH_BOUNDRY(tp->sh_mem_used);
+
+ /* Allocate transmit FCBs. */
+ tp->tx_fcb_head[MAC_QUEUE] = (FCBlock *)smctr_malloc(dev,
+ sizeof(FCBlock) * tp->num_tx_fcbs[MAC_QUEUE]);
+
+ tp->tx_fcb_head[NON_MAC_QUEUE] = (FCBlock *)smctr_malloc(dev,
+ sizeof(FCBlock) * tp->num_tx_fcbs[NON_MAC_QUEUE]);
+
+ tp->tx_fcb_head[BUG_QUEUE] = (FCBlock *)smctr_malloc(dev,
+ sizeof(FCBlock) * tp->num_tx_fcbs[BUG_QUEUE]);
+
+ /* Allocate transmit BDBs. */
+ tp->tx_bdb_head[MAC_QUEUE] = (BDBlock *)smctr_malloc(dev,
+ sizeof(BDBlock) * tp->num_tx_bdbs[MAC_QUEUE]);
+
+ tp->tx_bdb_head[NON_MAC_QUEUE] = (BDBlock *)smctr_malloc(dev,
+ sizeof(BDBlock) * tp->num_tx_bdbs[NON_MAC_QUEUE]);
+
+ tp->tx_bdb_head[BUG_QUEUE] = (BDBlock *)smctr_malloc(dev,
+ sizeof(BDBlock) * tp->num_tx_bdbs[BUG_QUEUE]);
+
+ /* Allocate receive FCBs. */
+ tp->rx_fcb_head[MAC_QUEUE] = (FCBlock *)smctr_malloc(dev,
+ sizeof(FCBlock) * tp->num_rx_fcbs[MAC_QUEUE]);
+
+ tp->rx_fcb_head[NON_MAC_QUEUE] = (FCBlock *)smctr_malloc(dev,
+ sizeof(FCBlock) * tp->num_rx_fcbs[NON_MAC_QUEUE]);
+
+ /* Allocate receive BDBs. */
+ tp->rx_bdb_head[MAC_QUEUE] = (BDBlock *)smctr_malloc(dev,
+ sizeof(BDBlock) * tp->num_rx_bdbs[MAC_QUEUE]);
+
+ tp->rx_bdb_end[MAC_QUEUE] = (BDBlock *)smctr_malloc(dev, 0);
+
+ tp->rx_bdb_head[NON_MAC_QUEUE] = (BDBlock *)smctr_malloc(dev,
+ sizeof(BDBlock) * tp->num_rx_bdbs[NON_MAC_QUEUE]);
+
+ tp->rx_bdb_end[NON_MAC_QUEUE] = (BDBlock *)smctr_malloc(dev, 0);
+
+ /* Allocate MAC transmit buffers.
+ * MAC Tx Buffers doen't have to be on an ODD Boundry.
+ */
+ tp->tx_buff_head[MAC_QUEUE]
+ = (__u16 *)smctr_malloc(dev, tp->tx_buff_size[MAC_QUEUE]);
+ tp->tx_buff_curr[MAC_QUEUE] = tp->tx_buff_head[MAC_QUEUE];
+ tp->tx_buff_end [MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
+
+ /* Allocate BUG transmit buffers. */
+ tp->tx_buff_head[BUG_QUEUE]
+ = (__u16 *)smctr_malloc(dev, tp->tx_buff_size[BUG_QUEUE]);
+ tp->tx_buff_curr[BUG_QUEUE] = tp->tx_buff_head[BUG_QUEUE];
+ tp->tx_buff_end[BUG_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
+
+ /* Allocate MAC receive data buffers.
+ * MAC Rx buffer doesn't have to be on a 256 byte boundry.
+ */
+ tp->rx_buff_head[MAC_QUEUE] = (__u16 *)smctr_malloc(dev,
+ RX_DATA_BUFFER_SIZE * tp->num_rx_bdbs[MAC_QUEUE]);
+ tp->rx_buff_end[MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
+
+ /* Allocate Non-MAC transmit buffers.
+ * ?? For maximum Netware performance, put Tx Buffers on
+ * ODD Boundry and then restore malloc to Even Boundrys.
+ */
+ smctr_malloc(dev, 1L);
+ tp->tx_buff_head[NON_MAC_QUEUE]
+ = (__u16 *)smctr_malloc(dev, tp->tx_buff_size[NON_MAC_QUEUE]);
+ tp->tx_buff_curr[NON_MAC_QUEUE] = tp->tx_buff_head[NON_MAC_QUEUE];
+ tp->tx_buff_end [NON_MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
+ smctr_malloc(dev, 1L);
+
+ /* Allocate Non-MAC receive data buffers.
+ * To guarantee a minimum of 256 contigous memory to
+ * UM_Receive_Packet's lookahead pointer, before a page
+ * change or ring end is encountered, place each rx buffer on
+ * a 256 byte boundry.
+ */
+ smctr_malloc(dev, TO_256_BYTE_BOUNDRY(tp->sh_mem_used));
+ tp->rx_buff_head[NON_MAC_QUEUE] = (__u16 *)smctr_malloc(dev,
+ RX_DATA_BUFFER_SIZE * tp->num_rx_bdbs[NON_MAC_QUEUE]);
+ tp->rx_buff_end[NON_MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
+
+ return (0);
+}
+
+/* Enter Bypass state. */
+static int smctr_bypass_state(struct net_device *dev)
+{
+ int err;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_bypass_state\n", dev->name);
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE,
+ JS_BYPASS_STATE);
+
+ return (err);
+}
+
+static int smctr_checksum_firmware(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ __u16 i, checksum = 0;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_checksum_firmware\n", dev->name);
+
+ smctr_enable_adapter_ctrl_store(dev);
+
+ for(i = 0; i < CS_RAM_SIZE; i += 2)
+ checksum += *((__u16 *)(tp->ram_access + i));
+
+ tp->microcode_version = *(__u16 *)(tp->ram_access
+ + CS_RAM_VERSION_OFFSET);
+ tp->microcode_version >>= 8;
+
+ smctr_disable_adapter_ctrl_store(dev);
+
+ if(checksum)
+ return (checksum);
+
+ return (0);
+}
+
+static int smctr_chg_rx_mask(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int err = 0;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_chg_rx_mask\n", dev->name);
+
+ smctr_enable_16bit(dev);
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+ if(tp->mode_bits & LOOPING_MODE_MASK)
+ tp->config_word0 |= RX_OWN_BIT;
+ else
+ tp->config_word0 &= ~RX_OWN_BIT;
+
+ if(tp->receive_mask & PROMISCUOUS_MODE)
+ tp->config_word0 |= PROMISCUOUS_BIT;
+ else
+ tp->config_word0 &= ~PROMISCUOUS_BIT;
+
+ if(tp->receive_mask & ACCEPT_ERR_PACKETS)
+ tp->config_word0 |= SAVBAD_BIT;
+ else
+ tp->config_word0 &= ~SAVBAD_BIT;
+
+ if(tp->receive_mask & ACCEPT_ATT_MAC_FRAMES)
+ tp->config_word0 |= RXATMAC;
+ else
+ tp->config_word0 &= ~RXATMAC;
+
+ if(tp->receive_mask & ACCEPT_MULTI_PROM)
+ tp->config_word1 |= MULTICAST_ADDRESS_BIT;
+ else
+ tp->config_word1 &= ~MULTICAST_ADDRESS_BIT;
+
+ if(tp->receive_mask & ACCEPT_SOURCE_ROUTING_SPANNING)
+ tp->config_word1 |= SOURCE_ROUTING_SPANNING_BITS;
+ else
+ {
+ if(tp->receive_mask & ACCEPT_SOURCE_ROUTING)
+ tp->config_word1 |= SOURCE_ROUTING_EXPLORER_BIT;
+ else
+ tp->config_word1 &= ~SOURCE_ROUTING_SPANNING_BITS;
+ }
+
+ if((err = smctr_issue_write_word_cmd(dev, RW_CONFIG_REGISTER_0,
+ &tp->config_word0)))
+ {
+ return (err);
+ }
+
+ if((err = smctr_issue_write_word_cmd(dev, RW_CONFIG_REGISTER_1,
+ &tp->config_word1)))
+ {
+ return (err);
+ }
+
+ smctr_disable_16bit(dev);
+
+ return (0);
+}
+
+static int smctr_clear_int(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ outb((tp->trc_mask | CSR_CLRTINT), dev->base_addr + CSR);
+
+ return (0);
+}
+
+static int smctr_clear_trc_reset(int ioaddr)
+{
+ __u8 r;
+
+ r = inb(ioaddr + MSR);
+ outb(~MSR_RST & r, ioaddr + MSR);
+
+ return (0);
+}
+
+/*
+ * The inverse routine to smctr_open().
+ */
+static int smctr_close(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ struct sk_buff *skb;
+ int err;
+
+ dev->tbusy = 1;
+ dev->start = 0;
+
+#ifdef MODULE
+ MOD_DEC_USE_COUNT;
+#endif
+
+ tp->cleanup = 1;
+
+ /* Check to see if adapter is already in a closed state. */
+ if(tp->status != OPEN)
+ return (0);
+
+ smctr_enable_16bit(dev);
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+ if((err = smctr_issue_remove_cmd(dev)))
+ {
+ smctr_disable_16bit(dev);
+ return (err);
+ }
+
+ for(;;)
+ {
+ skb = skb_dequeue(&tp->SendSkbQueue);
+ if(skb == NULL)
+ break;
+ tp->QueueSkb++;
+ dev_kfree_skb(skb);
+ }
+
+
+ return (0);
+}
+
+static int smctr_decode_firmware(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ short bit = 0x80, shift = 12;
+ DECODE_TREE_NODE *tree;
+ short branch, tsize;
+ __u16 buff = 0;
+ long weight;
+ __u8 *ucode;
+ __u16 *mem;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_decode_firmware\n", dev->name);
+
+ weight = *(long *)(tp->ptr_ucode + WEIGHT_OFFSET);
+ tsize = *(__u8 *)(tp->ptr_ucode + TREE_SIZE_OFFSET);
+ tree = (DECODE_TREE_NODE *)(tp->ptr_ucode + TREE_OFFSET);
+ ucode = (__u8 *)(tp->ptr_ucode + TREE_OFFSET
+ + (tsize * sizeof(DECODE_TREE_NODE)));
+ mem = (__u16 *)(tp->ram_access);
+
+ while(weight)
+ {
+ branch = ROOT;
+ while((tree + branch)->tag != LEAF && weight)
+ {
+ branch = *ucode & bit ? (tree + branch)->llink
+ : (tree + branch)->rlink;
+
+ bit >>= 1;
+ weight--;
+
+ if(bit == 0)
+ {
+ bit = 0x80;
+ ucode++;
+ }
+ }
+
+ buff |= (tree + branch)->info << shift;
+ shift -= 4;
+
+ if(shift < 0)
+ {
+ *(mem++) = SWAP_BYTES(buff);
+ buff = 0;
+ shift = 12;
+ }
+ }
+
+ /* The following assumes the Control Store Memory has
+ * been initialized to zero. If the last partial word
+ * is zero, it will not be written.
+ */
+ if(buff)
+ *(mem++) = SWAP_BYTES(buff);
+
+ return (0);
+}
+
+static int smctr_disable_16bit(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ __u8 r;
+
+ if(tp->adapter_bus == BUS_ISA16_TYPE
+ && ((tp->adapter_flags & FORCED_16BIT_MODE) == 0))
+ {
+ r = inb(dev->base_addr + LAAR);
+ outb((r & ~LAAR_MEM16ENB), dev->base_addr + LAAR);
+ }
+
+ return (0);
+}
+
+/*
+ * On Exit, Adapter is:
+ * 1. TRC is in a reset state and un-initialized.
+ * 2. Adapter memory is enabled.
+ * 3. Control Store memory is out of context (-WCSS is 1).
+ */
+static int smctr_disable_adapter_ctrl_store(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_disable_adapter_ctrl_store\n", dev->name);
+
+ tp->trc_mask |= CSR_WCSS;
+ outb(tp->trc_mask, ioaddr + CSR);
+
+ return (0);
+}
+
+static int smctr_disable_adapter_ram(struct net_device *dev)
+{
+ int ioaddr = dev->base_addr;
+ __u8 r;
+
+ /* First disable memory enable bit. */
+ r = inb(ioaddr + MSR);
+ outb(~MSR_MEMB & r, ioaddr + MSR);
+
+ /* Now disable 16 bit memory enable bit. */
+ r = inb(ioaddr + LAAR);
+ outb(~LAAR_MEM16ENB & r, ioaddr + LAAR);
+
+ return (0);
+}
+
+static int smctr_disable_bic_int(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+
+ tp->trc_mask = CSR_MSK_ALL | CSR_MSKCBUSY
+ | CSR_MSKTINT | CSR_WCSS;
+ outb(tp->trc_mask, ioaddr + CSR);
+
+ return (0);
+}
+
+static int smctr_enable_16bit(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ __u8 r;
+
+ if(tp->adapter_bus == BUS_ISA16_TYPE)
+ {
+ r = inb(dev->base_addr + LAAR);
+ outb((r | LAAR_MEM16ENB), dev->base_addr + LAAR);
+ }
+
+ return (0);
+}
+
+/*
+ * To enable the adapter control store memory:
+ * 1. Adapter must be in a RESET state.
+ * 2. Adapter memory must be enabled.
+ * 3. Control Store Memory is in context (-WCSS is 0).
+ */
+static int smctr_enable_adapter_ctrl_store(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_enable_adapter_ctrl_store\n", dev->name);
+
+ smctr_set_trc_reset(ioaddr);
+ smctr_enable_adapter_ram(dev);
+
+ tp->trc_mask &= ~CSR_WCSS;
+ outb(tp->trc_mask, ioaddr + CSR);
+
+ return (0);
+}
+
+static int smctr_enable_adapter_ram(struct net_device *dev)
+{
+ int ioaddr = dev->base_addr;
+ __u8 r;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_enable_adapter_ram\n", dev->name);
+
+ r = inb(ioaddr + MSR);
+ outb(MSR_MEMB | r, ioaddr + MSR);
+
+ return (0);
+}
+
+static int smctr_enable_bic_int(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+ __u8 r;
+
+ switch(tp->bic_type)
+ {
+ case (BIC_584_CHIP):
+ tp->trc_mask = CSR_MSKCBUSY | CSR_WCSS;
+ outb(tp->trc_mask, ioaddr + CSR);
+ r = inb(ioaddr + IRR);
+ outb(r | IRR_IEN, ioaddr + IRR);
+ break;
+
+ case (BIC_594_CHIP):
+ tp->trc_mask = CSR_MSKCBUSY | CSR_WCSS;
+ outb(tp->trc_mask, ioaddr + CSR);
+ r = inb(ioaddr + IMCCR);
+ outb(r | IMCCR_EIL, ioaddr + IMCCR);
+ break;
+ }
+
+ return (0);
+}
+
+static int __init smctr_find_adapter(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+ __u8 r1, r2, b, chksum = 0;
+ __u16 r;
+ int i;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_find_adapter %#4x\n", dev->name, ioaddr);
+
+ /* Checksum SMC node address */
+ for(i = 0; i < 8; i++)
+ {
+ b = inb(ioaddr + LAR0 + i);
+ chksum += b;
+ }
+
+ if(chksum != NODE_ADDR_CKSUM)
+ return (-1); /* Adapter Not Found */
+
+ /* Grab the region so that no one else tries to probe our ioports. */
+ request_region(ioaddr, SMCTR_IO_EXTENT, smctr_name);
+
+ b = inb(ioaddr + BDID);
+
+ /* Check for 8115T Board ID */
+ r2 = 0;
+ for(r = 0; r < 8; r++)
+ {
+ r1 = inb(ioaddr + 0x8 + r);
+ r2 += r1;
+ }
+
+ /* value of RegF adds up the sum to 0xFF */
+ if((r2 != 0xFF) && (r2 != 0xEE))
+ return (-1);
+
+ /* Get adapter ID */
+ tp->board_id = smctr_get_boardid(dev);
+ switch(tp->board_id & 0xffff)
+ {
+ case WD8115TA:
+ smctr_model = "8115T/A";
+ break;
+
+ case WD8115T:
+ smctr_model = "8115T";
+ break;
+
+ default:
+ smctr_model = "Unknown";
+ break;
+ }
+
+ /* Store BIC type. */
+ tp->bic_type = BIC_584_CHIP;
+ tp->nic_type = NIC_825_CHIP;
+
+ /* Copy Ram Size */
+ tp->ram_usable = CNFG_SIZE_16KB;
+ tp->ram_size = CNFG_SIZE_64KB;
+
+ /* Get 58x Ram Base */
+ r1 = inb(ioaddr);
+ r1 &= 0x3F;
+
+ r2 = inb(ioaddr + CNFG_LAAR_584);
+ r2 &= CNFG_LAAR_MASK;
+ r2 <<= 3;
+ r2 |= ((r1 & 0x38) >> 3);
+
+ tp->ram_base = ((__u32)r2 << 16) + (((__u32)(r1 & 0x7)) << 13);
+
+ /* Get 584 Irq */
+ r1 = 0;
+ r1 = inb(ioaddr + CNFG_ICR_583);
+ r1 &= CNFG_ICR_IR2_584;
+
+ r2 = inb(ioaddr + CNFG_IRR_583);
+ r2 &= CNFG_IRR_IRQS; /* 0x60 */
+ r2 >>= 5;
+
+ switch(r2)
+ {
+ case 0:
+ if(r1 == 0)
+ dev->irq = 2;
+ else
+ dev->irq = 10;
+ break;
+
+ case 1:
+ if(r1 == 0)
+ dev->irq = 3;
+ else
+ dev->irq = 11;
+ break;
+
+ case 2:
+ if(r1 == 0)
+ {
+ if(tp->extra_info & ALTERNATE_IRQ_BIT)
+ dev->irq = 5;
+ else
+ dev->irq = 4;
+ }
+ else
+ dev->irq = 15;
+ break;
+
+ case 3:
+ if(r1 == 0)
+ dev->irq = 7;
+ else
+ dev->irq = 4;
+ break;
+
+ default:
+ printk("%s: No IRQ found aborting\n", dev->name);
+ return(-1);
+ }
+
+ if(request_irq(dev->irq, smctr_interrupt, SA_SHIRQ, smctr_name, dev))
+ return (-ENODEV);
+
+ /* Get 58x Rom Base */
+ r1 = inb(ioaddr + CNFG_BIO_583);
+ r1 &= 0x3E;
+ r1 |= 0x40;
+
+ tp->rom_base = (__u32)r1 << 13;
+
+ /* Get 58x Rom Size */
+ r1 = inb(ioaddr + CNFG_BIO_583);
+ r1 &= 0xC0;
+ if(r1 == 0)
+ tp->rom_size = ROM_DISABLE;
+ else
+ {
+ r1 >>= 6;
+ tp->rom_size = (__u16)CNFG_SIZE_8KB << r1;
+ }
+
+ /* Get 58x Boot Status */
+ r1 = inb(ioaddr + CNFG_GP2);
+
+ tp->mode_bits &= (~BOOT_STATUS_MASK);
+
+ if(r1 & CNFG_GP2_BOOT_NIBBLE)
+ tp->mode_bits |= BOOT_TYPE_1;
+
+ /* Get 58x Zero Wait State */
+ tp->mode_bits &= (~ZERO_WAIT_STATE_MASK);
+
+ r1 = inb(ioaddr + CNFG_IRR_583);
+
+ if(r1 & CNFG_IRR_ZWS)
+ tp->mode_bits |= ZERO_WAIT_STATE_8_BIT;
+
+ if(tp->board_id & BOARD_16BIT)
+ {
+ r1 = inb(ioaddr + CNFG_LAAR_584);
+
+ if(r1 & CNFG_LAAR_ZWS)
+ tp->mode_bits |= ZERO_WAIT_STATE_16_BIT;
+ }
+
+ /* Get 584 Media Menu */
+ tp->media_menu = 14;
+ r1 = inb(ioaddr + CNFG_IRR_583);
+
+ tp->mode_bits &= 0xf8ff; /* (~CNFG_INTERFACE_TYPE_MASK) */
+ if((tp->board_id & TOKEN_MEDIA) == TOKEN_MEDIA)
+ {
+ /* Get Advanced Features */
+ if(((r1 & 0x6) >> 1) == 0x3)
+ tp->media_type |= MEDIA_UTP_16;
+ else
+ {
+ if(((r1 & 0x6) >> 1) == 0x2)
+ tp->media_type |= MEDIA_STP_16;
+ else
+ {
+ if(((r1 & 0x6) >> 1) == 0x1)
+ tp->media_type |= MEDIA_UTP_4;
+
+ else
+ tp->media_type |= MEDIA_STP_4;
+ }
+ }
+
+ r1 = inb(ioaddr + CNFG_GP2);
+ if(!(r1 & 0x2) ) /* GP2_ETRD */
+ tp->mode_bits |= EARLY_TOKEN_REL;
+
+ /* see if the chip is corrupted */
+ if(smctr_read_584_chksum(ioaddr))
+ {
+ printk("%s: EEPROM Checksum Failure\n", dev->name);
+ return(-1);
+ }
+ }
+
+ return (0);
+}
+
+static int __init smctr_get_boardid(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+ __u8 r, r1, IdByte;
+ __u16 BoardIdMask;
+
+ tp->board_id = BoardIdMask = 0;
+
+ BoardIdMask |= (INTERFACE_CHIP+TOKEN_MEDIA+PAGED_RAM+BOARD_16BIT);
+ tp->extra_info |= (INTERFACE_584_CHIP + RAM_SIZE_64K
+ + NIC_825_BIT + ALTERNATE_IRQ_BIT);
+
+ r = inb(ioaddr + BID_REG_1);
+ r &= 0x0c;
+ outb(r, ioaddr + BID_REG_1);
+ r = inb(ioaddr + BID_REG_1);
+
+ if(r & BID_SIXTEEN_BIT_BIT)
+ {
+ tp->extra_info |= SLOT_16BIT;
+ tp->adapter_bus = BUS_ISA16_TYPE;
+ }
+ else
+ tp->adapter_bus = BUS_ISA8_TYPE;
+
+ /* Get Board Id Byte */
+ IdByte = inb(ioaddr + BID_BOARD_ID_BYTE);
+
+ /* if Major version > 1.0 then
+ * return;
+ */
+ if(IdByte & 0xF8)
+ return (-1);
+
+ r1 = inb(ioaddr + BID_REG_1);
+ r1 &= BID_ICR_MASK;
+ r1 |= BID_OTHER_BIT;
+
+ outb(r1, ioaddr + BID_REG_1);
+ r1 = inb(ioaddr + BID_REG_3);
+
+ r1 &= BID_EAR_MASK;
+ r1 |= BID_ENGR_PAGE;
+
+ outb(r1, ioaddr + BID_REG_3);
+ r1 = inb(ioaddr + BID_REG_1);
+ r1 &= BID_ICR_MASK;
+ r1 |= (BID_RLA | BID_OTHER_BIT);
+
+ outb(r1, ioaddr + BID_REG_1);
+
+ r1 = inb(ioaddr + BID_REG_1);
+ while(r1 & BID_RECALL_DONE_MASK)
+ r1 = inb(ioaddr + BID_REG_1);
+
+ r = inb(ioaddr + BID_LAR_0 + BID_REG_6);
+
+ /* clear chip rev bits */
+ tp->extra_info &= ~CHIP_REV_MASK;
+ tp->extra_info |= ((r & BID_EEPROM_CHIP_REV_MASK) << 6);
+
+ r1 = inb(ioaddr + BID_REG_1);
+ r1 &= BID_ICR_MASK;
+ r1 |= BID_OTHER_BIT;
+
+ outb(r1, ioaddr + BID_REG_1);
+ r1 = inb(ioaddr + BID_REG_3);
+
+ r1 &= BID_EAR_MASK;
+ r1 |= BID_EA6;
+
+ outb(r1, ioaddr + BID_REG_3);
+ r1 = inb(ioaddr + BID_REG_1);
+
+ r1 &= BID_ICR_MASK;
+ r1 |= BID_RLA;
+
+ outb(r1, ioaddr + BID_REG_1);
+ r1 = inb(ioaddr + BID_REG_1);
+
+ while(r1 & BID_RECALL_DONE_MASK)
+ r1 = inb(ioaddr + BID_REG_1);
+
+ return (BoardIdMask);
+}
+
+static int smctr_get_group_address(struct net_device *dev)
+{
+ smctr_issue_read_word_cmd(dev, RW_INDIVIDUAL_GROUP_ADDR);
+
+ return(smctr_wait_cmd(dev));
+}
+
+static int smctr_get_functional_address(struct net_device *dev)
+{
+ smctr_issue_read_word_cmd(dev, RW_FUNCTIONAL_ADDR);
+
+ return(smctr_wait_cmd(dev));
+}
+
+/* Calculate number of Non-MAC receive BDB's and data buffers.
+ * This function must simulate allocateing shared memory exactly
+ * as the allocate_shared_memory function above.
+ */
+static unsigned int smctr_get_num_rx_bdbs(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int mem_used = 0;
+
+ /* Allocate System Control Blocks. */
+ mem_used += sizeof(SCGBlock);
+
+ mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
+ mem_used += sizeof(SCLBlock);
+
+ mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
+ mem_used += sizeof(ACBlock) * tp->num_acbs;
+
+ mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
+ mem_used += sizeof(ISBlock);
+
+ mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
+ mem_used += MISC_DATA_SIZE;
+
+ /* Allocate transmit FCB's. */
+ mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
+
+ mem_used += sizeof(FCBlock) * tp->num_tx_fcbs[MAC_QUEUE];
+ mem_used += sizeof(FCBlock) * tp->num_tx_fcbs[NON_MAC_QUEUE];
+ mem_used += sizeof(FCBlock) * tp->num_tx_fcbs[BUG_QUEUE];
+
+ /* Allocate transmit BDBs. */
+ mem_used += sizeof(BDBlock) * tp->num_tx_bdbs[MAC_QUEUE];
+ mem_used += sizeof(BDBlock) * tp->num_tx_bdbs[NON_MAC_QUEUE];
+ mem_used += sizeof(BDBlock) * tp->num_tx_bdbs[BUG_QUEUE];
+
+ /* Allocate receive FCBs. */
+ mem_used += sizeof(FCBlock) * tp->num_rx_fcbs[MAC_QUEUE];
+ mem_used += sizeof(FCBlock) * tp->num_rx_fcbs[NON_MAC_QUEUE];
+
+ /* Allocate receive BDBs. */
+ mem_used += sizeof(BDBlock) * tp->num_rx_bdbs[MAC_QUEUE];
+
+ /* Allocate MAC transmit buffers.
+ * MAC transmit buffers don't have to be on an ODD Boundry.
+ */
+ mem_used += tp->tx_buff_size[MAC_QUEUE];
+
+ /* Allocate BUG transmit buffers. */
+ mem_used += tp->tx_buff_size[BUG_QUEUE];
+
+ /* Allocate MAC receive data buffers.
+ * MAC receive buffers don't have to be on a 256 byte boundry.
+ */
+ mem_used += RX_DATA_BUFFER_SIZE * tp->num_rx_bdbs[MAC_QUEUE];
+
+ /* Allocate Non-MAC transmit buffers.
+ * For maximum Netware performance, put Tx Buffers on
+ * ODD Boundry,and then restore malloc to Even Boundrys.
+ */
+ mem_used += 1L;
+ mem_used += tp->tx_buff_size[NON_MAC_QUEUE];
+ mem_used += 1L;
+
+ /* CALCULATE NUMBER OF NON-MAC RX BDB'S
+ * AND NON-MAC RX DATA BUFFERS
+ *
+ * Make sure the mem_used offset at this point is the
+ * same as in allocate_shared memory or the following
+ * boundry adjustment will be incorrect (i.e. not allocating
+ * the non-mac recieve buffers above cannot change the 256
+ * byte offset).
+ *
+ * Since this cannot be guaranteed, adding the full 256 bytes
+ * to the amount of shared memory used at this point will guaranteed
+ * that the rx data buffers do not overflow shared memory.
+ */
+ mem_used += 0x100;
+
+ return((0xffff - mem_used) / (RX_DATA_BUFFER_SIZE + sizeof(BDBlock)));
+}
+
+static int smctr_get_physical_drop_number(struct net_device *dev)
+{
+ smctr_issue_read_word_cmd(dev, RW_PHYSICAL_DROP_NUMBER);
+
+ return(smctr_wait_cmd(dev));
+}
+
+static __u8 * smctr_get_rx_pointer(struct net_device *dev, short queue)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ BDBlock *bdb;
+
+ bdb = (BDBlock *)((__u32)tp->ram_access
+ + (__u32)(tp->rx_fcb_curr[queue]->trc_bdb_ptr));
+
+ tp->rx_fcb_curr[queue]->bdb_ptr = bdb;
+
+ return ((__u8 *)bdb->data_block_ptr);
+}
+
+static int smctr_get_station_id(struct net_device *dev)
+{
+ smctr_issue_read_word_cmd(dev, RW_INDIVIDUAL_MAC_ADDRESS);
+
+ return(smctr_wait_cmd(dev));
+}
+
+/*
+ * Get the current statistics. This may be called with the card open
+ * or closed.
+ */
+static struct enet_statistics *smctr_get_stats(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ return ((struct enet_statistics *)&tp->MacStat);
+}
+
+static FCBlock *smctr_get_tx_fcb(struct net_device *dev, __u16 queue,
+ __u16 bytes_count)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ FCBlock *pFCB;
+ BDBlock *pbdb;
+ unsigned short alloc_size;
+ unsigned short *temp;
+
+ if(smctr_debug > 20)
+ printk("smctr_get_tx_fcb\n");
+
+ /* check if there is enough FCB blocks */
+ if(tp->num_tx_fcbs_used[queue] >= tp->num_tx_fcbs[queue])
+ return ((FCBlock *)(-1L));
+
+ /* round off the input pkt size to the nearest even number */
+ alloc_size = (bytes_count + 1) & 0xfffe;
+
+ /* check if enough mem */
+ if((tp->tx_buff_used[queue] + alloc_size) > tp->tx_buff_size[queue])
+ return ((FCBlock *)(-1L));
+
+ /* check if past the end ;
+ * if exactly enough mem to end of ring, alloc from front.
+ * this avoids update of curr when curr = end
+ */
+ if(((unsigned long)(tp->tx_buff_curr[queue]) + alloc_size)
+ >= (unsigned long)(tp->tx_buff_end[queue]))
+ {
+ /* check if enough memory from ring head */
+ alloc_size = alloc_size +
+ (__u16)((__u32)tp->tx_buff_end[queue]
+ - (__u32)tp->tx_buff_curr[queue]);
+
+ if((tp->tx_buff_used[queue] + alloc_size)
+ > tp->tx_buff_size[queue])
+ {
+ return ((FCBlock *)(-1L));
+ }
+
+ /* ring wrap */
+ tp->tx_buff_curr[queue] = tp->tx_buff_head[queue];
+ }
+
+ tp->tx_buff_used[queue] += alloc_size;
+ tp->num_tx_fcbs_used[queue]++;
+ tp->tx_fcb_curr[queue]->frame_length = bytes_count;
+ tp->tx_fcb_curr[queue]->memory_alloc = alloc_size;
+ temp = tp->tx_buff_curr[queue];
+ tp->tx_buff_curr[queue]
+ = (__u16 *)((__u32)temp + (__u32)((bytes_count + 1) & 0xfffe));
+
+ pbdb = tp->tx_fcb_curr[queue]->bdb_ptr;
+ pbdb->buffer_length = bytes_count;
+ pbdb->data_block_ptr = temp;
+ pbdb->trc_data_block_ptr = TRC_POINTER(temp);
+
+ pFCB = tp->tx_fcb_curr[queue];
+ tp->tx_fcb_curr[queue] = tp->tx_fcb_curr[queue]->next_ptr;
+
+ return (pFCB);
+}
+
+static int smctr_get_upstream_neighbor_addr(struct net_device *dev)
+{
+ smctr_issue_read_word_cmd(dev, RW_UPSTREAM_NEIGHBOR_ADDRESS);
+
+ return(smctr_wait_cmd(dev));
+}
+
+static int smctr_hardware_send_packet(struct net_device *dev,
+ struct net_local *tp)
+{
+ struct tr_statistics *tstat = &tp->MacStat;
+ struct sk_buff *skb;
+ FCBlock *fcb;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_hardware_send_packet\n", dev->name);
+
+ if(tp->status != OPEN)
+ return (-1);
+
+ if(tp->monitor_state_ready != 1)
+ return (-1);
+
+ for(;;)
+ {
+ /* Send first buffer from queue */
+ skb = skb_dequeue(&tp->SendSkbQueue);
+ if(skb == NULL)
+ return (-1);
+
+ tp->QueueSkb++;
+
+ if(skb->len < SMC_HEADER_SIZE || skb->len > tp->max_packet_size) return (-1);
+
+ smctr_enable_16bit(dev);
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+ if((fcb = smctr_get_tx_fcb(dev, NON_MAC_QUEUE, skb->len))
+ == (FCBlock *)(-1L))
+ {
+ smctr_disable_16bit(dev);
+ return (-1);
+ }
+
+ smctr_tx_move_frame(dev, skb,
+ (__u8 *)fcb->bdb_ptr->data_block_ptr, skb->len);
+
+ smctr_set_page(dev, (__u8 *)fcb);
+
+ smctr_trc_send_packet(dev, fcb, NON_MAC_QUEUE);
+ dev_kfree_skb(skb);
+
+ tstat->tx_packets++;
+
+ smctr_disable_16bit(dev);
+ }
+
+ return (0);
+}
+
+static int smctr_init_acbs(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int i;
+ ACBlock *acb;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_init_acbs\n", dev->name);
+
+ acb = tp->acb_head;
+ acb->cmd_done_status = (ACB_COMMAND_DONE | ACB_COMMAND_SUCCESSFUL);
+ acb->cmd_info = ACB_CHAIN_END;
+ acb->cmd = 0;
+ acb->subcmd = 0;
+ acb->data_offset_lo = 0;
+ acb->data_offset_hi = 0;
+ acb->next_ptr
+ = (ACBlock *)(((char *)acb) + sizeof(ACBlock));
+ acb->trc_next_ptr = TRC_POINTER(acb->next_ptr);
+
+ for(i = 1; i < tp->num_acbs; i++)
+ {
+ acb = acb->next_ptr;
+ acb->cmd_done_status
+ = (ACB_COMMAND_DONE | ACB_COMMAND_SUCCESSFUL);
+ acb->cmd_info = ACB_CHAIN_END;
+ acb->cmd = 0;
+ acb->subcmd = 0;
+ acb->data_offset_lo = 0;
+ acb->data_offset_hi = 0;
+ acb->next_ptr
+ = (ACBlock *)(((char *)acb) + sizeof(ACBlock));
+ acb->trc_next_ptr = TRC_POINTER(acb->next_ptr);
+ }
+
+ acb->next_ptr = tp->acb_head;
+ acb->trc_next_ptr = TRC_POINTER(tp->acb_head);
+ tp->acb_next = tp->acb_head->next_ptr;
+ tp->acb_curr = tp->acb_head->next_ptr;
+ tp->num_acbs_used = 0;
+
+ return (0);
+}
+
+static int smctr_init_adapter(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int err;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_init_adapter\n", dev->name);
+
+ tp->status = CLOSED;
+ tp->page_offset_mask = (tp->ram_usable * 1024) - 1;
+ skb_queue_head_init(&tp->SendSkbQueue);
+ tp->QueueSkb = MAX_TX_QUEUE;
+
+ if(!(tp->group_address_0 & 0x0080))
+ tp->group_address_0 |= 0x00C0;
+
+ if(!(tp->functional_address_0 & 0x00C0))
+ tp->functional_address_0 |= 0x00C0;
+
+ tp->functional_address[0] &= 0xFF7F;
+
+ if(tp->authorized_function_classes == 0)
+ tp->authorized_function_classes = 0x7FFF;
+
+ if(tp->authorized_access_priority == 0)
+ tp->authorized_access_priority = 0x06;
+
+ smctr_disable_bic_int(dev);
+ smctr_set_trc_reset(dev->base_addr);
+
+ /* By default the adapter will operate in 16-bit mode only. If
+ * there are two or more adapters in a box, switching between
+ * 16-bit and 8-bit mode may cause problems. In short the adapters
+ * will interfere with each other. XXX - smc.
+ */
+ smctr_disable_adapter_ram(dev);
+ if((err = smctr_rom_conflict_test(dev)))
+ return (err);
+
+ if((err = smctr_ram_conflict_test(dev)))
+ return (err);
+
+ smctr_enable_adapter_ram(dev);
+ smctr_enable_16bit(dev);
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+ if(smctr_checksum_firmware(dev))
+ return (UCODE_NOT_PRESENT);
+
+ if((err = smctr_ram_memory_test(dev)))
+ return (err);
+
+ smctr_enable_16bit(dev);
+ if(smctr_checksum_firmware(dev))
+ return (-1);
+
+ if((err = smctr_ram_memory_test(dev)))
+ return (-1);
+
+ smctr_set_rx_look_ahead(dev);
+ smctr_load_node_addr(dev);
+
+ /* Initialize adapter for Internal Self Test. */
+ smctr_reset_adapter(dev);
+
+ if((err = smctr_init_card_real(dev)))
+ return (err);
+
+ /* This routine clobbers the TRC's internal registers. */
+ if((err = smctr_internal_self_test(dev)))
+ return (err);
+
+ /* Re-Initialize adapter's internal registers */
+ smctr_reset_adapter(dev);
+
+ if((err = smctr_init_card_real(dev)))
+ return (err);
+
+ smctr_enable_bic_int(dev);
+
+ if((err = smctr_issue_enable_int_cmd(dev, TRC_INTERRUPT_ENABLE_MASK)))
+ return (err);
+
+ smctr_disable_16bit(dev);
+
+ return (0);
+}
+
+/* Dummy function */
+static int __init smctr_init_card(struct net_device *dev)
+{
+ if(smctr_debug > 10)
+ printk("%s: smctr_init_card\n", dev->name);
+
+ return (0);
+}
+
+static int smctr_init_card_real(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int err = 0;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_init_card_real\n", dev->name);
+
+ tp->sh_mem_used = 0;
+ tp->num_acbs = NUM_OF_ACBS;
+
+ /* Range Check Max Packet Size */
+ if(tp->max_packet_size < 256)
+ tp->max_packet_size = 256;
+ else
+ {
+ if(tp->max_packet_size > NON_MAC_TX_BUFFER_MEMORY)
+ tp->max_packet_size = NON_MAC_TX_BUFFER_MEMORY;
+ }
+
+ tp->num_of_tx_buffs = (NON_MAC_TX_BUFFER_MEMORY
+ / tp->max_packet_size) - 1;
+
+ if(tp->num_of_tx_buffs > NUM_NON_MAC_TX_FCBS)
+ tp->num_of_tx_buffs = NUM_NON_MAC_TX_FCBS;
+ else
+ {
+ if(tp->num_of_tx_buffs == 0)
+ tp->num_of_tx_buffs = 1;
+ }
+
+ /* Tx queue constants */
+ tp->num_tx_fcbs [BUG_QUEUE] = NUM_BUG_TX_FCBS;
+ tp->num_tx_bdbs [BUG_QUEUE] = NUM_BUG_TX_BDBS;
+ tp->tx_buff_size [BUG_QUEUE] = BUG_TX_BUFFER_MEMORY;
+ tp->tx_buff_used [BUG_QUEUE] = 0;
+ tp->tx_queue_status [BUG_QUEUE] = NOT_TRANSMITING;
+
+ tp->num_tx_fcbs [MAC_QUEUE] = NUM_MAC_TX_FCBS;
+ tp->num_tx_bdbs [MAC_QUEUE] = NUM_MAC_TX_BDBS;
+ tp->tx_buff_size [MAC_QUEUE] = MAC_TX_BUFFER_MEMORY;
+ tp->tx_buff_used [MAC_QUEUE] = 0;
+ tp->tx_queue_status [MAC_QUEUE] = NOT_TRANSMITING;
+
+ tp->num_tx_fcbs [NON_MAC_QUEUE] = NUM_NON_MAC_TX_FCBS;
+ tp->num_tx_bdbs [NON_MAC_QUEUE] = NUM_NON_MAC_TX_BDBS;
+ tp->tx_buff_size [NON_MAC_QUEUE] = NON_MAC_TX_BUFFER_MEMORY;
+ tp->tx_buff_used [NON_MAC_QUEUE] = 0;
+ tp->tx_queue_status [NON_MAC_QUEUE] = NOT_TRANSMITING;
+
+ /* Receive Queue Constants */
+ tp->num_rx_fcbs[MAC_QUEUE] = NUM_MAC_RX_FCBS;
+ tp->num_rx_bdbs[MAC_QUEUE] = NUM_MAC_RX_BDBS;
+
+ if(tp->extra_info & CHIP_REV_MASK)
+ tp->num_rx_fcbs[NON_MAC_QUEUE] = 78; /* 825 Rev. XE */
+ else
+ tp->num_rx_fcbs[NON_MAC_QUEUE] = 7; /* 825 Rev. XD */
+
+ tp->num_rx_bdbs[NON_MAC_QUEUE] = smctr_get_num_rx_bdbs(dev);
+
+ smctr_alloc_shared_memory(dev);
+ smctr_init_shared_memory(dev);
+
+ if((err = smctr_issue_init_timers_cmd(dev)))
+ return (err);
+
+ if((err = smctr_issue_init_txrx_cmd(dev)))
+ return (err);
+
+ return (0);
+}
+
+static int smctr_init_rx_bdbs(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int i, j;
+ BDBlock *bdb;
+ __u16 *buf;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_init_rx_bdbs\n", dev->name);
+
+ for(i = 0; i < NUM_RX_QS_USED; i++)
+ {
+ bdb = tp->rx_bdb_head[i];
+ buf = tp->rx_buff_head[i];
+ bdb->info = (BDB_CHAIN_END | BDB_NO_WARNING);
+ bdb->buffer_length = RX_DATA_BUFFER_SIZE;
+ bdb->next_ptr = (BDBlock *)(((char *)bdb) + sizeof(BDBlock));
+ bdb->data_block_ptr = buf;
+ bdb->trc_next_ptr = TRC_POINTER(bdb->next_ptr);
+
+ if(i == NON_MAC_QUEUE)
+ bdb->trc_data_block_ptr = RX_BUFF_TRC_POINTER(buf);
+ else
+ bdb->trc_data_block_ptr = TRC_POINTER(buf);
+
+ for(j = 1; j < tp->num_rx_bdbs[i]; j++)
+ {
+ bdb->next_ptr->back_ptr = bdb;
+ bdb = bdb->next_ptr;
+ buf = (__u16 *)((char *)buf + RX_DATA_BUFFER_SIZE);
+ bdb->info = (BDB_NOT_CHAIN_END | BDB_NO_WARNING);
+ bdb->buffer_length = RX_DATA_BUFFER_SIZE;
+ bdb->next_ptr = (BDBlock *)(((char *)bdb) + sizeof(BDBlock));
+ bdb->data_block_ptr = buf;
+ bdb->trc_next_ptr = TRC_POINTER(bdb->next_ptr);
+
+ if(i == NON_MAC_QUEUE)
+ bdb->trc_data_block_ptr = RX_BUFF_TRC_POINTER(buf);
+ else
+ bdb->trc_data_block_ptr = TRC_POINTER(buf);
+ }
+
+ bdb->next_ptr = tp->rx_bdb_head[i];
+ bdb->trc_next_ptr = TRC_POINTER(tp->rx_bdb_head[i]);
+
+ tp->rx_bdb_head[i]->back_ptr = bdb;
+ tp->rx_bdb_curr[i] = tp->rx_bdb_head[i]->next_ptr;
+ }
+
+ return (0);
+}
+
+static int smctr_init_rx_fcbs(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int i, j;
+ FCBlock *fcb;
+
+ for(i = 0; i < NUM_RX_QS_USED; i++)
+ {
+ fcb = tp->rx_fcb_head[i];
+ fcb->frame_status = 0;
+ fcb->frame_length = 0;
+ fcb->info = FCB_CHAIN_END;
+ fcb->next_ptr = (FCBlock *)(((char*)fcb) + sizeof(FCBlock));
+ if(i == NON_MAC_QUEUE)
+ fcb->trc_next_ptr = RX_FCB_TRC_POINTER(fcb->next_ptr);
+ else
+ fcb->trc_next_ptr = TRC_POINTER(fcb->next_ptr);
+
+ for(j = 1; j < tp->num_rx_fcbs[i]; j++)
+ {
+ fcb->next_ptr->back_ptr = fcb;
+ fcb = fcb->next_ptr;
+ fcb->frame_status = 0;
+ fcb->frame_length = 0;
+ fcb->info = FCB_WARNING;
+ fcb->next_ptr
+ = (FCBlock *)(((char *)fcb) + sizeof(FCBlock));
+
+ if(i == NON_MAC_QUEUE)
+ fcb->trc_next_ptr
+ = RX_FCB_TRC_POINTER(fcb->next_ptr);
+ else
+ fcb->trc_next_ptr
+ = TRC_POINTER(fcb->next_ptr);
+ }
+
+ fcb->next_ptr = tp->rx_fcb_head[i];
+
+ if(i == NON_MAC_QUEUE)
+ fcb->trc_next_ptr = RX_FCB_TRC_POINTER(fcb->next_ptr);
+ else
+ fcb->trc_next_ptr = TRC_POINTER(fcb->next_ptr);
+
+ tp->rx_fcb_head[i]->back_ptr = fcb;
+ tp->rx_fcb_curr[i] = tp->rx_fcb_head[i]->next_ptr;
+ }
+
+ return(0);
+}
+
+static int smctr_init_shared_memory(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int i;
+ __u32 *iscpb;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_init_shared_memory\n", dev->name);
+
+ smctr_set_page(dev, (__u8 *)(unsigned int)tp->iscpb_ptr);
+
+ /* Initialize Initial System Configuration Point. (ISCP) */
+ iscpb = (__u32 *)PAGE_POINTER(&tp->iscpb_ptr->trc_scgb_ptr);
+ *iscpb = (__u32)(SWAP_WORDS(TRC_POINTER(tp->scgb_ptr)));
+
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+ /* Initialize System Configuration Pointers. (SCP) */
+ tp->scgb_ptr->config = (SCGB_ADDRESS_POINTER_FORMAT
+ | SCGB_MULTI_WORD_CONTROL | SCGB_DATA_FORMAT
+ | SCGB_BURST_LENGTH);
+
+ tp->scgb_ptr->trc_sclb_ptr = TRC_POINTER(tp->sclb_ptr);
+ tp->scgb_ptr->trc_acb_ptr = TRC_POINTER(tp->acb_head);
+ tp->scgb_ptr->trc_isb_ptr = TRC_POINTER(tp->isb_ptr);
+ tp->scgb_ptr->isbsiz = (sizeof(ISBlock)) - 2;
+
+ /* Initialize System Control Block. (SCB) */
+ tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_CMD_NOP;
+ tp->sclb_ptr->iack_code = 0;
+ tp->sclb_ptr->resume_control = 0;
+ tp->sclb_ptr->int_mask_control = 0;
+ tp->sclb_ptr->int_mask_state = 0;
+
+ /* Initialize Interrupt Status Block. (ISB) */
+ for(i = 0; i < NUM_OF_INTERRUPTS; i++)
+ {
+ tp->isb_ptr->IStatus[i].IType = 0xf0;
+ tp->isb_ptr->IStatus[i].ISubtype = 0;
+ }
+
+ tp->current_isb_index = 0;
+
+ /* Initialize Action Command Block. (ACB) */
+ smctr_init_acbs(dev);
+
+ /* Initialize transmit FCB's and BDB's. */
+ smctr_link_tx_fcbs_to_bdbs(dev);
+ smctr_init_tx_bdbs(dev);
+ smctr_init_tx_fcbs(dev);
+
+ /* Initialize receive FCB's and BDB's. */
+ smctr_init_rx_bdbs(dev);
+ smctr_init_rx_fcbs(dev);
+
+ return (0);
+}
+
+static int smctr_init_tx_bdbs(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int i, j;
+ BDBlock *bdb;
+
+ for(i = 0; i < NUM_TX_QS_USED; i++)
+ {
+ bdb = tp->tx_bdb_head[i];
+ bdb->info = (BDB_NOT_CHAIN_END | BDB_NO_WARNING);
+ bdb->next_ptr = (BDBlock *)(((char *)bdb) + sizeof(BDBlock));
+ bdb->trc_next_ptr = TRC_POINTER(bdb->next_ptr);
+
+ for(j = 1; j < tp->num_tx_bdbs[i]; j++)
+ {
+ bdb->next_ptr->back_ptr = bdb;
+ bdb = bdb->next_ptr;
+ bdb->info = (BDB_NOT_CHAIN_END | BDB_NO_WARNING);
+ bdb->next_ptr
+ = (BDBlock *)(((char *)bdb) + sizeof( BDBlock)); bdb->trc_next_ptr = TRC_POINTER(bdb->next_ptr);
+ }
+
+ bdb->next_ptr = tp->tx_bdb_head[i];
+ bdb->trc_next_ptr = TRC_POINTER(tp->tx_bdb_head[i]);
+ tp->tx_bdb_head[i]->back_ptr = bdb;
+ }
+
+ return (0);
+}
+
+static int smctr_init_tx_fcbs(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int i, j;
+ FCBlock *fcb;
+
+ for(i = 0; i < NUM_TX_QS_USED; i++)
+ {
+ fcb = tp->tx_fcb_head[i];
+ fcb->frame_status = 0;
+ fcb->frame_length = 0;
+ fcb->info = FCB_CHAIN_END;
+ fcb->next_ptr = (FCBlock *)(((char *)fcb) + sizeof(FCBlock));
+ fcb->trc_next_ptr = TRC_POINTER(fcb->next_ptr);
+
+ for(j = 1; j < tp->num_tx_fcbs[i]; j++)
+ {
+ fcb->next_ptr->back_ptr = fcb;
+ fcb = fcb->next_ptr;
+ fcb->frame_status = 0;
+ fcb->frame_length = 0;
+ fcb->info = FCB_CHAIN_END;
+ fcb->next_ptr
+ = (FCBlock *)(((char *)fcb) + sizeof(FCBlock));
+ fcb->trc_next_ptr = TRC_POINTER(fcb->next_ptr);
+ }
+
+ fcb->next_ptr = tp->tx_fcb_head[i];
+ fcb->trc_next_ptr = TRC_POINTER(tp->tx_fcb_head[i]);
+
+ tp->tx_fcb_head[i]->back_ptr = fcb;
+ tp->tx_fcb_end[i] = tp->tx_fcb_head[i]->next_ptr;
+ tp->tx_fcb_curr[i] = tp->tx_fcb_head[i]->next_ptr;
+ tp->num_tx_fcbs_used[i] = 0;
+ }
+
+ return (0);
+}
+
+static int smctr_internal_self_test(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int err;
+
+ if((err = smctr_issue_test_internal_rom_cmd(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ if(tp->acb_head->cmd_done_status & 0xff)
+ return (-1);
+
+ if((err = smctr_issue_test_hic_cmd(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ if(tp->acb_head->cmd_done_status & 0xff)
+ return (-1);
+
+ if((err = smctr_issue_test_mac_reg_cmd(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ if(tp->acb_head->cmd_done_status & 0xff)
+ return (-1);
+
+ return (0);
+}
+
+/*
+ * The typical workload of the driver: Handle the network interface interrupts.
+ */
+static void smctr_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct net_local *tp;
+ int ioaddr;
+ __u16 interrupt_unmask_bits = 0, interrupt_ack_code = 0xff00;
+ __u16 err1, err = NOT_MY_INTERRUPT;
+ __u8 isb_type, isb_subtype;
+ __u16 isb_index;
+
+ if(dev == NULL)
+ {
+ printk("%s: irq %d for unknown device.\n", dev->name, irq);
+ return;
+ }
+
+ dev->interrupt = 1;
+
+ ioaddr = dev->base_addr;
+ tp = (struct net_local *)dev->priv;
+
+ dev->interrupt = 0;
+
+ if(tp->status == NOT_INITIALIZED)
+ return;
+
+ smctr_disable_bic_int(dev);
+ smctr_enable_16bit(dev);
+
+ smctr_clear_int(dev);
+
+ /* First read the LSB */
+ while((tp->isb_ptr->IStatus[tp->current_isb_index].IType & 0xf0) == 0)
+ {
+ isb_index = tp->current_isb_index;
+ isb_type = tp->isb_ptr->IStatus[isb_index].IType;
+ isb_subtype = tp->isb_ptr->IStatus[isb_index].ISubtype;
+
+ (tp->current_isb_index)++;
+ if(tp->current_isb_index == NUM_OF_INTERRUPTS)
+ tp->current_isb_index = 0;
+
+ if(isb_type >= 0x10)
+ {
+ smctr_disable_16bit(dev);
+ return;
+ }
+
+ err = HARDWARE_FAILED;
+ interrupt_ack_code = isb_index;
+ tp->isb_ptr->IStatus[isb_index].IType |= 0xf0;
+
+ interrupt_unmask_bits |= (1 << (__u16)isb_type);
+
+ switch(isb_type)
+ {
+ case ISB_IMC_MAC_TYPE_3:
+ smctr_disable_16bit(dev);
+
+ switch(isb_subtype)
+ {
+ case 0:
+ tp->monitor_state
+ = MS_MONITOR_FSM_INACTIVE;
+ break;
+
+ case 1:
+ tp->monitor_state
+ = MS_REPEAT_BEACON_STATE;
+ break;
+
+ case 2:
+ tp->monitor_state
+ = MS_REPEAT_CLAIM_TOKEN_STATE;
+ break;
+
+ case 3:
+ tp->monitor_state
+ = MS_TRANSMIT_CLAIM_TOKEN_STATE; break;
+
+ case 4:
+ tp->monitor_state
+ = MS_STANDBY_MONITOR_STATE;
+ break;
+
+ case 5:
+ tp->monitor_state
+ = MS_TRANSMIT_BEACON_STATE;
+ break;
+
+ case 6:
+ tp->monitor_state
+ = MS_ACTIVE_MONITOR_STATE;
+ break;
+
+ case 7:
+ tp->monitor_state
+ = MS_TRANSMIT_RING_PURGE_STATE;
+ break;
+
+ case 8: /* diagnostic state */
+ break;
+
+ case 9:
+ tp->monitor_state
+ = MS_BEACON_TEST_STATE;
+ if(smctr_lobe_media_test(dev))
+ {
+ tp->ring_status_flags
+ = RING_STATUS_CHANGED;
+ tp->ring_status
+ = AUTO_REMOVAL_ERROR;
+ smctr_ring_status_chg(dev);
+ smctr_bypass_state(dev);
+ }
+ else
+ smctr_issue_insert_cmd(dev);
+ break;
+
+ /* case 0x0a-0xff, illegal states */
+ default:
+ break;
+ }
+
+ tp->ring_status_flags = MONITOR_STATE_CHANGED;
+ err = smctr_ring_status_chg(dev);
+
+ smctr_enable_16bit(dev);
+ break;
+
+ /* Type 0x02 - MAC Error Counters Interrupt
+ * One or more MAC Error Counter is half full
+ * MAC Error Counters
+ * Lost_FR_Error_Counter
+ * RCV_Congestion_Counter
+ * FR_copied_Error_Counter
+ * FREQ_Error_Counter
+ * Token_Error_Counter
+ * Line_Error_Counter
+ * Internal_Error_Count
+ */
+ case ISB_IMC_MAC_ERROR_COUNTERS:
+ /* Read 802.5 Error Counters */
+ err = smctr_issue_read_ring_status_cmd(dev);
+ break;
+
+ /* Type 0x04 - MAC Type 2 Interrupt
+ * HOST needs to enqueue MAC Frame for transmission
+ * SubType Bit 15 - RQ_INIT_PDU( Request Initialization) * Changed from RQ_INIT_PDU to
+ * TRC_Status_Changed_Indicate
+ */
+ case ISB_IMC_MAC_TYPE_2:
+ err = smctr_issue_read_ring_status_cmd(dev);
+ break;
+
+
+ /* Type 0x05 - TX Frame Interrupt (FI). */
+ case ISB_IMC_TX_FRAME:
+ /* BUG QUEUE for TRC stuck receive BUG */
+ if(isb_subtype & TX_PENDING_PRIORITY_2)
+ {
+ if((err = smctr_tx_complete(dev,
+ BUG_QUEUE)) != SUCCESS)
+ break;
+ }
+
+ /* NON-MAC frames only */
+ if(isb_subtype & TX_PENDING_PRIORITY_1)
+ {
+ if((err = smctr_tx_complete(dev,
+ NON_MAC_QUEUE)) != SUCCESS)
+ break;
+ }
+
+ /* MAC frames only */
+ if(isb_subtype & TX_PENDING_PRIORITY_0)
+ err = smctr_tx_complete(dev, MAC_QUEUE); break;
+
+ /* Type 0x06 - TX END OF QUEUE (FE) */
+ case ISB_IMC_END_OF_TX_QUEUE:
+ /* BUG queue */
+ if(isb_subtype & TX_PENDING_PRIORITY_2)
+ {
+ /* ok to clear Receive FIFO overrun
+ * imask send_BUG now completes.
+ */
+ interrupt_unmask_bits |= 0x800;
+
+ tp->tx_queue_status[BUG_QUEUE]
+ = NOT_TRANSMITING;
+ if((err = smctr_tx_complete(dev,
+ BUG_QUEUE)) != SUCCESS)
+ break;
+ if((err = smctr_restart_tx_chain(dev,
+ BUG_QUEUE)) != SUCCESS)
+ break;
+ }
+
+ /* NON-MAC queue only */
+ if(isb_subtype & TX_PENDING_PRIORITY_1)
+ {
+ tp->tx_queue_status[NON_MAC_QUEUE]
+ = NOT_TRANSMITING;
+ if((err = smctr_tx_complete(dev,
+ NON_MAC_QUEUE)) != SUCCESS)
+ break;
+ if((err = smctr_restart_tx_chain(dev,
+ NON_MAC_QUEUE)) != SUCCESS)
+ break;
+ }
+
+ /* MAC queue only */
+ if(isb_subtype & TX_PENDING_PRIORITY_0)
+ {
+ tp->tx_queue_status[MAC_QUEUE]
+ = NOT_TRANSMITING;
+ if((err = smctr_tx_complete(dev,
+ MAC_QUEUE)) != SUCCESS)
+ break;
+
+ err = smctr_restart_tx_chain(dev,
+ MAC_QUEUE);
+ }
+ break;
+
+ /* Type 0x07 - NON-MAC RX Resource Interrupt
+ * Subtype bit 12 - (BW) BDB warning
+ * Subtype bit 13 - (FW) FCB warning
+ * Subtype bit 14 - (BE) BDB End of chain
+ * Subtype bit 15 - (FE) FCB End of chain
+ */
+ case ISB_IMC_NON_MAC_RX_RESOURCE:
+ tp->rx_fifo_overrun_count = 0;
+ tp->receive_queue_number = NON_MAC_QUEUE;
+ err1 = smctr_rx_frame(dev);
+
+ if(isb_subtype & NON_MAC_RX_RESOURCE_FE)
+ {
+ if((err = smctr_issue_resume_rx_fcb_cmd( dev, NON_MAC_QUEUE)) != SUCCESS) break;
+
+ if(tp->ptr_rx_fcb_overruns)
+ (*tp->ptr_rx_fcb_overruns)++;
+ }
+
+ if(isb_subtype & NON_MAC_RX_RESOURCE_BE)
+ {
+ if((err = smctr_issue_resume_rx_bdb_cmd( dev, NON_MAC_QUEUE)) != SUCCESS) break;
+
+ if(tp->ptr_rx_bdb_overruns)
+ (*tp->ptr_rx_bdb_overruns)++;
+ }
+ err = err1;
+ break;
+
+ /* Type 0x08 - MAC RX Resource Interrupt
+ * Subtype bit 12 - (BW) BDB warning
+ * Subtype bit 13 - (FW) FCB warning
+ * Subtype bit 14 - (BE) BDB End of chain
+ * Subtype bit 15 - (FE) FCB End of chain
+ */
+ case ISB_IMC_MAC_RX_RESOURCE:
+ tp->receive_queue_number = MAC_QUEUE;
+ err1 = smctr_rx_frame(dev);
+
+ if(isb_subtype & MAC_RX_RESOURCE_FE)
+ {
+ if((err = smctr_issue_resume_rx_fcb_cmd( dev, MAC_QUEUE)) != SUCCESS)
+ break;
+
+ if(tp->ptr_rx_fcb_overruns)
+ (*tp->ptr_rx_fcb_overruns)++;
+ }
+
+ if(isb_subtype & MAC_RX_RESOURCE_BE)
+ {
+ if((err = smctr_issue_resume_rx_bdb_cmd( dev, MAC_QUEUE)) != SUCCESS)
+ break;
+
+ if(tp->ptr_rx_bdb_overruns)
+ (*tp->ptr_rx_bdb_overruns)++;
+ }
+ err = err1;
+ break;
+
+ /* Type 0x09 - NON_MAC RX Frame Interrupt */
+ case ISB_IMC_NON_MAC_RX_FRAME:
+ tp->rx_fifo_overrun_count = 0;
+ tp->receive_queue_number = NON_MAC_QUEUE;
+ err = smctr_rx_frame(dev);
+ break;
+
+ /* Type 0x0A - MAC RX Frame Interrupt */
+ case ISB_IMC_MAC_RX_FRAME:
+ tp->receive_queue_number = MAC_QUEUE;
+ err = smctr_rx_frame(dev);
+ break;
+
+ /* Type 0x0B - TRC status
+ * TRC has encountered an error condition
+ * subtype bit 14 - transmit FIFO underrun
+ * subtype bit 15 - receive FIFO overrun
+ */
+ case ISB_IMC_TRC_FIFO_STATUS:
+ if(isb_subtype & TRC_FIFO_STATUS_TX_UNDERRUN)
+ {
+ if(tp->ptr_tx_fifo_underruns)
+ (*tp->ptr_tx_fifo_underruns)++;
+ }
+
+ if(isb_subtype & TRC_FIFO_STATUS_RX_OVERRUN)
+ {
+ /* update overrun stuck receive counter
+ * if >= 3, has to clear it by sending
+ * back to back frames. We pick
+ * DAT(duplicate address MAC frame)
+ */
+ tp->rx_fifo_overrun_count++;
+
+ if(tp->rx_fifo_overrun_count >= 3)
+ {
+ tp->rx_fifo_overrun_count = 0;
+
+ /* delay clearing fifo overrun
+ * imask till send_BUG tx
+ * complete posted
+ */
+ interrupt_unmask_bits &= (~0x800);
+ printk("Jay please send bug\n");// smctr_send_bug(dev);
+ }
+
+ if(tp->ptr_rx_fifo_overruns)
+ (*tp->ptr_rx_fifo_overruns)++;
+ }
+
+ err = SUCCESS;
+ break;
+
+ /* Type 0x0C - Action Command Status Interrupt
+ * Subtype bit 14 - CB end of command chain (CE)
+ * Subtype bit 15 - CB command interrupt (CI)
+ */
+ case ISB_IMC_COMMAND_STATUS:
+ err = SUCCESS;
+ if(tp->acb_head->cmd == ACB_CMD_HIC_NOP)
+ {
+ printk("i1\n");
+ smctr_disable_16bit(dev);
+
+ /* XXXXXXXXXXXXXXXXX */
+ /* err = UM_Interrupt(dev); */
+
+ smctr_enable_16bit(dev);
+ }
+ else
+ {
+ if((tp->acb_head->cmd
+ == ACB_CMD_READ_TRC_STATUS)
+ && (tp->acb_head->subcmd
+ == RW_TRC_STATUS_BLOCK))
+ {
+ if(tp->ptr_bcn_type != 0)
+ {
+ *(tp->ptr_bcn_type)
+ = (__u32)((SBlock *)tp->misc_command_data)->BCN_Type;
+ }
+
+ if(((SBlock *)tp->misc_command_data)->Status_CHG_Indicate & ERROR_COUNTERS_CHANGED)
+ {
+ smctr_update_err_stats(dev);
+ }
+
+ if(((SBlock *)tp->misc_command_data)->Status_CHG_Indicate & TI_NDIS_RING_STATUS_CHANGED)
+ {
+ tp->ring_status
+ = ((SBlock*)tp->misc_command_data)->TI_NDIS_Ring_Status;
+ smctr_disable_16bit(dev);
+ err = smctr_ring_status_chg(dev);
+ smctr_enable_16bit(dev);
+ if((tp->ring_status & REMOVE_RECEIVED)
+ && (tp->config_word0 & NO_AUTOREMOVE))
+ {
+ smctr_issue_remove_cmd(dev);
+ }
+
+ if(err != SUCCESS)
+ {
+ tp->acb_pending
+= 0;
+ break;
+ }
+ }
+
+ if(((SBlock *)tp->misc_command_data)->Status_CHG_Indicate & UNA_CHANGED)
+ {
+ if(tp->ptr_una)
+ {
+ tp->ptr_una[0]
+ = SWAP_BYTES(((SBlock *)tp->misc_command_data)->UNA[0]);
+ tp->ptr_una[1]
+ = SWAP_BYTES(((SBlock *)tp->misc_command_data)->UNA[1]);
+ tp->ptr_una[2]
+ = SWAP_BYTES(((SBlock *)tp->misc_command_data)->UNA[2]);
+ }
+
+ }
+
+ if(((SBlock *)tp->misc_command_data)->Status_CHG_Indicate
+ & READY_TO_SEND_RQ_INIT) {
+ err = smctr_send_rq_init(dev);
+ }
+ }
+ }
+
+ tp->acb_pending = 0;
+ break;
+
+ /* Type 0x0D - MAC Type 1 interrupt
+ * Subtype -- 00 FR_BCN received at S12
+ * 01 FR_BCN received at S21
+ * 02 FR_DAT(DA=MA, A<>0) received at S21
+ * 03 TSM_EXP at S21
+ * 04 FR_REMOVE received at S42
+ * 05 TBR_EXP, BR_FLAG_SET at S42
+ * 06 TBT_EXP at S53
+ */
+ case ISB_IMC_MAC_TYPE_1:
+ if(isb_subtype > 8)
+ {
+ err = HARDWARE_FAILED;
+ break;
+ }
+
+ err = SUCCESS;
+ switch(isb_subtype)
+ {
+ case 0:
+ tp->join_state = JS_BYPASS_STATE;
+ if(tp->status != CLOSED)
+ {
+ tp->status = CLOSED;
+ err = smctr_status_chg(dev);
+ }
+ break;
+
+ case 1:
+ tp->join_state
+ = JS_LOBE_TEST_STATE;
+ break;
+
+ case 2:
+ tp->join_state
+ = JS_DETECT_MONITOR_PRESENT_STATE;
+ break;
+
+ case 3:
+ tp->join_state
+ = JS_AWAIT_NEW_MONITOR_STATE;
+ break;
+
+ case 4:
+ tp->join_state
+ = JS_DUPLICATE_ADDRESS_TEST_STATE;
+ break;
+
+ case 5:
+ tp->join_state
+ = JS_NEIGHBOR_NOTIFICATION_STATE;
+ break;
+
+ case 6:
+ tp->join_state
+ = JS_REQUEST_INITIALIZATION_STATE;
+ break;
+
+ case 7:
+ tp->join_state
+ = JS_JOIN_COMPLETE_STATE;
+ tp->status = OPEN;
+ err = smctr_status_chg(dev);
+ break;
+
+ case 8:
+ tp->join_state
+ = JS_BYPASS_WAIT_STATE;
+ break;
+ }
+ break ;
+
+ /* Type 0x0E - TRC Initialization Sequence Interrupt
+ * Subtype -- 00-FF Initializatin sequence complete
+ */
+ case ISB_IMC_TRC_INTRNL_TST_STATUS:
+ tp->status = INITIALIZED;
+ smctr_disable_16bit(dev);
+ err = smctr_status_chg(dev);
+ smctr_enable_16bit(dev);
+ break;
+
+ /* other interrupt types, illegal */
+ default:
+ break;
+ }
+
+ if(err != SUCCESS)
+ break;
+ }
+
+ /* Checking the ack code instead of the unmask bits here is because :
+ * while fixing the stuck receive, DAT frame are sent and mask off
+ * FIFO overrun interrupt temporarily (interrupt_unmask_bits = 0)
+ * but we still want to issue ack to ISB
+ */
+ if(!(interrupt_ack_code & 0xff00))
+ smctr_issue_int_ack(dev, interrupt_ack_code,
+ interrupt_unmask_bits);
+
+ smctr_disable_16bit(dev);
+ smctr_enable_bic_int(dev);
+
+ return;
+}
+
+static int smctr_issue_enable_int_cmd(struct net_device *dev,
+ __u16 interrupt_enable_mask)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int err;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ tp->sclb_ptr->int_mask_control = interrupt_enable_mask;
+ tp->sclb_ptr->valid_command = SCLB_VALID
+ | SCLB_CMD_CLEAR_INTERRUPT_MASK;
+
+ smctr_set_ctrl_attention(dev);
+
+ return (0);
+}
+
+static int smctr_issue_int_ack(struct net_device *dev, __u16 iack_code,
+ __u16 ibits)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ if(smctr_wait_while_cbusy(dev))
+ return (-1);
+
+ tp->sclb_ptr->int_mask_control = ibits;
+ tp->sclb_ptr->iack_code = iack_code << 1; /* use the offset from base */ tp->sclb_ptr->resume_control = 0;
+ tp->sclb_ptr->valid_command =
+ SCLB_VALID | SCLB_IACK_CODE_VALID
+ | SCLB_CMD_CLEAR_INTERRUPT_MASK;
+
+ smctr_set_ctrl_attention(dev);
+
+ return (0);
+}
+
+static int smctr_issue_init_timers_cmd(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int i;
+ int err;
+ __u16 *pTimer_Struc = (__u16 *)tp->misc_command_data;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ tp->config_word0 = THDREN | DMA_TRIGGER | USETPT | NO_AUTOREMOVE;
+ tp->config_word1 = 0;
+
+ if((tp->media_type == MEDIA_STP_16)
+ || (tp->media_type == MEDIA_UTP_16)
+ || (tp->media_type == MEDIA_STP_16_UTP_16))
+ {
+ tp->config_word0 |= FREQ_16MB_BIT;
+ }
+
+ if(tp->mode_bits & EARLY_TOKEN_REL)
+ tp->config_word0 |= ETREN;
+
+ if(tp->mode_bits & LOOPING_MODE_MASK)
+ tp->config_word0 |= RX_OWN_BIT;
+ else
+ tp->config_word0 &= ~RX_OWN_BIT;
+
+ if(tp->receive_mask & PROMISCUOUS_MODE)
+ tp->config_word0 |= PROMISCUOUS_BIT;
+ else
+ tp->config_word0 &= ~PROMISCUOUS_BIT;
+
+ if(tp->receive_mask & ACCEPT_ERR_PACKETS)
+ tp->config_word0 |= SAVBAD_BIT;
+ else
+ tp->config_word0 &= ~SAVBAD_BIT;
+
+ if(tp->receive_mask & ACCEPT_ATT_MAC_FRAMES)
+ tp->config_word0 |= RXATMAC;
+ else
+ tp->config_word0 &= ~RXATMAC;
+
+ if(tp->receive_mask & ACCEPT_MULTI_PROM)
+ tp->config_word1 |= MULTICAST_ADDRESS_BIT;
+ else
+ tp->config_word1 &= ~MULTICAST_ADDRESS_BIT;
+
+ if(tp->receive_mask & ACCEPT_SOURCE_ROUTING_SPANNING)
+ tp->config_word1 |= SOURCE_ROUTING_SPANNING_BITS;
+ else
+ {
+ if(tp->receive_mask & ACCEPT_SOURCE_ROUTING)
+ tp->config_word1 |= SOURCE_ROUTING_EXPLORER_BIT;
+ else
+ tp->config_word1 &= ~SOURCE_ROUTING_SPANNING_BITS;
+ }
+
+ if((tp->media_type == MEDIA_STP_16)
+ || (tp->media_type == MEDIA_UTP_16)
+ || (tp->media_type == MEDIA_STP_16_UTP_16))
+ {
+ tp->config_word1 |= INTERFRAME_SPACING_16;
+ }
+ else
+ tp->config_word1 |= INTERFRAME_SPACING_4;
+
+ *pTimer_Struc++ = tp->config_word0;
+ *pTimer_Struc++ = tp->config_word1;
+
+ if((tp->media_type == MEDIA_STP_4)
+ || (tp->media_type == MEDIA_UTP_4)
+ || (tp->media_type == MEDIA_STP_4_UTP_4))
+ {
+ *pTimer_Struc++ = 0x00FA; /* prescale */
+ *pTimer_Struc++ = 0x2710; /* TPT_limit */
+ *pTimer_Struc++ = 0x2710; /* TQP_limit */
+ *pTimer_Struc++ = 0x0A28; /* TNT_limit */
+ *pTimer_Struc++ = 0x3E80; /* TBT_limit */
+ *pTimer_Struc++ = 0x3A98; /* TSM_limit */
+ *pTimer_Struc++ = 0x1B58; /* TAM_limit */
+ *pTimer_Struc++ = 0x00C8; /* TBR_limit */
+ *pTimer_Struc++ = 0x07D0; /* TER_limit */
+ *pTimer_Struc++ = 0x000A; /* TGT_limit */
+ *pTimer_Struc++ = 0x1162; /* THT_limit */
+ *pTimer_Struc++ = 0x07D0; /* TRR_limit */
+ *pTimer_Struc++ = 0x1388; /* TVX_limit */
+ *pTimer_Struc++ = 0x0000; /* reserved */
+ }
+ else
+ {
+ *pTimer_Struc++ = 0x03E8; /* prescale */
+ *pTimer_Struc++ = 0x9C40; /* TPT_limit */
+ *pTimer_Struc++ = 0x9C40; /* TQP_limit */
+ *pTimer_Struc++ = 0x0A28; /* TNT_limit */
+ *pTimer_Struc++ = 0x3E80; /* TBT_limit */
+ *pTimer_Struc++ = 0x3A98; /* TSM_limit */
+ *pTimer_Struc++ = 0x1B58; /* TAM_limit */
+ *pTimer_Struc++ = 0x00C8; /* TBR_limit */
+ *pTimer_Struc++ = 0x07D0; /* TER_limit */
+ *pTimer_Struc++ = 0x000A; /* TGT_limit */
+ *pTimer_Struc++ = 0x4588; /* THT_limit */
+ *pTimer_Struc++ = 0x1F40; /* TRR_limit */
+ *pTimer_Struc++ = 0x4E20; /* TVX_limit */
+ *pTimer_Struc++ = 0x0000; /* reserved */
+ }
+
+ /* Set node address. */
+ *pTimer_Struc++ = dev->dev_addr[0] << 8
+ | (dev->dev_addr[1] & 0xFF);
+ *pTimer_Struc++ = dev->dev_addr[2] << 8
+ | (dev->dev_addr[3] & 0xFF);
+ *pTimer_Struc++ = dev->dev_addr[4] << 8
+ | (dev->dev_addr[5] & 0xFF);
+
+ /* Set group address. */
+ *pTimer_Struc++ = tp->group_address_0 << 8
+ | tp->group_address_0 >> 8;
+ *pTimer_Struc++ = tp->group_address[0] << 8
+ | tp->group_address[0] >> 8;
+ *pTimer_Struc++ = tp->group_address[1] << 8
+ | tp->group_address[1] >> 8;
+
+ /* Set functional address. */
+ *pTimer_Struc++ = tp->functional_address_0 << 8
+ | tp->functional_address_0 >> 8;
+ *pTimer_Struc++ = tp->functional_address[0] << 8
+ | tp->functional_address[0] >> 8;
+ *pTimer_Struc++ = tp->functional_address[1] << 8
+ | tp->functional_address[1] >> 8;
+
+ /* Set Bit-Wise group address. */
+ *pTimer_Struc++ = tp->bitwise_group_address[0] << 8
+ | tp->bitwise_group_address[0] >> 8;
+ *pTimer_Struc++ = tp->bitwise_group_address[1] << 8
+ | tp->bitwise_group_address[1] >> 8;
+
+ /* Set ring number address. */
+ *pTimer_Struc++ = tp->source_ring_number;
+ *pTimer_Struc++ = tp->target_ring_number;
+
+ /* Physical drop number. */
+ *pTimer_Struc++ = (unsigned short)0;
+ *pTimer_Struc++ = (unsigned short)0;
+
+ /* Product instance ID. */
+ for(i = 0; i < 9; i++)
+ *pTimer_Struc++ = (unsigned short)0;
+
+ err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_INIT_TRC_TIMERS, 0);
+
+ return (err);
+}
+
+static int smctr_issue_init_txrx_cmd(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int i;
+ int err;
+ void **txrx_ptrs = (void *)tp->misc_command_data;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ /* Initialize Transmit Queue Pointers that are used, to point to
+ * a single FCB.
+ */
+ for(i = 0; i < NUM_TX_QS_USED; i++)
+ *txrx_ptrs++ = (void *)TRC_POINTER(tp->tx_fcb_head[i]);
+
+ /* Initialize Transmit Queue Pointers that are NOT used to ZERO. */
+ for(; i < MAX_TX_QS; i++)
+ *txrx_ptrs++ = (void *)0;
+
+ /* Initialize Receive Queue Pointers (MAC and Non-MAC) that are
+ * used, to point to a single FCB and a BDB chain of buffers.
+ */
+ for(i = 0; i < NUM_RX_QS_USED; i++)
+ {
+ *txrx_ptrs++ = (void *)TRC_POINTER(tp->rx_fcb_head[i]);
+ *txrx_ptrs++ = (void *)TRC_POINTER(tp->rx_bdb_head[i]);
+ }
+
+ /* Initialize Receive Queue Pointers that are NOT used to ZERO. */
+ for(; i < MAX_RX_QS; i++)
+ {
+ *txrx_ptrs++ = (void *)0;
+ *txrx_ptrs++ = (void *)0;
+ }
+
+ err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_INIT_TX_RX, 0);
+
+ return (err);
+}
+
+static int smctr_issue_insert_cmd(struct net_device *dev)
+{
+ int err;
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_INSERT, ACB_SUB_CMD_NOP);
+
+ return (err);
+}
+
+static int smctr_issue_read_ring_status_cmd(struct net_device *dev)
+{
+ int err;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_READ_TRC_STATUS,
+ RW_TRC_STATUS_BLOCK);
+
+ return (err);
+}
+
+static int smctr_issue_read_word_cmd(struct net_device *dev, __u16 aword_cnt)
+{
+ int err;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_READ_VALUE,
+ aword_cnt);
+
+ return (err);
+}
+
+static int smctr_issue_remove_cmd(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int err;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ tp->sclb_ptr->resume_control = 0;
+ tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_CMD_REMOVE;
+
+ smctr_set_ctrl_attention(dev);
+
+ return (0);
+}
+
+static int smctr_issue_resume_acb_cmd(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int err;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ tp->sclb_ptr->resume_control = SCLB_RC_ACB;
+ tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_RESUME_CONTROL_VALID;
+
+ tp->acb_pending = 1;
+
+ smctr_set_ctrl_attention(dev);
+
+ return (0);
+}
+
+static int smctr_issue_resume_rx_bdb_cmd(struct net_device *dev, __u16 queue)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int err;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ if(queue == MAC_QUEUE)
+ tp->sclb_ptr->resume_control = SCLB_RC_RX_MAC_BDB;
+ else
+ tp->sclb_ptr->resume_control = SCLB_RC_RX_NON_MAC_BDB;
+
+ tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_RESUME_CONTROL_VALID;
+
+ smctr_set_ctrl_attention(dev);
+
+ return (0);
+}
+
+static int smctr_issue_resume_rx_fcb_cmd(struct net_device *dev, __u16 queue)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_issue_resume_rx_fcb_cmd\n", dev->name);
+
+ if(smctr_wait_while_cbusy(dev))
+ return (-1);
+
+ if(queue == MAC_QUEUE)
+ tp->sclb_ptr->resume_control = SCLB_RC_RX_MAC_FCB;
+ else
+ tp->sclb_ptr->resume_control = SCLB_RC_RX_NON_MAC_FCB;
+
+ tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_RESUME_CONTROL_VALID;
+
+ smctr_set_ctrl_attention(dev);
+
+ return (0);
+}
+
+static int smctr_issue_resume_tx_fcb_cmd(struct net_device *dev, __u16 queue)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_issue_resume_tx_fcb_cmd\n", dev->name);
+
+ if(smctr_wait_while_cbusy(dev))
+ return (-1);
+
+ tp->sclb_ptr->resume_control = (SCLB_RC_TFCB0 << queue);
+ tp->sclb_ptr->valid_command = SCLB_RESUME_CONTROL_VALID | SCLB_VALID;
+
+ smctr_set_ctrl_attention(dev);
+
+ return (0);
+}
+
+static int smctr_issue_test_internal_rom_cmd(struct net_device *dev)
+{
+ int err;
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
+ TRC_INTERNAL_ROM_TEST);
+
+ return (err);
+}
+
+static int smctr_issue_test_hic_cmd(struct net_device *dev)
+{
+ int err;
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_HIC_TEST,
+ TRC_HOST_INTERFACE_REG_TEST);
+
+ return (err);
+}
+
+static int smctr_issue_test_mac_reg_cmd(struct net_device *dev)
+{
+ int err;
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
+ TRC_MAC_REGISTERS_TEST);
+
+ return (err);
+}
+
+static int smctr_issue_trc_loopback_cmd(struct net_device *dev)
+{
+ int err;
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
+ TRC_INTERNAL_LOOPBACK);
+
+ return (err);
+}
+
+static int smctr_issue_tri_loopback_cmd(struct net_device *dev)
+{
+ int err;
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
+ TRC_TRI_LOOPBACK);
+
+ return (err);
+}
+
+static int smctr_issue_write_byte_cmd(struct net_device *dev,
+ short aword_cnt, void *byte)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int iword, ibyte;
+ int err;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ for(iword = 0, ibyte = 0; iword < (unsigned int)(aword_cnt & 0xff);
+ iword++, ibyte += 2)
+ {
+ tp->misc_command_data[iword] = (*((__u8 *)byte + ibyte) << 8)
+ | (*((__u8 *)byte + ibyte + 1));
+ }
+
+ return (smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_WRITE_VALUE,
+ aword_cnt));
+}
+
+static int smctr_issue_write_word_cmd(struct net_device *dev,
+ short aword_cnt, void *word)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int i, err;
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ for(i = 0; i < (unsigned int)(aword_cnt & 0xff); i++)
+ tp->misc_command_data[i] = *((__u16 *)word + i);
+
+ err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_WRITE_VALUE,
+ aword_cnt);
+
+ return (err);
+}
+
+static int smctr_join_complete_state(struct net_device *dev)
+{
+ int err;
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE,
+ JS_JOIN_COMPLETE_STATE);
+
+ return (err);
+}
+
+static int smctr_link_tx_fcbs_to_bdbs(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int i, j;
+ FCBlock *fcb;
+ BDBlock *bdb;
+
+ for(i = 0; i < NUM_TX_QS_USED; i++)
+ {
+ fcb = tp->tx_fcb_head[i];
+ bdb = tp->tx_bdb_head[i];
+
+ for(j = 0; j < tp->num_tx_fcbs[i]; j++)
+ {
+ fcb->bdb_ptr = bdb;
+ fcb->trc_bdb_ptr = TRC_POINTER(bdb);
+ fcb = (FCBlock *)((char *)fcb + sizeof(FCBlock));
+ bdb = (BDBlock *)((char *)bdb + sizeof(BDBlock));
+ }
+ }
+
+ return (0);
+}
+
+static int smctr_load_firmware(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ __u16 i, checksum = 0;
+ int err = 0;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_load_firmware\n", dev->name);
+
+ tp->ptr_ucode = smctr_code;
+ tp->num_of_tx_buffs = 4;
+ tp->mode_bits |= UMAC;
+ tp->receive_mask = 0;
+ tp->max_packet_size = 4177;
+
+ /* Can only upload the firmware once per adapter reset. */
+ if(tp->microcode_version != 0)
+ return (UCODE_PRESENT);
+
+ /* Verify the firmware exists and is there in the right amount. */
+ if((tp->ptr_ucode == 0L)
+ || (*(tp->ptr_ucode + UCODE_VERSION_OFFSET) < UCODE_VERSION))
+ {
+ return (UCODE_NOT_PRESENT);
+ }
+
+ /* UCODE_SIZE is not included in Checksum. */
+ for(i = 0; i < *((__u16 *)(tp->ptr_ucode + UCODE_SIZE_OFFSET)); i += 2)
+ checksum += *((__u16 *)(tp->ptr_ucode + 2 + i));
+ if(checksum)
+ return (UCODE_NOT_PRESENT);
+
+ /* At this point we have a valid firmware image, lets kick it on up. */
+ smctr_enable_adapter_ram(dev);
+ smctr_enable_16bit(dev);
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+ if((smctr_checksum_firmware(dev))
+ || (*(tp->ptr_ucode + UCODE_VERSION_OFFSET)
+ > tp->microcode_version))
+ {
+ smctr_enable_adapter_ctrl_store(dev);
+
+ /* Zero out ram space for firmware. */
+ for(i = 0; i < CS_RAM_SIZE; i += 2)
+ *((__u16 *)(tp->ram_access + i)) = 0;
+
+ smctr_decode_firmware(dev);
+
+ tp->microcode_version = *(tp->ptr_ucode + UCODE_VERSION_OFFSET); *((__u16 *)(tp->ram_access + CS_RAM_VERSION_OFFSET))
+ = (tp->microcode_version << 8);
+ *((__u16 *)(tp->ram_access + CS_RAM_CHECKSUM_OFFSET))
+ = ~(tp->microcode_version << 8) + 1;
+
+ smctr_disable_adapter_ctrl_store(dev);
+
+ if(smctr_checksum_firmware(dev))
+ err = HARDWARE_FAILED;
+ }
+ else
+ err = UCODE_PRESENT;
+
+ smctr_disable_16bit(dev);
+
+ return (err);
+}
+
+static int smctr_load_node_addr(struct net_device *dev)
+{
+ int ioaddr = dev->base_addr;
+ unsigned int i;
+ __u8 r;
+
+ /* Check if node address has been specified by user. (non-0) */
+ for(i = 0; ((i < 6) && (dev->dev_addr[i] == 0)); i++);
+ {
+ if(i != 6)
+ {
+ for(i = 0; i < 6; i++)
+ {
+ r = inb(ioaddr + LAR0 + i);
+ dev->dev_addr[i] = (char)r;
+ }
+ dev->addr_len = 6;
+ }
+ else /* Node addr. not given by user, read it from board. */
+ {
+ for(i = 0; i < 6; i++)
+ {
+ r = inb(ioaddr + LAR0 + i);
+ dev->dev_addr[i] = (char)r;
+ }
+ dev->addr_len = 6;
+ }
+ }
+
+ return (0);
+}
+
+/* Lobe Media Test.
+ * During the transmission of the initial 1500 lobe media MAC frames,
+ * the phase lock loop in the 805 chip may lock, and then un-lock, causing
+ * the 825 to go into a PURGE state. When performing a PURGE, the MCT
+ * microcode will not transmit any frames given to it by the host, and
+ * will consequently cause a timeout.
+ *
+ * NOTE 1: If the monitor_state is MS_BEACON_TEST_STATE, all transmit
+ * queues other then the one used for the lobe_media_test should be
+ * disabled.!?
+ *
+ * NOTE 2: If the monitor_state is MS_BEACON_TEST_STATE and the receive_mask
+ * has any multi-cast or promiscous bits set, the receive_mask needs to
+ * be changed to clear the multi-cast or promiscous mode bits, the lobe_test
+ * run, and then the receive mask set back to its original value if the test
+ * is successful.
+ */
+static int smctr_lobe_media_test(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int i, perror = 0;
+ unsigned short saved_rcv_mask;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_lobe_media_test\n", dev->name);
+
+ /* Clear receive mask for lobe test. */
+ saved_rcv_mask = tp->receive_mask;
+ tp->receive_mask = 0;
+
+ smctr_chg_rx_mask(dev);
+
+ /* Setup the lobe media test. */
+ smctr_lobe_media_test_cmd(dev);
+ if(smctr_wait_cmd(dev))
+ {
+ smctr_reset_adapter(dev);
+ tp->status = CLOSED;
+ return (LOBE_MEDIA_TEST_FAILED);
+ }
+
+ /* Tx lobe media test frames. */
+ for(i = 0; i < 1500; ++i)
+ {
+ if(smctr_send_lobe_media_test(dev))
+ {
+ if(perror)
+ {
+ smctr_reset_adapter(dev);
+ tp->state = CLOSED;
+ return (LOBE_MEDIA_TEST_FAILED);
+ }
+ else
+ {
+ perror = 1;
+ if(smctr_lobe_media_test_cmd(dev))
+ {
+ smctr_reset_adapter(dev);
+ tp->state = CLOSED;
+ return (LOBE_MEDIA_TEST_FAILED);
+ }
+ }
+ }
+ }
+
+ if(smctr_send_dat(dev))
+ {
+ if(smctr_send_dat(dev))
+ {
+ smctr_reset_adapter(dev);
+ tp->state = CLOSED;
+ return (LOBE_MEDIA_TEST_FAILED);
+ }
+ }
+
+ /* Check if any frames received during test. */
+ if((tp->rx_fcb_curr[MAC_QUEUE]->frame_status)
+ || (tp->rx_fcb_curr[NON_MAC_QUEUE]->frame_status))
+ {
+ smctr_reset_adapter(dev);
+ tp->state = CLOSED;
+ return (LOBE_MEDIA_TEST_FAILED);
+ }
+
+ /* Set receive mask to "Promisc" mode. */
+ tp->receive_mask = saved_rcv_mask;
+
+ smctr_chg_rx_mask(dev);
+
+ return (0);
+}
+
+static int smctr_lobe_media_test_cmd(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int err;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_lobe_media_test_cmd\n", dev->name);
+
+ /* Change to lobe media test state. */
+ if(tp->monitor_state != MS_BEACON_TEST_STATE)
+ {
+ smctr_lobe_media_test_state(dev);
+ if(smctr_wait_cmd(dev))
+ {
+ printk("Lobe Failed test state\n");
+ return (LOBE_MEDIA_TEST_FAILED);
+ }
+ }
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
+ TRC_LOBE_MEDIA_TEST);
+
+ return (err);
+}
+
+static int smctr_lobe_media_test_state(struct net_device *dev)
+{
+ int err;
+
+ err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE,
+ JS_LOBE_TEST_STATE);
+
+ return (err);
+}
+
+static int smctr_make_8025_hdr(struct net_device *dev,
+ MAC_HEADER *rmf, MAC_HEADER *tmf, __u16 ac_fc)
+{
+ tmf->ac = MSB(ac_fc); /* msb is access control */
+ tmf->fc = LSB(ac_fc); /* lsb is frame control */
+
+ tmf->sa[0] = dev->dev_addr[0];
+ tmf->sa[1] = dev->dev_addr[1];
+ tmf->sa[2] = dev->dev_addr[2];
+ tmf->sa[3] = dev->dev_addr[3];
+ tmf->sa[4] = dev->dev_addr[4];
+ tmf->sa[5] = dev->dev_addr[5];
+
+ switch(tmf->vc)
+ {
+ /* Send RQ_INIT to RPS */
+ case RQ_INIT:
+ tmf->da[0] = 0xc0;
+ tmf->da[1] = 0x00;
+ tmf->da[2] = 0x00;
+ tmf->da[3] = 0x00;
+ tmf->da[4] = 0x00;
+ tmf->da[5] = 0x02;
+ break;
+
+ /* Send RPT_TX_FORWARD to CRS */
+ case RPT_TX_FORWARD:
+ tmf->da[0] = 0xc0;
+ tmf->da[1] = 0x00;
+ tmf->da[2] = 0x00;
+ tmf->da[3] = 0x00;
+ tmf->da[4] = 0x00;
+ tmf->da[5] = 0x10;
+ break;
+
+ /* Everything else goes to sender */
+ default:
+ tmf->da[0] = rmf->sa[0];
+ tmf->da[1] = rmf->sa[1];
+ tmf->da[2] = rmf->sa[2];
+ tmf->da[3] = rmf->sa[3];
+ tmf->da[4] = rmf->sa[4];
+ tmf->da[5] = rmf->sa[5];
+ break;
+ }
+
+ return (0);
+}
+
+static int smctr_make_access_pri(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ tsv->svi = AUTHORIZED_ACCESS_PRIORITY;
+ tsv->svl = S_AUTHORIZED_ACCESS_PRIORITY;
+
+ tsv->svv[0] = MSB(tp->authorized_access_priority);
+ tsv->svv[1] = LSB(tp->authorized_access_priority);
+
+ return (0);
+}
+
+static int smctr_make_addr_mod(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+ tsv->svi = ADDRESS_MODIFER;
+ tsv->svl = S_ADDRESS_MODIFER;
+
+ tsv->svv[0] = 0;
+ tsv->svv[1] = 0;
+
+ return (0);
+}
+
+static int smctr_make_auth_funct_class(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ tsv->svi = AUTHORIZED_FUNCTION_CLASS;
+ tsv->svl = S_AUTHORIZED_FUNCTION_CLASS;
+
+ tsv->svv[0] = MSB(tp->authorized_function_classes);
+ tsv->svv[1] = LSB(tp->authorized_function_classes);
+
+ return (0);
+}
+
+static int smctr_make_corr(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv, __u16 correlator)
+{
+ tsv->svi = CORRELATOR;
+ tsv->svl = S_CORRELATOR;
+
+ tsv->svv[0] = MSB(correlator);
+ tsv->svv[1] = LSB(correlator);
+
+ return (0);
+}
+
+static int smctr_make_funct_addr(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ smctr_get_functional_address(dev);
+
+ tsv->svi = FUNCTIONAL_ADDRESS;
+ tsv->svl = S_FUNCTIONAL_ADDRESS;
+
+ tsv->svv[0] = MSB(tp->misc_command_data[0]);
+ tsv->svv[1] = LSB(tp->misc_command_data[0]);
+
+ tsv->svv[2] = MSB(tp->misc_command_data[1]);
+ tsv->svv[3] = LSB(tp->misc_command_data[1]);
+
+ return (0);
+}
+
+static int smctr_make_group_addr(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ smctr_get_group_address(dev);
+
+ tsv->svi = GROUP_ADDRESS;
+ tsv->svl = S_GROUP_ADDRESS;
+
+ tsv->svv[0] = MSB(tp->misc_command_data[0]);
+ tsv->svv[1] = LSB(tp->misc_command_data[0]);
+
+ tsv->svv[2] = MSB(tp->misc_command_data[1]);
+ tsv->svv[3] = LSB(tp->misc_command_data[1]);
+
+ /* Set Group Address Sub-vector to all zeros if only the
+ * Group Address/Functional Address Indicator is set.
+ */
+ if(tsv->svv[0] == 0x80 && tsv->svv[1] == 0x00
+ && tsv->svv[2] == 0x00 && tsv->svv[3] == 0x00)
+ tsv->svv[0] = 0x00;
+
+ return (0);
+}
+
+static int smctr_make_phy_drop_num(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ smctr_get_physical_drop_number(dev);
+
+ tsv->svi = PHYSICAL_DROP;
+ tsv->svl = S_PHYSICAL_DROP;
+
+ tsv->svv[0] = MSB(tp->misc_command_data[0]);
+ tsv->svv[1] = LSB(tp->misc_command_data[0]);
+
+ tsv->svv[2] = MSB(tp->misc_command_data[1]);
+ tsv->svv[3] = LSB(tp->misc_command_data[1]);
+
+ return (0);
+}
+
+static int smctr_make_product_id(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+ int i;
+
+ tsv->svi = PRODUCT_INSTANCE_ID;
+ tsv->svl = S_PRODUCT_INSTANCE_ID;
+
+ for(i = 0; i < 18; i++)
+ tsv->svv[i] = 0xF0;
+
+ return (0);
+}
+
+static int smctr_make_station_id(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ smctr_get_station_id(dev);
+
+ tsv->svi = STATION_IDENTIFER;
+ tsv->svl = S_STATION_IDENTIFER;
+
+ tsv->svv[0] = MSB(tp->misc_command_data[0]);
+ tsv->svv[1] = LSB(tp->misc_command_data[0]);
+
+ tsv->svv[2] = MSB(tp->misc_command_data[1]);
+ tsv->svv[3] = LSB(tp->misc_command_data[1]);
+
+ tsv->svv[4] = MSB(tp->misc_command_data[2]);
+ tsv->svv[5] = LSB(tp->misc_command_data[2]);
+
+ return (0);
+}
+
+static int smctr_make_ring_station_status(struct net_device *dev,
+ MAC_SUB_VECTOR * tsv)
+{
+ tsv->svi = RING_STATION_STATUS;
+ tsv->svl = S_RING_STATION_STATUS;
+
+ tsv->svv[0] = 0;
+ tsv->svv[1] = 0;
+ tsv->svv[2] = 0;
+ tsv->svv[3] = 0;
+ tsv->svv[4] = 0;
+ tsv->svv[5] = 0;
+
+ return (0);
+}
+
+static int smctr_make_ring_station_version(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ tsv->svi = RING_STATION_VERSION_NUMBER;
+ tsv->svl = S_RING_STATION_VERSION_NUMBER;
+
+ tsv->svv[0] = 0xe2; /* EBCDIC - S */
+ tsv->svv[1] = 0xd4; /* EBCDIC - M */
+ tsv->svv[2] = 0xc3; /* EBCDIC - C */
+ tsv->svv[3] = 0x40; /* EBCDIC - */
+ tsv->svv[4] = 0xe5; /* EBCDIC - V */
+ tsv->svv[5] = 0xF0 + (tp->microcode_version >> 4);
+ tsv->svv[6] = 0xF0 + (tp->microcode_version & 0x0f);
+ tsv->svv[7] = 0x40; /* EBCDIC - */
+ tsv->svv[8] = 0xe7; /* EBCDIC - X */
+
+ if(tp->extra_info & CHIP_REV_MASK)
+ tsv->svv[9] = 0xc5; /* EBCDIC - E */
+ else
+ tsv->svv[9] = 0xc4; /* EBCDIC - D */
+
+ return (0);
+}
+
+static int smctr_make_tx_status_code(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv, __u16 tx_fstatus)
+{
+ tsv->svi = TRANSMIT_STATUS_CODE;
+ tsv->svl = S_TRANSMIT_STATUS_CODE;
+
+ tsv->svv[0] = ((tx_fstatus & 0x0100 >> 6) || IBM_PASS_SOURCE_ADDR);
+
+ /* Stripped frame status of Transmitted Frame */
+ tsv->svv[1] = tx_fstatus & 0xff;
+
+ return (0);
+}
+
+static int smctr_make_upstream_neighbor_addr(struct net_device *dev,
+ MAC_SUB_VECTOR *tsv)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ smctr_get_upstream_neighbor_addr(dev);
+
+ tsv->svi = UPSTREAM_NEIGHBOR_ADDRESS;
+ tsv->svl = S_UPSTREAM_NEIGHBOR_ADDRESS;
+
+ tsv->svv[0] = MSB(tp->misc_command_data[0]);
+ tsv->svv[1] = LSB(tp->misc_command_data[0]);
+
+ tsv->svv[2] = MSB(tp->misc_command_data[1]);
+ tsv->svv[3] = LSB(tp->misc_command_data[1]);
+
+ tsv->svv[4] = MSB(tp->misc_command_data[2]);
+ tsv->svv[5] = LSB(tp->misc_command_data[2]);
+
+ return (0);
+}
+
+static int smctr_make_wrap_data(struct net_device *dev, MAC_SUB_VECTOR *tsv)
+{
+ tsv->svi = WRAP_DATA;
+ tsv->svl = S_WRAP_DATA;
+
+ return (0);
+}
+
+/*
+ * Open/initialize the board. This is called 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 smctr_open(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int err;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_open\n", dev->name);
+
+ tp->status = NOT_INITIALIZED;
+
+ err = smctr_load_firmware(dev);
+ if(err < 0)
+ return (err);
+
+ err = smctr_init_adapter(dev);
+ if(err < 0)
+ return (err);
+
+#ifdef MODULE
+ MOD_INC_USE_COUNT;
+#endif
+
+ return (err);
+}
+
+/* Interrupt driven open of Token card. */
+static int smctr_open_tr(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned long flags;
+ int err;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_open_tr\n", dev->name);
+
+ /* Now we can actually open the adapter. */
+ if(tp->status == OPEN)
+ return (0);
+ if(tp->status != INITIALIZED)
+ return (-1);
+
+ save_flags(flags);
+ cli();
+
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+ if((err = smctr_issue_resume_rx_fcb_cmd(dev, (short)MAC_QUEUE)))
+ return (err);
+
+ if((err = smctr_issue_resume_rx_bdb_cmd(dev, (short)MAC_QUEUE)))
+ return (err);
+
+ if((err = smctr_issue_resume_rx_fcb_cmd(dev, (short)NON_MAC_QUEUE)))
+ return (err);
+
+ if((err = smctr_issue_resume_rx_bdb_cmd(dev, (short)NON_MAC_QUEUE)))
+ return (err);
+
+ tp->status = CLOSED;
+
+ /* Insert into the Ring or Enter Loopback Mode. */
+ if((tp->mode_bits & LOOPING_MODE_MASK) == LOOPBACK_MODE_1)
+ {
+ tp->status = CLOSED;
+
+ if(!(err = smctr_issue_trc_loopback_cmd(dev)))
+ {
+ if(!(err = smctr_wait_cmd(dev)))
+ tp->status = OPEN;
+ }
+
+ smctr_status_chg(dev);
+ }
+ else
+ {
+ if((tp->mode_bits & LOOPING_MODE_MASK) == LOOPBACK_MODE_2)
+ {
+ tp->status = CLOSED;
+ if(!(err = smctr_issue_tri_loopback_cmd(dev)))
+ {
+ if(!(err = smctr_wait_cmd(dev)))
+ tp->status = OPEN;
+ }
+
+ smctr_status_chg(dev);
+ }
+ else
+ {
+ if((tp->mode_bits & LOOPING_MODE_MASK)
+ == LOOPBACK_MODE_3)
+ {
+ tp->status = CLOSED;
+ if(!(err = smctr_lobe_media_test_cmd(dev)))
+ {
+ if(!(err = smctr_wait_cmd(dev)))
+ tp->status = OPEN;
+ }
+ smctr_status_chg(dev);
+ }
+ else
+ {
+ if(!(err = smctr_lobe_media_test(dev)))
+ err = smctr_issue_insert_cmd(dev);
+ }
+ }
+ }
+
+ restore_flags(flags);
+
+ return (err);
+}
+
+/* Check for a network adapter of this type, and return '0 if one exists.
+ * If dev->base_addr == 0, probe all likely locations.
+ * If dev->base_addr == 1, always return failure.
+ */
+int __init smctr_probe (struct net_device *dev)
+{
+ int i;
+ int base_addr = dev ? dev->base_addr : 0;
+
+ if(base_addr > 0x1ff) /* Check a single specified location. */
+ return (smctr_probe1(dev, base_addr));
+ else if(base_addr != 0) /* Don't probe at all. */
+ return (-ENXIO);
+
+ for(i = 0; smctr_portlist[i]; i++)
+ {
+ int ioaddr = smctr_portlist[i];
+ if(check_region(ioaddr, SMCTR_IO_EXTENT))
+ continue;
+ if(smctr_probe1(dev, ioaddr))
+ {
+#ifndef MODULE
+ tr_freedev(dev);
+#endif
+ }
+ else
+ return (0);
+ }
+
+ return (-ENODEV);
+}
+
+static int __init smctr_probe1(struct net_device *dev, int ioaddr)
+{
+ static unsigned version_printed = 0;
+ struct net_local *tp;
+ int err;
+ __u32 *ram;
+
+ if(smctr_debug && version_printed++ == 0)
+ printk("%s", version);
+
+#ifndef MODULE
+ dev = init_trdev(dev, 0);
+ if(dev == NULL)
+ return (-ENOMEM);
+#endif
+
+ /* See if we have a SMCTR card floating around. */
+ if((ioaddr & 0x1F) != 0)
+ return (-ENODEV); /* No Adapter */
+
+ /* Setup this devices private information structure */
+ tp = (struct net_local *)kmalloc(sizeof(struct net_local),
+ GFP_KERNEL);
+ if(tp == NULL)
+ return (-ENOMEM);
+ memset(tp, 0, sizeof(struct net_local));
+ dev->priv = tp;
+ dev->base_addr = ioaddr;
+
+ err = smctr_find_adapter(dev);
+ if(err < 0)
+ {
+ kfree_s(tp, sizeof(struct net_local));
+ return (-ENODEV);
+ }
+
+ tp = (struct net_local *)dev->priv;
+ dev->rmem_start = dev->mem_start = tp->ram_base;
+ dev->rmem_end = dev->mem_end = dev->mem_start + 0x10000;
+ ram = (__u32 *)phys_to_virt(dev->mem_start);
+ tp->ram_access = *(__u32 *)&ram;
+
+ /* Allow user to specify ring speed on module insert. */
+ if(ringspeed == 4)
+ tp->media_type = MEDIA_UTP_4;
+ else
+ tp->media_type = MEDIA_UTP_16;
+
+ printk("%s: %s %s at Io %#4x, Irq %d, Rom %#4x, Ram %#4x.\n",
+ dev->name, smctr_name, smctr_model,
+ (unsigned int)dev->base_addr,
+ dev->irq, tp->rom_base, tp->ram_base);
+
+ dev->init = smctr_init_card;
+ dev->open = smctr_open;
+ dev->stop = smctr_close;
+ dev->hard_start_xmit = smctr_send_packet;
+ dev->get_stats = smctr_get_stats;
+ dev->set_multicast_list = &smctr_set_multicast_list;
+
+ return (0);
+}
+
+static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
+ struct net_device *dev, __u16 rx_status)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ struct sk_buff *skb;
+ __u16 rcode, correlator;
+ int err = 0;
+ __u8 xframe = 1;
+ __u16 tx_fstatus;
+
+ rmf->vl = SWAP_BYTES(rmf->vl);
+ if(rx_status & FCB_RX_STATUS_DA_MATCHED)
+ {
+ switch(rmf->vc)
+ {
+ /* Received MAC Frames Processed by RS. */
+ case INIT:
+ if((rcode = smctr_rcv_init(dev, rmf,
+ &correlator)) == HARDWARE_FAILED)
+ {
+ return (rcode);
+ }
+
+ if((err = smctr_send_rsp(dev, rmf, rcode,
+ correlator)))
+ {
+ return (err);
+ }
+ break;
+
+ case CHG_PARM:
+ if((rcode = smctr_rcv_chg_param(dev, rmf,
+ &correlator)) ==HARDWARE_FAILED)
+ {
+ return (rcode);
+ }
+
+ if((err = smctr_send_rsp(dev, rmf, rcode,
+ correlator)))
+ {
+ return (err);
+ }
+ break;
+
+ case RQ_ADDR:
+ if((rcode = smctr_rcv_rq_addr_state_attch(dev,
+ rmf, &correlator)) != POSITIVE_ACK)
+ {
+ if(rcode == HARDWARE_FAILED)
+ return (rcode);
+ else
+ return (smctr_send_rsp(dev, rmf,
+ rcode, correlator));
+ }
+
+ if((err = smctr_send_rpt_addr(dev, rmf,
+ correlator)))
+ {
+ return (err);
+ }
+ break;
+
+ case RQ_ATTCH:
+ if((rcode = smctr_rcv_rq_addr_state_attch(dev,
+ rmf, &correlator)) != POSITIVE_ACK)
+ {
+ if(rcode == HARDWARE_FAILED)
+ return (rcode);
+ else
+ return (smctr_send_rsp(dev, rmf,
+ rcode,
+ correlator));
+ }
+
+ if((err = smctr_send_rpt_attch(dev, rmf,
+ correlator)))
+ {
+ return (err);
+ }
+ break;
+
+ case RQ_STATE:
+ if((rcode = smctr_rcv_rq_addr_state_attch(dev,
+ rmf, &correlator)) != POSITIVE_ACK)
+ {
+ if(rcode == HARDWARE_FAILED)
+ return (rcode);
+ else
+ return (smctr_send_rsp(dev, rmf,
+ rcode,
+ correlator));
+ }
+
+ if((err = smctr_send_rpt_state(dev, rmf,
+ correlator)))
+ {
+ return (err);
+ }
+ break;
+
+ case TX_FORWARD:
+ if((rcode = smctr_rcv_tx_forward(dev, rmf))
+ != POSITIVE_ACK)
+ {
+ if(rcode == HARDWARE_FAILED)
+ return (rcode);
+ else
+ return (smctr_send_rsp(dev, rmf,
+ rcode,
+ correlator));
+ }
+
+ if((err = smctr_send_tx_forward(dev, rmf,
+ &tx_fstatus)) == HARDWARE_FAILED)
+ {
+ return (err);
+ }
+
+ if(err == A_FRAME_WAS_FORWARDED)
+ {
+ if((err = smctr_send_rpt_tx_forward(dev,
+ rmf, tx_fstatus))
+ == HARDWARE_FAILED)
+ {
+ return (err);
+ }
+ }
+ break;
+
+ /* Received MAC Frames Processed by CRS/REM/RPS. */
+ case RSP:
+ case RQ_INIT:
+ case RPT_NEW_MON:
+ case RPT_SUA_CHG:
+ case RPT_ACTIVE_ERR:
+ case RPT_NN_INCMP:
+ case RPT_ERROR:
+ case RPT_ATTCH:
+ case RPT_STATE:
+ case RPT_ADDR:
+ break;
+
+ /* Rcvd Att. MAC Frame (if RXATMAC set) or UNKNOWN */
+ default:
+ xframe = 0;
+ if(!(tp->receive_mask & ACCEPT_ATT_MAC_FRAMES))
+ {
+ rcode = smctr_rcv_unknown(dev, rmf,
+ &correlator);
+ if((err = smctr_send_rsp(dev, rmf,rcode,
+ correlator)))
+ {
+ return (err);
+ }
+ }
+
+ break;
+ }
+ }
+ else
+ {
+ /* 1. DA doesn't match (Promiscuous Mode).
+ * 2. Parse for Extended MAC Frame Type.
+ */
+ switch(rmf->vc)
+ {
+ case RSP:
+ case INIT:
+ case RQ_INIT:
+ case RQ_ADDR:
+ case RQ_ATTCH:
+ case RQ_STATE:
+ case CHG_PARM:
+ case RPT_ADDR:
+ case RPT_ERROR:
+ case RPT_ATTCH:
+ case RPT_STATE:
+ case RPT_NEW_MON:
+ case RPT_SUA_CHG:
+ case RPT_NN_INCMP:
+ case RPT_ACTIVE_ERR:
+ break;
+
+ default:
+ xframe = 0;
+ break;
+ }
+ }
+
+ /* NOTE: UNKNOWN MAC frames will NOT be passed up unless
+ * ACCEPT_ATT_MAC_FRAMES is set.
+ */
+ if(((tp->receive_mask & ACCEPT_ATT_MAC_FRAMES)
+ && (xframe == (__u8)0))
+ || ((tp->receive_mask & ACCEPT_EXT_MAC_FRAMES)
+ && (xframe == (__u8)1)))
+ {
+ rmf->vl = SWAP_BYTES(rmf->vl);
+
+ skb = dev_alloc_skb(size);
+ skb->len = size;
+
+ /* Slide data into a sleek skb. */
+ skb_put(skb, skb->len);
+ memcpy(skb->data, rmf, skb->len);
+
+ /* Update Counters */
+ tp->MacStat.rx_packets++;
+ tp->MacStat.rx_bytes += skb->len;
+
+ /* Kick the packet on up. */
+ skb->dev = dev;
+ skb->protocol = tr_type_trans(skb, dev);
+ netif_rx(skb);
+ err = 0;
+ }
+
+ return (err);
+}
+
+/* Test for RAM in adapter RAM space. */
+static int smctr_ram_conflict_test(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int i;
+ __u16 sword;
+
+ for(i = 0; i < (unsigned int)(tp->ram_usable * 1024); i += 1024)
+ {
+ sword = *(__u16 *)(tp->ram_access + i);
+ *(__u16 *)(tp->ram_access + i) = 0x1234;
+ if(*(__u16 *)(tp->ram_access + i) == 0x1234)
+ {
+ *(__u16 *)(tp->ram_access + i) = sword;
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
+/* Adapter RAM test. Incremental word ODD boundry data test. */
+static int smctr_ram_memory_test(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ __u16 page, pages_of_ram, start_pattern = 0, word_pattern = 0,
+ word_read = 0, err_word = 0, err_pattern = 0;
+ unsigned int err_offset;
+ __u32 j, pword;
+ __u8 err = 0;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_ram_memory_test\n", dev->name);
+
+ start_pattern = 0x0001;
+ pages_of_ram = tp->ram_size / tp->ram_usable;
+ pword = tp->ram_access;
+
+ /* Incremental word ODD boundry test. */
+ for(page = 0; (page < pages_of_ram) && (~err);
+ page++, start_pattern += 0x8000)
+ {
+ smctr_set_page(dev, (__u8 *)(tp->ram_access
+ + (page * tp->ram_usable * 1024) + 1));
+ word_pattern = start_pattern;
+
+ for(j = 1; j < (__u32)(tp->ram_usable * 1024) - 1; j += 2)
+ *(__u16 *)(pword + j) = word_pattern++;
+
+ word_pattern = start_pattern;
+
+ for(j = 1; j < (__u32)(tp->ram_usable * 1024) - 1
+ && (~err); j += 2, word_pattern++)
+ {
+ word_read = *(__u16 *)(pword + j);
+ if(word_read != word_pattern)
+ {
+ err = (__u8)1;
+ err_offset = j;
+ err_word = word_read;
+ err_pattern = word_pattern;
+ return (-1);
+ }
+ }
+ }
+
+ /* Zero out memory. */
+ for(page = 0; page < pages_of_ram && (~err); page++)
+ {
+ smctr_set_page(dev, (__u8 *)(tp->ram_access
+ + (page * tp->ram_usable * 1024)));
+ word_pattern = 0;
+
+ for(j = 0; j < (__u32)tp->ram_usable * 1024; j +=2)
+ *(__u16 *)(pword + j) = word_pattern;
+
+ for(j =0; j < (__u32)tp->ram_usable * 1024
+ && (~err); j += 2)
+ {
+ word_read = *(__u16 *)(pword + j);
+ if(word_read != word_pattern)
+ {
+ err = (__u8)1;
+ err_offset = j;
+ err_word = word_read;
+ err_pattern = word_pattern;
+ return (-1);
+ }
+ }
+ }
+
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+
+ return (0);
+}
+
+static unsigned int __init smctr_read_584_chksum(int ioaddr)
+{
+ __u8 pg_no, r1, r2;
+ __u16 byte_no, csum_val = 0;
+
+ for(pg_no = 0; pg_no < 16; pg_no++)
+ {
+ r1 = inb(ioaddr + 0x01);
+ r1 &= 0x04;
+ r1 |= 0x02;
+
+ outb(r1, ioaddr + 0x01);
+
+ r1 = inb(ioaddr + 0x03);
+ r1 &= 0x0f;
+ r1 |= (pg_no << 4);
+
+ outb(r1, ioaddr + 0x03);
+
+ r1 = inb(ioaddr + 0x01);
+ r1 &= 0x04;
+ r1 |= 0x12;
+
+ outb(r1, ioaddr + 0x01);
+
+ do {
+ r1 = inb(ioaddr + 0x01);
+ } while(r1 & 0x10);
+
+ r2 = 0;
+ for(byte_no = 0x08; byte_no < 0x10; byte_no++)
+ {
+ r1 = inb(ioaddr + byte_no);
+ r2 += r1;
+ }
+
+ csum_val += r2;
+ }
+
+ r1 = inb(ioaddr + 0x01);
+ r1 &= 0x04;
+ r1 |= 0x10;
+ outb(r1, ioaddr + 0x01);
+
+ csum_val &= 0xff;
+ if(csum_val == 0xff)
+ return (0);
+ else
+ return (-1);
+}
+
+static int smctr_rcv_chg_param(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 *correlator)
+{
+ MAC_SUB_VECTOR *rsv;
+ signed short vlen;
+ __u16 rcode = POSITIVE_ACK;
+ unsigned int svectors = F_NO_SUB_VECTORS_FOUND;
+
+ /* This Frame can only come from a CRS */
+ if((rmf->dc_sc & SC_MASK) != SC_CRS)
+ return(E_INAPPROPRIATE_SOURCE_CLASS);
+
+ /* Remove MVID Length from total length. */
+ vlen = (signed short)rmf->vl - 4;
+
+ /* Point to First SVID */
+ rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
+
+ /* Search for Appropriate SVID's. */
+ while((vlen > 0) && (rcode == POSITIVE_ACK))
+ {
+ switch(rsv->svi)
+ {
+ case CORRELATOR:
+ svectors |= F_CORRELATOR;
+ rcode = smctr_set_corr(dev, rsv, correlator);
+ break;
+
+ case LOCAL_RING_NUMBER:
+ svectors |= F_LOCAL_RING_NUMBER;
+ rcode = smctr_set_local_ring_num(dev, rsv);
+ break;
+
+ case ASSIGN_PHYSICAL_DROP:
+ svectors |= F_ASSIGN_PHYSICAL_DROP;
+ rcode = smctr_set_phy_drop(dev, rsv);
+ break;
+
+ case ERROR_TIMER_VALUE:
+ svectors |= F_ERROR_TIMER_VALUE;
+ rcode = smctr_set_error_timer_value(dev, rsv);
+ break;
+
+ case AUTHORIZED_FUNCTION_CLASS:
+ svectors |= F_AUTHORIZED_FUNCTION_CLASS;
+ rcode = smctr_set_auth_funct_class(dev, rsv);
+ break;
+
+ case AUTHORIZED_ACCESS_PRIORITY:
+ svectors |= F_AUTHORIZED_ACCESS_PRIORITY;
+ rcode = smctr_set_auth_access_pri(dev, rsv);
+ break;
+
+ default:
+ rcode = E_SUB_VECTOR_UNKNOWN;
+ break;
+ }
+
+ /* Let Sender Know if SUM of SV length's is
+ * larger then length in MVID length field
+ */
+ if((vlen -= rsv->svl) < 0)
+ rcode = E_VECTOR_LENGTH_ERROR;
+
+ rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
+ }
+
+ if(rcode == POSITIVE_ACK)
+ {
+ /* Let Sender Know if MVID length field
+ * is larger then SUM of SV length's
+ */
+ if(vlen != 0)
+ rcode = E_VECTOR_LENGTH_ERROR;
+ else
+ {
+ /* Let Sender Know if Expected SVID Missing */
+ if((svectors & R_CHG_PARM) ^ R_CHG_PARM)
+ rcode = E_MISSING_SUB_VECTOR;
+ }
+ }
+
+ return (rcode);
+}
+
+static int smctr_rcv_init(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 *correlator)
+{
+ MAC_SUB_VECTOR *rsv;
+ signed short vlen;
+ __u16 rcode = POSITIVE_ACK;
+ unsigned int svectors = F_NO_SUB_VECTORS_FOUND;
+
+ /* This Frame can only come from a RPS */
+ if((rmf->dc_sc & SC_MASK) != SC_RPS)
+ return (E_INAPPROPRIATE_SOURCE_CLASS);
+
+ /* Remove MVID Length from total length. */
+ vlen = (signed short)rmf->vl - 4;
+
+ /* Point to First SVID */
+ rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
+
+ /* Search for Appropriate SVID's */
+ while((vlen > 0) && (rcode == POSITIVE_ACK))
+ {
+ switch(rsv->svi)
+ {
+ case CORRELATOR:
+ svectors |= F_CORRELATOR;
+ rcode = smctr_set_corr(dev, rsv, correlator);
+ break;
+
+ case LOCAL_RING_NUMBER:
+ svectors |= F_LOCAL_RING_NUMBER;
+ rcode = smctr_set_local_ring_num(dev, rsv);
+ break;
+
+ case ASSIGN_PHYSICAL_DROP:
+ svectors |= F_ASSIGN_PHYSICAL_DROP;
+ rcode = smctr_set_phy_drop(dev, rsv);
+ break;
+
+ case ERROR_TIMER_VALUE:
+ svectors |= F_ERROR_TIMER_VALUE;
+ rcode = smctr_set_error_timer_value(dev, rsv);
+ break;
+
+ default:
+ rcode = E_SUB_VECTOR_UNKNOWN;
+ break;
+ }
+
+ /* Let Sender Know if SUM of SV length's is
+ * larger then length in MVID length field
+ */
+ if((vlen -= rsv->svl) < 0)
+ rcode = E_VECTOR_LENGTH_ERROR;
+
+ rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
+ }
+
+ if(rcode == POSITIVE_ACK)
+ {
+ /* Let Sender Know if MVID length field
+ * is larger then SUM of SV length's
+ */
+ if(vlen != 0)
+ rcode = E_VECTOR_LENGTH_ERROR;
+ else
+ {
+ /* Let Sender Know if Expected SV Missing */
+ if((svectors & R_INIT) ^ R_INIT)
+ rcode = E_MISSING_SUB_VECTOR;
+ }
+ }
+
+ return (rcode);
+}
+
+static int smctr_rcv_tx_forward(struct net_device *dev, MAC_HEADER *rmf)
+{
+ MAC_SUB_VECTOR *rsv;
+ signed short vlen;
+ __u16 rcode = POSITIVE_ACK;
+ unsigned int svectors = F_NO_SUB_VECTORS_FOUND;
+
+ /* This Frame can only come from a CRS */
+ if((rmf->dc_sc & SC_MASK) != SC_CRS)
+ return (E_INAPPROPRIATE_SOURCE_CLASS);
+
+ /* Remove MVID Length from total length */
+ vlen = (signed short)rmf->vl - 4;
+
+ /* Point to First SVID */
+ rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
+
+ /* Search for Appropriate SVID's */
+ while((vlen > 0) && (rcode == POSITIVE_ACK))
+ {
+ switch(rsv->svi)
+ {
+ case FRAME_FORWARD:
+ svectors |= F_FRAME_FORWARD;
+ rcode = smctr_set_frame_forward(dev, rsv,
+ rmf->dc_sc);
+ break;
+
+ default:
+ rcode = E_SUB_VECTOR_UNKNOWN;
+ break;
+ }
+
+ /* Let Sender Know if SUM of SV length's is
+ * larger then length in MVID length field
+ */
+ if((vlen -= rsv->svl) < 0)
+ rcode = E_VECTOR_LENGTH_ERROR;
+
+ rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
+ }
+
+ if(rcode == POSITIVE_ACK)
+ {
+ /* Let Sender Know if MVID length field
+ * is larger then SUM of SV length's
+ */
+ if(vlen != 0)
+ rcode = E_VECTOR_LENGTH_ERROR;
+ else
+ {
+ /* Let Sender Know if Expected SV Missing */
+ if((svectors & R_TX_FORWARD) ^ R_TX_FORWARD)
+ rcode = E_MISSING_SUB_VECTOR;
+ }
+ }
+
+ return (rcode);
+}
+
+static int smctr_rcv_rq_addr_state_attch(struct net_device *dev,
+ MAC_HEADER *rmf, __u16 *correlator)
+{
+ MAC_SUB_VECTOR *rsv;
+ signed short vlen;
+ __u16 rcode = POSITIVE_ACK;
+ unsigned int svectors = F_NO_SUB_VECTORS_FOUND;
+
+ /* Remove MVID Length from total length */
+ vlen = (signed short)rmf->vl - 4;
+
+ /* Point to First SVID */
+ rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
+
+ /* Search for Appropriate SVID's */
+ while((vlen > 0) && (rcode == POSITIVE_ACK))
+ {
+ switch(rsv->svi)
+ {
+ case CORRELATOR:
+ svectors |= F_CORRELATOR;
+ rcode = smctr_set_corr(dev, rsv, correlator);
+ break;
+
+ default:
+ rcode = E_SUB_VECTOR_UNKNOWN;
+ break;
+ }
+
+ /* Let Sender Know if SUM of SV length's is
+ * larger then length in MVID length field
+ */
+ if((vlen -= rsv->svl) < 0)
+ rcode = E_VECTOR_LENGTH_ERROR;
+
+ rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
+ }
+
+ if(rcode == POSITIVE_ACK)
+ {
+ /* Let Sender Know if MVID length field
+ * is larger then SUM of SV length's
+ */
+ if(vlen != 0)
+ rcode = E_VECTOR_LENGTH_ERROR;
+ else
+ {
+ /* Let Sender Know if Expected SVID Missing */
+ if((svectors & R_RQ_ATTCH_STATE_ADDR)
+ ^ R_RQ_ATTCH_STATE_ADDR)
+ rcode = E_MISSING_SUB_VECTOR;
+ }
+ }
+
+ return (rcode);
+}
+
+static int smctr_rcv_unknown(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 *correlator)
+{
+ MAC_SUB_VECTOR *rsv;
+ signed short vlen;
+
+ *correlator = 0;
+
+ /* Remove MVID Length from total length */
+ vlen = (signed short)rmf->vl - 4;
+
+ /* Point to First SVID */
+ rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
+
+ /* Search for CORRELATOR for RSP to UNKNOWN */
+ while((vlen > 0) && (*correlator == 0))
+ {
+ switch(rsv->svi)
+ {
+ case CORRELATOR:
+ smctr_set_corr(dev, rsv, correlator);
+ break;
+
+ default:
+ break;
+ }
+
+ vlen -= rsv->svl;
+ rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
+ }
+
+ return (E_UNRECOGNIZED_VECTOR_ID);
+}
+
+/*
+ * Reset the 825 NIC and exit w:
+ * 1. The NIC reset cleared (non-reset state), halted and un-initialized.
+ * 2. TINT masked.
+ * 3. CBUSY masked.
+ * 4. TINT clear.
+ * 5. CBUSY clear.
+ */
+static int smctr_reset_adapter(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+
+ /* Reseting the NIC will put it in a halted and un-initialized state. */ smctr_set_trc_reset(ioaddr);
+ udelay(200000); /* ~2 ms */
+
+ smctr_clear_trc_reset(ioaddr);
+ udelay(200000); /* ~2 ms */
+
+ /* Remove any latched interrupts that occured prior to reseting the
+ * adapter or possibily caused by line glitches due to the reset.
+ */
+ outb(tp->trc_mask | CSR_CLRTINT | CSR_CLRCBUSY, ioaddr + CSR);
+
+ return (0);
+}
+
+static int smctr_restart_tx_chain(struct net_device *dev, short queue)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int err = 0;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_restart_tx_chain\n", dev->name);
+
+ if(tp->num_tx_fcbs_used[queue] != 0
+ && tp->tx_queue_status[queue] == NOT_TRANSMITING)
+ {
+ tp->tx_queue_status[queue] = TRANSMITING;
+ err = smctr_issue_resume_tx_fcb_cmd(dev, queue);
+ }
+
+ return (err);
+}
+
+static int smctr_ring_status_chg(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_ring_status_chg\n", dev->name);
+
+ /* Check for ring_status_flag: whenever MONITOR_STATE_BIT
+ * Bit is set, check value of monitor_state, only then we
+ * enable and start transmit/receive timeout (if and only
+ * if it is MS_ACTIVE_MONITOR_STATE or MS_STANDBY_MONITOR_STATE)
+ */
+ if(tp->ring_status_flags == MONITOR_STATE_CHANGED)
+ {
+ if((tp->monitor_state == MS_ACTIVE_MONITOR_STATE)
+ || (tp->monitor_state == MS_STANDBY_MONITOR_STATE))
+ {
+ tp->monitor_state_ready = 1;
+ }
+ else
+ {
+ /* if adapter is NOT in either active monitor
+ * or standby monitor state => Disable
+ * transmit/receive timeout.
+ */
+ tp->monitor_state_ready = 0;
+
+ /* Ring speed problem, switching to auto mode. */
+ if(tp->monitor_state == MS_MONITOR_FSM_INACTIVE
+ && !tp->cleanup)
+ {
+ printk(KERN_INFO "%s: Incorrect ring speed switching.\n",
+ dev->name);
+ smctr_set_ring_speed(dev);
+ }
+ }
+ }
+
+ if(!(tp->ring_status_flags & RING_STATUS_CHANGED))
+ return (0);
+
+ switch(tp->ring_status)
+ {
+ case RING_RECOVERY:
+ printk(KERN_INFO "%s: Ring Recovery\n", dev->name);
+ tp->current_ring_status |= RING_RECOVERY;
+ break;
+
+ case SINGLE_STATION:
+ printk(KERN_INFO "%s: Single Statinon\n", dev->name);
+ tp->current_ring_status |= SINGLE_STATION;
+ break;
+
+ case COUNTER_OVERFLOW:
+ printk(KERN_INFO "%s: Counter Overflow\n", dev->name);
+ tp->current_ring_status |= COUNTER_OVERFLOW;
+ break;
+
+ case REMOVE_RECEIVED:
+ printk(KERN_INFO "%s: Remove Received\n", dev->name);
+ tp->current_ring_status |= REMOVE_RECEIVED;
+ break;
+
+ case AUTO_REMOVAL_ERROR:
+ printk(KERN_INFO "%s: Auto Remove Error\n", dev->name);
+ tp->current_ring_status |= AUTO_REMOVAL_ERROR;
+ break;
+
+ case LOBE_WIRE_FAULT:
+ printk(KERN_INFO "%s: Lobe Wire Fault\n", dev->name);
+ tp->current_ring_status |= LOBE_WIRE_FAULT;
+ break;
+
+ case TRANSMIT_BEACON:
+ printk(KERN_INFO "%s: Transmit Beacon\n", dev->name);
+ tp->current_ring_status |= TRANSMIT_BEACON;
+ break;
+
+ case SOFT_ERROR:
+ printk(KERN_INFO "%s: Soft Error\n", dev->name);
+ tp->current_ring_status |= SOFT_ERROR;
+ break;
+
+ case HARD_ERROR:
+ printk(KERN_INFO "%s: Hard Error\n", dev->name);
+ tp->current_ring_status |= HARD_ERROR;
+ break;
+
+ case SIGNAL_LOSS:
+ printk(KERN_INFO "%s: Singal Loss\n", dev->name);
+ tp->current_ring_status |= SIGNAL_LOSS;
+ break;
+
+ default:
+ printk(KERN_INFO "%s: Unknown ring status change\n",
+ dev->name);
+ break;
+ }
+
+ return (0);
+}
+
+/* Test for ROM signature within adapter RAM space. */
+static int smctr_rom_conflict_test(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int i;
+
+ for(i = 0; i < (unsigned int)tp->ram_usable * 1024; i += 4096)
+ {
+ if(*(__u16 *)(tp->ram_access + i) == 0xaa55)
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int smctr_rx_frame(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ __u16 queue, status, rx_size, err = 0;
+ __u8 *pbuff;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_rx_frame\n", dev->name);
+
+ cli();
+ queue = tp->receive_queue_number;
+
+ while((status = tp->rx_fcb_curr[queue]->frame_status) != SUCCESS)
+ {
+ err = HARDWARE_FAILED;
+
+ if(((status & 0x007f) == 0)
+ || ((tp->receive_mask & ACCEPT_ERR_PACKETS) != 0))
+ {
+ /* frame length less the CRC (4 bytes) + FS (1 byte) */
+ rx_size = tp->rx_fcb_curr[queue]->frame_length - 5;
+
+ pbuff = smctr_get_rx_pointer(dev, queue);
+
+ smctr_set_page(dev, pbuff);
+ smctr_disable_16bit(dev);
+
+ /* pbuff points to addr within one page */
+ pbuff = (__u8 *)PAGE_POINTER(pbuff);
+
+ if(queue == NON_MAC_QUEUE)
+ {
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb(rx_size);
+ skb_put(skb, rx_size);
+
+ memcpy(skb->data, pbuff, rx_size);
+ sti();
+
+ /* Update Counters */
+ tp->MacStat.rx_packets++;
+ tp->MacStat.rx_bytes += skb->len;
+
+ /* Kick the packet on up. */
+ skb->dev = dev;
+ skb->protocol = tr_type_trans(skb, dev);
+ netif_rx(skb);
+ }
+ else
+ smctr_process_rx_packet((MAC_HEADER *)pbuff,
+ rx_size, dev, status);
+ }
+
+ smctr_enable_16bit(dev);
+ smctr_set_page(dev, (__u8 *)tp->ram_access);
+ smctr_update_rx_chain(dev, queue);
+
+ if(err != SUCCESS)
+ break;
+ }
+
+ return (err);
+}
+
+static int smctr_send_dat(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int i, err;
+ MAC_HEADER *tmf;
+ FCBlock *fcb;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_send_dat\n", dev->name);
+
+ if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE,
+ sizeof(MAC_HEADER))) == (FCBlock *)(-1L))
+ {
+ return (OUT_OF_RESOURCES);
+ }
+
+ /* Initialize DAT Data Fields. */
+ tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+ tmf->ac = MSB(AC_FC_DAT);
+ tmf->fc = LSB(AC_FC_DAT);
+
+ for(i = 0; i < 6; i++)
+ {
+ tmf->sa[i] = dev->dev_addr[i];
+ tmf->da[i] = dev->dev_addr[i];
+
+ }
+
+ tmf->vc = DAT;
+ tmf->dc_sc = DC_RS | SC_RS;
+ tmf->vl = 4;
+ tmf->vl = SWAP_BYTES(tmf->vl);
+
+ /* Start Transmit. */
+ if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
+ return (err);
+
+ /* Wait for Transmit to Complete */
+ for(i = 0; i < 10000; i++)
+ {
+ if(fcb->frame_status & FCB_COMMAND_DONE)
+ break;
+ udelay(1000);
+ }
+
+ /* Check if GOOD frame Tx'ed. */
+ if(!(fcb->frame_status & FCB_COMMAND_DONE)
+ || fcb->frame_status & (FCB_TX_STATUS_E | FCB_TX_AC_BITS))
+ {
+ return (INITIALIZE_FAILED);
+ }
+
+ /* De-allocated Tx FCB and Frame Buffer
+ * The FCB must be de-allocated manually if executing with
+ * interrupts disabled, other wise the ISR (LM_Service_Events)
+ * will de-allocate it when the interrupt occurs.
+ */
+ tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
+ smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
+
+ return (0);
+}
+
+/*
+ * Gets skb from system, queues it and checks if it can be sent
+ */
+static int smctr_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_send_packet\n", dev->name);
+
+ if(dev->tbusy)
+ {
+ /*
+ * If we get here, some higher level has decided we are broken.
+ * There should really be a "kick me" function call instead.
+ *
+ * Resetting the token ring adapter takes a long time so just
+ * fake transmission time and go on trying. Our own timeout
+ * routine is in sktr_timer_chk()
+ */
+ dev->tbusy = 0;
+ dev->trans_start = jiffies;
+ return (1);
+ }
+
+ /*
+ * If some higher layer thinks we've missed an tx-done interrupt we
+ * are passed NULL.
+ */
+ if(skb == NULL)
+ return (0);
+
+ /*
+ * Block a timer-based transmit from overlapping. This could better be
+ * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.
+ */
+ if(test_and_set_bit(0, (void*)&dev->tbusy) != 0)
+ {
+ printk("%s: Transmitter access conflict.\n", dev->name);
+ return (1);
+ }
+
+ if(tp->QueueSkb == 0)
+ return (1); /* Return with tbusy set: queue full */
+
+ tp->QueueSkb--;
+ skb_queue_tail(&tp->SendSkbQueue, skb);
+ smctr_hardware_send_packet(dev, tp);
+ if(tp->QueueSkb > 0)
+ dev->tbusy = 0;
+
+ return (0);
+}
+
+static int smctr_send_lobe_media_test(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ MAC_SUB_VECTOR *tsv;
+ MAC_HEADER *tmf;
+ FCBlock *fcb;
+ __u32 i;
+ int err;
+
+ if(smctr_debug > 15)
+ printk("%s: smctr_send_lobe_media_test\n", dev->name);
+
+ if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(struct trh_hdr)
+ + S_WRAP_DATA + S_WRAP_DATA)) == (FCBlock *)(-1L))
+ {
+ return (OUT_OF_RESOURCES);
+ }
+
+ /* Initialize DAT Data Fields. */
+ tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+ tmf->ac = MSB(AC_FC_LOBE_MEDIA_TEST);
+ tmf->fc = LSB(AC_FC_LOBE_MEDIA_TEST);
+
+ for(i = 0; i < 6; i++)
+ {
+ tmf->da[i] = 0;
+ tmf->sa[i] = dev->dev_addr[i];
+ }
+
+ tmf->vc = LOBE_MEDIA_TEST;
+ tmf->dc_sc = DC_RS | SC_RS;
+ tmf->vl = 4;
+
+ tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+ smctr_make_wrap_data(dev, tsv);
+ tmf->vl += tsv->svl;
+
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_wrap_data(dev, tsv);
+ tmf->vl += tsv->svl;
+
+ /* Start Transmit. */
+ tmf->vl = SWAP_BYTES(tmf->vl);
+ if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
+ return (err);
+
+ /* Wait for Transmit to Complete. (10 ms). */
+ for(i=0; i < 10000; i++)
+ {
+ if(fcb->frame_status & FCB_COMMAND_DONE)
+ break;
+ udelay(1000);
+ }
+
+ /* Check if GOOD frame Tx'ed */
+ if(!(fcb->frame_status & FCB_COMMAND_DONE)
+ || fcb->frame_status & (FCB_TX_STATUS_E | FCB_TX_AC_BITS))
+ {
+ return (LOBE_MEDIA_TEST_FAILED);
+ }
+
+ /* De-allocated Tx FCB and Frame Buffer
+ * The FCB must be de-allocated manually if executing with
+ * interrupts disabled, other wise the ISR (LM_Service_Events)
+ * will de-allocate it when the interrupt occurs.
+ */
+ tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
+ smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
+
+ return (0);
+}
+
+static int smctr_send_rpt_addr(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 correlator)
+{
+ MAC_HEADER *tmf;
+ MAC_SUB_VECTOR *tsv;
+ FCBlock *fcb;
+
+ if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+ + S_CORRELATOR + S_PHYSICAL_DROP + S_UPSTREAM_NEIGHBOR_ADDRESS
+ + S_ADDRESS_MODIFER + S_GROUP_ADDRESS + S_FUNCTIONAL_ADDRESS))
+ == (FCBlock *)(-1L))
+ {
+ return (0);
+ }
+
+ tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+ tmf->vc = RPT_ADDR;
+ tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
+ tmf->vl = 4;
+
+ smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RPT_ADDR);
+
+ tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+ smctr_make_corr(dev, tsv, correlator);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_phy_drop_num(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_upstream_neighbor_addr(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_addr_mod(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_group_addr(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_funct_addr(dev, tsv);
+
+ tmf->vl += tsv->svl;
+
+ /* Subtract out MVID and MVL which is
+ * include in both vl and MAC_HEADER
+ */
+/* fcb->frame_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+ fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+*/
+ tmf->vl = SWAP_BYTES(tmf->vl);
+
+ return (smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+}
+
+static int smctr_send_rpt_attch(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 correlator)
+{
+ MAC_HEADER *tmf;
+ MAC_SUB_VECTOR *tsv;
+ FCBlock *fcb;
+
+ if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+ + S_CORRELATOR + S_PRODUCT_INSTANCE_ID + S_FUNCTIONAL_ADDRESS
+ + S_AUTHORIZED_FUNCTION_CLASS + S_AUTHORIZED_ACCESS_PRIORITY))
+ == (FCBlock *)(-1L))
+ {
+ return (0);
+ }
+
+ tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+ tmf->vc = RPT_ATTCH;
+ tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
+ tmf->vl = 4;
+
+ smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RPT_ATTCH);
+
+ tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+ smctr_make_corr(dev, tsv, correlator);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_product_id(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_funct_addr(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_auth_funct_class(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_access_pri(dev, tsv);
+
+ tmf->vl += tsv->svl;
+
+ /* Subtract out MVID and MVL which is
+ * include in both vl and MAC_HEADER
+ */
+/* fcb->frame_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+ fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+*/
+ tmf->vl = SWAP_BYTES(tmf->vl);
+
+ return (smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+}
+
+static int smctr_send_rpt_state(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 correlator)
+{
+ MAC_HEADER *tmf;
+ MAC_SUB_VECTOR *tsv;
+ FCBlock *fcb;
+
+ if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+ + S_CORRELATOR + S_RING_STATION_VERSION_NUMBER
+ + S_RING_STATION_STATUS + S_STATION_IDENTIFER))
+ == (FCBlock *)(-1L))
+ {
+ return (0);
+ }
+
+ tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+ tmf->vc = RPT_STATE;
+ tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
+ tmf->vl = 4;
+
+ smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RPT_STATE);
+
+ tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+ smctr_make_corr(dev, tsv, correlator);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_ring_station_version(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_ring_station_status(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_station_id(dev, tsv);
+
+ tmf->vl += tsv->svl;
+
+ /* Subtract out MVID and MVL which is
+ * include in both vl and MAC_HEADER
+ */
+/* fcb->frame_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+ fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+*/
+ tmf->vl = SWAP_BYTES(tmf->vl);
+
+ return (smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+}
+
+static int smctr_send_rpt_tx_forward(struct net_device *dev,
+ MAC_HEADER *rmf, __u16 tx_fstatus)
+{
+ MAC_HEADER *tmf;
+ MAC_SUB_VECTOR *tsv;
+ FCBlock *fcb;
+
+ if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+ + S_TRANSMIT_STATUS_CODE)) == (FCBlock *)(-1L))
+ {
+ return (0);
+ }
+
+ tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+ tmf->vc = RPT_TX_FORWARD;
+ tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
+ tmf->vl = 4;
+
+ smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RPT_TX_FORWARD);
+
+ tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+ smctr_make_tx_status_code(dev, tsv, tx_fstatus);
+
+ tmf->vl += tsv->svl;
+
+ /* Subtract out MVID and MVL which is
+ * include in both vl and MAC_HEADER
+ */
+/* fcb->frame_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+ fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+*/
+ tmf->vl = SWAP_BYTES(tmf->vl);
+
+ return(smctr_trc_send_packet(dev, fcb, MAC_QUEUE));
+}
+
+static int smctr_send_rsp(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 rcode, __u16 correlator)
+{
+ MAC_HEADER *tmf;
+ MAC_SUB_VECTOR *tsv;
+ FCBlock *fcb;
+
+ if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+ + S_CORRELATOR + S_RESPONSE_CODE)) == (FCBlock *)(-1L))
+ {
+ return (0);
+ }
+
+ tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+ tmf->vc = RSP;
+ tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
+ tmf->vl = 4;
+
+ smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RSP);
+
+ tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+ smctr_make_corr(dev, tsv, correlator);
+
+ return (0);
+}
+
+static int smctr_send_rq_init(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ MAC_HEADER *tmf;
+ MAC_SUB_VECTOR *tsv;
+ FCBlock *fcb;
+ unsigned int i, count = 0;
+ __u16 fstatus;
+ int err;
+
+ do {
+ if(((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
+ + S_PRODUCT_INSTANCE_ID + S_UPSTREAM_NEIGHBOR_ADDRESS
+ + S_RING_STATION_VERSION_NUMBER + S_ADDRESS_MODIFER))
+ == (FCBlock *)(-1L)))
+ {
+ return (0);
+ }
+
+ tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
+ tmf->vc = RQ_INIT;
+ tmf->dc_sc = DC_RPS | SC_RS;
+ tmf->vl = 4;
+
+ smctr_make_8025_hdr(dev, 0L, tmf, AC_FC_RQ_INIT);
+
+ tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
+ smctr_make_product_id(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_upstream_neighbor_addr(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_ring_station_version(dev, tsv);
+
+ tmf->vl += tsv->svl;
+ tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
+ smctr_make_addr_mod(dev, tsv);
+
+ tmf->vl += tsv->svl;
+
+ /* Subtract out MVID and MVL which is
+ * include in both vl and MAC_HEADER
+ */
+/* fcb->frame_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+ fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
+*/
+ tmf->vl = SWAP_BYTES(tmf->vl);
+
+ if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
+ return (err);
+
+ /* Wait for Transmit to Complete */
+ for(i = 0; i < 10000; i++)
+ {
+ if(fcb->frame_status & FCB_COMMAND_DONE)
+ break;
+ udelay(1000);
+ }
+
+ /* Check if GOOD frame Tx'ed */
+ fstatus = fcb->frame_status;
+
+ if(!(fstatus & FCB_COMMAND_DONE))
+ return (HARDWARE_FAILED);
+
+ if(!(fstatus & FCB_TX_STATUS_E))
+ count++;
+
+ /* De-allocated Tx FCB and Frame Buffer
+ * The FCB must be de-allocated manually if executing with
+ * interrupts disabled, other wise the ISR (LM_Service_Events)
+ * will de-allocate it when the interrupt occurs.
+ */
+ tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
+ smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
+ } while(count < 4 && ((fstatus & FCB_TX_AC_BITS) ^ FCB_TX_AC_BITS));
+
+ return (smctr_join_complete_state(dev));
+}
+
+static int smctr_send_tx_forward(struct net_device *dev, MAC_HEADER *rmf,
+ __u16 *tx_fstatus)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ FCBlock *fcb;
+ unsigned int i;
+ int err;
+
+ /* Check if this is the END POINT of the Transmit Forward Chain. */
+ if(rmf->vl <= 18)
+ return (0);
+
+ /* Allocate Transmit FCB only by requesting 0 bytes
+ * of data buffer.
+ */
+ if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, 0)) == (FCBlock *)(-1L))
+ return (0);
+
+ /* Set pointer to Transmit Frame Buffer to the data
+ * portion of the received TX Forward frame, making
+ * sure to skip over the Vector Code (vc) and Vector
+ * length (vl).
+ */
+ fcb->bdb_ptr->trc_data_block_ptr = TRC_POINTER((__u32)rmf
+ + sizeof(MAC_HEADER) + 2);
+ fcb->bdb_ptr->data_block_ptr = (__u16 *)((__u32)rmf
+ + sizeof(MAC_HEADER) + 2);
+
+ fcb->frame_length = rmf->vl - 4 - 2;
+ fcb->bdb_ptr->buffer_length = rmf->vl - 4 - 2;
+
+ if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
+ return (err);
+
+ /* Wait for Transmit to Complete */
+ for(i = 0; i < 10000; i++)
+ {
+ if(fcb->frame_status & FCB_COMMAND_DONE)
+ break;
+ udelay(1000);
+ }
+
+ /* Check if GOOD frame Tx'ed */
+ if(!(fcb->frame_status & FCB_COMMAND_DONE))
+ {
+ if((err = smctr_issue_resume_tx_fcb_cmd(dev, MAC_QUEUE)))
+ return (err);
+
+ for(i = 0; i < 10000; i++)
+ {
+ if(fcb->frame_status & FCB_COMMAND_DONE)
+ break;
+ udelay(1000);
+ }
+
+ if(!(fcb->frame_status & FCB_COMMAND_DONE))
+ return (HARDWARE_FAILED);
+ }
+
+ *tx_fstatus = fcb->frame_status;
+
+ return (A_FRAME_WAS_FORWARDED);
+}
+
+static int smctr_set_auth_access_pri(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ if(rsv->svl != S_AUTHORIZED_ACCESS_PRIORITY)
+ return (E_SUB_VECTOR_LENGTH_ERROR);
+
+ tp->authorized_access_priority = (rsv->svv[0] << 8 | rsv->svv[1]);
+
+ return (POSITIVE_ACK);
+}
+
+static int smctr_set_auth_funct_class(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ if(rsv->svl != S_AUTHORIZED_FUNCTION_CLASS)
+ return (E_SUB_VECTOR_LENGTH_ERROR);
+
+ tp->authorized_function_classes = (rsv->svv[0] << 8 | rsv->svv[1]);
+
+ return (POSITIVE_ACK);
+}
+
+static int smctr_set_corr(struct net_device *dev, MAC_SUB_VECTOR *rsv,
+ __u16 *correlator)
+{
+ if(rsv->svl != S_CORRELATOR)
+ return (E_SUB_VECTOR_LENGTH_ERROR);
+
+ *correlator = (rsv->svv[0] << 8 | rsv->svv[1]);
+
+ return (POSITIVE_ACK);
+}
+
+static int smctr_set_error_timer_value(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv)
+{
+ __u16 err_tval;
+ int err;
+
+ if(rsv->svl != S_ERROR_TIMER_VALUE)
+ return (E_SUB_VECTOR_LENGTH_ERROR);
+
+ err_tval = (rsv->svv[0] << 8 | rsv->svv[1])*10;
+
+ smctr_issue_write_word_cmd(dev, RW_TER_THRESHOLD, &err_tval);
+
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ return (POSITIVE_ACK);
+}
+
+static int smctr_set_frame_forward(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv, __u8 dc_sc)
+{
+ if((rsv->svl < 2) || (rsv->svl > S_FRAME_FORWARD))
+ return (E_SUB_VECTOR_LENGTH_ERROR);
+
+ if((dc_sc & DC_MASK) != DC_CRS)
+ {
+ if(rsv->svl >= 2 && rsv->svl < 20)
+ return (E_TRANSMIT_FORWARD_INVALID);
+
+ if((rsv->svv[0] != 0) || (rsv->svv[1] != 0))
+ return (E_TRANSMIT_FORWARD_INVALID);
+ }
+
+ return (POSITIVE_ACK);
+}
+
+static int smctr_set_local_ring_num(struct net_device *dev,
+ MAC_SUB_VECTOR *rsv)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ if(rsv->svl != S_LOCAL_RING_NUMBER)
+ return (E_SUB_VECTOR_LENGTH_ERROR);
+
+ if(tp->ptr_local_ring_num)
+ *(__u16 *)(tp->ptr_local_ring_num)
+ = (rsv->svv[0] << 8 | rsv->svv[1]);
+
+ return (POSITIVE_ACK);
+}
+
+static unsigned short smctr_set_ctrl_attention(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int ioaddr = dev->base_addr;
+
+ if(tp->bic_type == BIC_585_CHIP)
+ outb((tp->trc_mask | HWR_CA), ioaddr + HWR);
+ else
+ {
+ outb((tp->trc_mask | CSR_CA), ioaddr + CSR);
+ outb(tp->trc_mask, ioaddr + CSR);
+ }
+
+ return (0);
+}
+
+static void smctr_set_multicast_list(struct net_device *dev)
+{
+ if(smctr_debug > 10)
+ printk("%s: smctr_set_multicast_list\n", dev->name);
+
+ return;
+}
+
+static int smctr_set_page(struct net_device *dev, __u8 *buf)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ __u8 amask;
+ __u32 tptr;
+
+ tptr = (__u32)buf - (__u32)tp->ram_access;
+ amask = (__u8)((tptr & PR_PAGE_MASK) >> 8);
+ outb(amask, dev->base_addr + PR);
+
+ return (0);
+}
+
+static int smctr_set_phy_drop(struct net_device *dev, MAC_SUB_VECTOR *rsv)
+{
+ int err;
+
+ if(rsv->svl != S_PHYSICAL_DROP)
+ return (E_SUB_VECTOR_LENGTH_ERROR);
+
+ smctr_issue_write_byte_cmd(dev, RW_PHYSICAL_DROP_NUMBER, &rsv->svv[0]);
+ if((err = smctr_wait_cmd(dev)))
+ return (err);
+
+ return (POSITIVE_ACK);
+}
+
+/* Reset the ring speed to the oposite of what it was. This auto-pilot
+ * mode requires a complete reset and re-init of the adapter.
+ */
+static int smctr_set_ring_speed(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int err;
+
+ if(tp->media_type == MEDIA_UTP_16)
+ tp->media_type = MEDIA_UTP_4;
+ else
+ tp->media_type = MEDIA_UTP_16;
+
+ smctr_enable_16bit(dev);
+
+ /* Re-Initialize adapter's internal registers */
+ smctr_reset_adapter(dev);
+
+ if((err = smctr_init_card_real(dev)))
+ return (err);
+
+ smctr_enable_bic_int(dev);
+
+ if((err = smctr_issue_enable_int_cmd(dev, TRC_INTERRUPT_ENABLE_MASK)))
+ return (err);
+
+ smctr_disable_16bit(dev);
+
+ return (0);
+}
+
+static int smctr_set_rx_look_ahead(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ __u16 sword, rword;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_set_rx_look_ahead_flag\n", dev->name);
+
+ tp->adapter_flags &= ~(FORCED_16BIT_MODE);
+ tp->adapter_flags |= RX_VALID_LOOKAHEAD;
+
+ if(tp->adapter_bus == BUS_ISA16_TYPE)
+ {
+ sword = *((__u16 *)(tp->ram_access));
+ *((__u16 *)(tp->ram_access)) = 0x1234;
+
+ smctr_disable_16bit(dev);
+ rword = *((__u16 *)(tp->ram_access));
+ smctr_enable_16bit(dev);
+
+ if(rword != 0x1234)
+ tp->adapter_flags |= FORCED_16BIT_MODE;
+
+ *((__u16 *)(tp->ram_access)) = sword;
+ }
+
+ return (0);
+}
+
+static int smctr_set_trc_reset(int ioaddr)
+{
+ __u8 r;
+
+ r = inb(ioaddr + MSR);
+ outb(MSR_RST | r, ioaddr + MSR);
+
+ return (0);
+}
+
+/*
+ * This function can be called if the adapter is busy or not.
+ */
+static int smctr_setup_single_cmd(struct net_device *dev,
+ __u16 command, __u16 subcommand)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int err;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_setup_single_cmd\n", dev->name);
+
+ if((err = smctr_wait_while_cbusy(dev)))
+ return (err);
+
+ if((err = (unsigned int)smctr_wait_cmd(dev)))
+ return (err);
+
+ tp->acb_head->cmd_done_status = 0;
+ tp->acb_head->cmd = command;
+ tp->acb_head->subcmd = subcommand;
+
+ err = smctr_issue_resume_acb_cmd(dev);
+
+ return (err);
+}
+
+/*
+ * This function can not be called with the adapter busy.
+ */
+static int smctr_setup_single_cmd_w_data(struct net_device *dev,
+ __u16 command, __u16 subcommand)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ tp->acb_head->cmd_done_status = 0;
+ tp->acb_head->cmd = command;
+ tp->acb_head->subcmd = subcommand;
+ tp->acb_head->data_offset_lo
+ = (__u16)TRC_POINTER(tp->misc_command_data);
+
+ return(smctr_issue_resume_acb_cmd(dev));
+}
+
+static char *smctr_malloc(struct net_device *dev, __u16 size)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ char *m;
+
+ m = (char *)(tp->ram_access + tp->sh_mem_used);
+ tp->sh_mem_used += (__u32)size;
+
+ return (m);
+}
+
+static int smctr_status_chg(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_status_chg\n", dev->name);
+
+ switch(tp->status)
+ {
+ case OPEN:
+ break;
+
+ case CLOSED:
+ break;
+
+ /* Interrupt driven open() completion. XXX */
+ case INITIALIZED:
+ tp->group_address_0 = 0;
+ tp->group_address[0] = 0;
+ tp->group_address[1] = 0;
+ tp->functional_address_0 = 0;
+ tp->functional_address[0] = 0;
+ tp->functional_address[1] = 0;
+ smctr_open_tr(dev);
+ break;
+
+ default:
+ printk(KERN_INFO "%s: status change unknown %x\n",
+ dev->name, tp->status);
+ break;
+ }
+
+ return (0);
+}
+
+static int smctr_trc_send_packet(struct net_device *dev, FCBlock *fcb,
+ __u16 queue)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ int err = 0;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_trc_send_packet\n", dev->name);
+
+ fcb->info = FCB_CHAIN_END | FCB_ENABLE_TFS;
+ if(tp->num_tx_fcbs[queue] != 1)
+ fcb->back_ptr->info = FCB_INTERRUPT_ENABLE | FCB_ENABLE_TFS;
+
+ if(tp->tx_queue_status[queue] == NOT_TRANSMITING)
+ {
+ tp->tx_queue_status[queue] = TRANSMITING;
+ err = smctr_issue_resume_tx_fcb_cmd(dev, queue);
+ }
+
+ return (err);
+}
+
+static __u16 smctr_tx_complete(struct net_device *dev, __u16 queue)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ __u16 status, err = 0;
+ int cstatus;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_tx_complete\n", dev->name);
+
+ while((status = tp->tx_fcb_end[queue]->frame_status) != SUCCESS)
+ {
+ if(status & 0x7e00 )
+ {
+ err = HARDWARE_FAILED;
+ break;
+ }
+
+ if((err = smctr_update_tx_chain(dev, tp->tx_fcb_end[queue],
+ queue)) != SUCCESS)
+ break;
+
+ smctr_disable_16bit(dev);
+
+ if(tp->mode_bits & UMAC)
+ {
+ if(!(status & (FCB_TX_STATUS_AR1 | FCB_TX_STATUS_AR2)))
+ cstatus = NO_SUCH_DESTINATION;
+ else
+ {
+ if(!(status & (FCB_TX_STATUS_CR1 | FCB_TX_STATUS_CR2)))
+ cstatus = DEST_OUT_OF_RESOURCES;
+ else
+ {
+ if(status & FCB_TX_STATUS_E)
+ cstatus = MAX_COLLISIONS;
+ else
+ cstatus = SUCCESS;
+ }
+ }
+ }
+ else
+ cstatus = SUCCESS;
+
+ if(queue == BUG_QUEUE)
+ err = SUCCESS;
+
+ smctr_enable_16bit(dev);
+ if(err != SUCCESS)
+ break;
+ }
+
+ return (err);
+}
+
+static unsigned short smctr_tx_move_frame(struct net_device *dev,
+ struct sk_buff *skb, __u8 *pbuff, unsigned int bytes)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int ram_usable;
+ __u32 flen, len, offset = 0;
+ __u8 *frag, *page;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_tx_move_frame\n", dev->name);
+
+ ram_usable = ((unsigned int)tp->ram_usable) << 10;
+ frag = skb->data;
+ flen = skb->len;
+
+ while(flen > 0 && bytes > 0)
+ {
+ smctr_set_page(dev, pbuff);
+
+ offset = SMC_PAGE_OFFSET(pbuff);
+
+ if(offset + flen > ram_usable)
+ len = ram_usable - offset;
+ else
+ len = flen;
+
+ if(len > bytes)
+ len = bytes;
+
+ page = (char *) (offset + tp->ram_access);
+ memcpy(page, frag, len);
+
+ flen -=len;
+ bytes -= len;
+ frag += len;
+ pbuff += len;
+ }
+
+ return (0);
+}
+
+/* Update the error statistic counters for this adapter. */
+static int smctr_update_err_stats(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ struct tr_statistics *tstat = &tp->MacStat;
+
+ if(tstat->internal_errors)
+ tstat->internal_errors
+ += *(tp->misc_command_data + 0) & 0x00ff;
+
+ if(tstat->line_errors)
+ tstat->line_errors += *(tp->misc_command_data + 0) >> 8;
+
+ if(tstat->A_C_errors)
+ tstat->A_C_errors += *(tp->misc_command_data + 1) & 0x00ff;
+
+ if(tstat->burst_errors)
+ tstat->burst_errors += *(tp->misc_command_data + 1) >> 8;
+
+ if(tstat->abort_delimiters)
+ tstat->abort_delimiters += *(tp->misc_command_data + 2) >> 8;
+
+ if(tstat->recv_congest_count)
+ tstat->recv_congest_count
+ += *(tp->misc_command_data + 3) & 0x00ff;
+
+ if(tstat->lost_frames)
+ tstat->lost_frames
+ += *(tp->misc_command_data + 3) >> 8;
+
+ if(tstat->frequency_errors)
+ tstat->frequency_errors += *(tp->misc_command_data + 4) & 0x00ff;
+
+ if(tstat->frame_copied_errors)
+ tstat->frame_copied_errors
+ += *(tp->misc_command_data + 4) >> 8;
+
+ if(tstat->token_errors)
+ tstat->token_errors += *(tp->misc_command_data + 5) >> 8;
+
+ return (0);
+}
+
+static int smctr_update_rx_chain(struct net_device *dev, __u16 queue)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ FCBlock *fcb;
+ BDBlock *bdb;
+ __u16 size, len;
+
+ fcb = tp->rx_fcb_curr[queue];
+ len = fcb->frame_length;
+
+ fcb->frame_status = 0;
+ fcb->info = FCB_CHAIN_END;
+ fcb->back_ptr->info = FCB_WARNING;
+
+ tp->rx_fcb_curr[queue] = tp->rx_fcb_curr[queue]->next_ptr;
+
+ /* update RX BDBs */
+ size = (len >> RX_BDB_SIZE_SHIFT);
+ if(len & RX_DATA_BUFFER_SIZE_MASK)
+ size += sizeof(BDBlock);
+ size &= (~RX_BDB_SIZE_MASK);
+
+ /* check if wrap around */
+ bdb = (BDBlock *)((__u32)(tp->rx_bdb_curr[queue]) + (__u32)(size));
+ if((__u32)bdb >= (__u32)tp->rx_bdb_end[queue])
+ {
+ bdb = (BDBlock *)((__u32)(tp->rx_bdb_head[queue])
+ + (__u32)(bdb) - (__u32)(tp->rx_bdb_end[queue]));
+ }
+
+ bdb->back_ptr->info = BDB_CHAIN_END;
+ tp->rx_bdb_curr[queue]->back_ptr->info = BDB_NOT_CHAIN_END;
+ tp->rx_bdb_curr[queue] = bdb;
+
+ return (0);
+}
+
+static int smctr_update_tx_chain(struct net_device *dev, FCBlock *fcb,
+ __u16 queue)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+
+ if(smctr_debug > 20)
+ printk("smctr_update_tx_chain\n");
+
+ if(tp->num_tx_fcbs_used[queue] <= 0)
+ return (HARDWARE_FAILED);
+ else
+ {
+ if(tp->tx_buff_used[queue] < fcb->memory_alloc)
+ {
+ tp->tx_buff_used[queue] = 0;
+ return (HARDWARE_FAILED);
+ }
+
+ tp->tx_buff_used[queue] -= fcb->memory_alloc;
+
+ /* if all transmit buffer are cleared
+ * need to set the tx_buff_curr[] to tx_buff_head[]
+ * otherwise, tx buffer will be segregate and cannot
+ * accomodate and buffer greater than (curr - head) and
+ * (end - curr) since we do not allow wrap around allocation.
+ */
+ if(tp->tx_buff_used[queue] == 0)
+ tp->tx_buff_curr[queue] = tp->tx_buff_head[queue];
+
+ tp->num_tx_fcbs_used[queue]--;
+ fcb->frame_status = 0;
+ tp->tx_fcb_end[queue] = fcb->next_ptr;
+
+ return (0);
+ }
+}
+
+static int smctr_wait_cmd(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int loop_count = 0x20000;
+
+ if(smctr_debug > 10)
+ printk("%s: smctr_wait_cmd\n", dev->name);
+
+ while(loop_count)
+ {
+ if(tp->acb_head->cmd_done_status & ACB_COMMAND_DONE)
+ break;
+ loop_count--;
+ }
+
+ if(loop_count == 0)
+ return(-1);
+
+ if(tp->acb_head->cmd_done_status & 0xff)
+ return(-1);
+
+ return (0);
+}
+
+static int smctr_wait_while_cbusy(struct net_device *dev)
+{
+ struct net_local *tp = (struct net_local *)dev->priv;
+ unsigned int timeout = 0x20000;
+ int ioaddr = dev->base_addr;
+ __u8 r;
+
+ if(tp->bic_type == BIC_585_CHIP)
+ {
+ while(timeout)
+ {
+ r = inb(ioaddr + HWR);
+ if((r & HWR_CBUSY) == 0)
+ break;
+ timeout--;
+ }
+ }
+ else
+ {
+ while(timeout)
+ {
+ r = inb(ioaddr + CSR);
+ if((r & CSR_CBUSY) == 0)
+ break;
+ timeout--;
+ }
+ }
+
+ if(timeout)
+ return (0);
+ else
+ return (-1);
+}
+
+#ifdef MODULE
+
+static struct net_device* dev_smctr[SMCTR_MAX_ADAPTERS];
+static int io[SMCTR_MAX_ADAPTERS] = { 0, 0 };
+static int irq[SMCTR_MAX_ADAPTERS] = { 0, 0 };
+static int mem[SMCTR_MAX_ADAPTERS] = { 0, 0 };
+
+MODULE_PARM(io, "1-" __MODULE_STRING(SMCTR_MAX_ADAPTERS) "i");
+MODULE_PARM(irq, "1-" __MODULE_STRING(SMCTR_MAX_ADAPTERS) "i");
+MODULE_PARM(mem, "1-" __MODULE_STRING(SMCTR_MAX_ADAPTERS) "i");
+MODULE_PARM(ringspeed, "1-" __MODULE_STRING(SMCTR_MAX_ADAPTERS) "i");
+
+int init_module(void)
+{
+ int i;
+
+ for(i = 0; i < SMCTR_MAX_ADAPTERS; i++)
+ {
+ irq[i] = 0;
+ mem[i] = 0;
+ dev_smctr[i] = NULL;
+ dev_smctr[i] = init_trdev(dev_smctr[i], 0);
+ if(dev_smctr[i] == NULL)
+ return (-ENOMEM);
+
+ dev_smctr[i]->base_addr = io[i];
+ dev_smctr[i]->irq = irq[i];
+ dev_smctr[i]->mem_start = mem[i];
+ dev_smctr[i]->init = &smctr_probe;
+
+ if(register_trdev(dev_smctr[i]) != 0)
+ {
+ kfree_s(dev_smctr[i], sizeof(struct net_device));
+ dev_smctr[i] = NULL;
+ if(i == 0)
+ {
+ printk("%s: register_trdev() returned (<0).\n",
+ cardname);
+ return (-EIO);
+ }
+ else
+ return (0);
+ }
+ }
+
+ return (0);
+}
+
+void cleanup_module(void)
+{
+ int i;
+
+ for(i = 0; i < SMCTR_MAX_ADAPTERS; i++)
+ {
+ if(dev_smctr[i])
+ {
+ unregister_trdev(dev_smctr[i]);
+ release_region(dev_smctr[i]->base_addr,
+ SMCTR_IO_EXTENT);
+ if(dev_smctr[i]->irq)
+ free_irq(dev_smctr[i]->irq, dev_smctr[i]);
+ if(dev_smctr[i]->priv)
+ kfree_s(dev_smctr[i]->priv,
+ sizeof(struct net_local));
+ kfree_s(dev_smctr[i], sizeof(struct net_device));
+ dev_smctr[i] = NULL;
+ }
+ }
+}
+#endif /* MODULE */
--- /dev/null
+/* smctr.h: SMC Token Ring driver header for Linux
+ *
+ * Authors:
+ * - Jay Schulist <jschlst@turbolinux.com>
+ */
+
+#ifndef __LINUX_SMCTR_H
+#define __LINUX_SMCTR_H
+
+#ifdef __KERNEL__
+
+#define MAX_TX_QUEUE 10
+
+#define SMC_HEADER_SIZE 14
+
+#define SMC_PAGE_OFFSET(X) (((unsigned long)(X) - tp->ram_access) & tp->page_offset_mask)
+
+#define INIT 0x0D
+#define RQ_ATTCH 0x10
+#define RQ_STATE 0x0F
+#define RQ_ADDR 0x0E
+#define CHG_PARM 0x0C
+#define RSP 0x00
+#define TX_FORWARD 0x09
+
+#define AC_FC_DAT ((3<<13) | 1)
+#define DAT 0x07
+
+#define RPT_NEW_MON 0x25
+#define RPT_SUA_CHG 0x26
+#define RPT_ACTIVE_ERR 0x28
+#define RPT_NN_INCMP 0x27
+#define RPT_ERROR 0x29
+
+#define RQ_INIT 0x20
+#define RPT_ATTCH 0x24
+#define RPT_STATE 0x23
+#define RPT_ADDR 0x22
+
+#define POSITIVE_ACK 0x0001
+#define A_FRAME_WAS_FORWARDED 0x8888
+
+#define GROUP_ADDRESS 0x2B
+#define PHYSICAL_DROP 0x0B
+#define AUTHORIZED_ACCESS_PRIORITY 0x07
+#define AUTHORIZED_FUNCTION_CLASS 0x06
+#define FUNCTIONAL_ADDRESS 0x2C
+#define RING_STATION_STATUS 0x29
+#define TRANSMIT_STATUS_CODE 0x2A
+#define IBM_PASS_SOURCE_ADDR 0x01
+#define AC_FC_RPT_TX_FORWARD ((0<<13) | 0)
+#define AC_FC_RPT_STATE ((0<<13) | 0)
+#define AC_FC_RPT_ADDR ((0<<13) | 0)
+#define CORRELATOR 0x09
+
+#define POSITIVE_ACK 0x0001 /* */
+#define E_MAC_DATA_INCOMPLETE 0x8001 /* not used */
+#define E_VECTOR_LENGTH_ERROR 0x8002 /* */
+#define E_UNRECOGNIZED_VECTOR_ID 0x8003 /* */
+#define E_INAPPROPRIATE_SOURCE_CLASS 0x8004 /* */
+#define E_SUB_VECTOR_LENGTH_ERROR 0x8005 /* */
+#define E_TRANSMIT_FORWARD_INVALID 0x8006 /* def. by IBM */
+#define E_MISSING_SUB_VECTOR 0x8007 /* */
+#define E_SUB_VECTOR_UNKNOWN 0x8008 /* */
+#define E_MAC_HEADER_TOO_LONG 0x8009 /* */
+#define E_FUNCTION_DISABLED 0x800A /* not used */
+
+#define A_FRAME_WAS_FORWARDED 0x8888 /* used by send_TX_FORWARD */
+
+#define UPSTREAM_NEIGHBOR_ADDRESS 0x02
+#define LOCAL_RING_NUMBER 0x03
+#define ASSIGN_PHYSICAL_DROP 0x04
+#define ERROR_TIMER_VALUE 0x05
+#define AUTHORIZED_FUNCTION_CLASS 0x06
+#define AUTHORIZED_ACCESS_PRIORITY 0x07
+#define CORRELATOR 0x09
+#define PHYSICAL_DROP 0x0B
+#define RESPONSE_CODE 0x20
+#define ADDRESS_MODIFER 0x21
+#define PRODUCT_INSTANCE_ID 0x22
+#define RING_STATION_VERSION_NUMBER 0x23
+#define WRAP_DATA 0x26
+#define FRAME_FORWARD 0x27
+#define STATION_IDENTIFER 0x28
+#define RING_STATION_STATUS 0x29
+#define TRANSMIT_STATUS_CODE 0x2A
+#define GROUP_ADDRESS 0x2B
+#define FUNCTIONAL_ADDRESS 0x2C
+
+#define F_NO_SUB_VECTORS_FOUND 0x0000
+#define F_UPSTREAM_NEIGHBOR_ADDRESS 0x0001
+#define F_LOCAL_RING_NUMBER 0x0002
+#define F_ASSIGN_PHYSICAL_DROP 0x0004
+#define F_ERROR_TIMER_VALUE 0x0008
+#define F_AUTHORIZED_FUNCTION_CLASS 0x0010
+#define F_AUTHORIZED_ACCESS_PRIORITY 0x0020
+#define F_CORRELATOR 0x0040
+#define F_PHYSICAL_DROP 0x0080
+#define F_RESPONSE_CODE 0x0100
+#define F_PRODUCT_INSTANCE_ID 0x0200
+#define F_RING_STATION_VERSION_NUMBER 0x0400
+#define F_STATION_IDENTIFER 0x0800
+#define F_RING_STATION_STATUS 0x1000
+#define F_GROUP_ADDRESS 0x2000
+#define F_FUNCTIONAL_ADDRESS 0x4000
+#define F_FRAME_FORWARD 0x8000
+
+#define R_INIT 0x00
+#define R_RQ_ATTCH_STATE_ADDR 0x00
+#define R_CHG_PARM 0x00
+#define R_TX_FORWARD F_FRAME_FORWARD
+
+
+#define UPSTREAM_NEIGHBOR_ADDRESS 0x02
+#define ADDRESS_MODIFER 0x21
+#define RING_STATION_VERSION_NUMBER 0x23
+#define PRODUCT_INSTANCE_ID 0x22
+
+#define RPT_TX_FORWARD 0x2A
+
+#define AC_FC_INIT (3<<13) | 0 /* */
+#define AC_FC_RQ_INIT ((3<<13) | 0) /* */
+#define AC_FC_RQ_ATTCH (3<<13) | 0 /* DC = SC of rx frame */
+#define AC_FC_RQ_STATE (3<<13) | 0 /* DC = SC of rx frame */
+#define AC_FC_RQ_ADDR (3<<13) | 0 /* DC = SC of rx frame */
+#define AC_FC_CHG_PARM (3<<13) | 0 /* */
+#define AC_FC_RSP (0<<13) | 0 /* DC = SC of rx frame */
+#define AC_FC_RPT_ATTCH (0<<13) | 0
+
+#define S_UPSTREAM_NEIGHBOR_ADDRESS 6 + 2
+#define S_LOCAL_RING_NUMBER 2 + 2
+#define S_ASSIGN_PHYSICAL_DROP 4 + 2
+#define S_ERROR_TIMER_VALUE 2 + 2
+#define S_AUTHORIZED_FUNCTION_CLASS 2 + 2
+#define S_AUTHORIZED_ACCESS_PRIORITY 2 + 2
+#define S_CORRELATOR 2 + 2
+#define S_PHYSICAL_DROP 4 + 2
+#define S_RESPONSE_CODE 4 + 2
+#define S_ADDRESS_MODIFER 2 + 2
+#define S_PRODUCT_INSTANCE_ID 18 + 2
+#define S_RING_STATION_VERSION_NUMBER 10 + 2
+#define S_STATION_IDENTIFER 6 + 2
+#define S_RING_STATION_STATUS 6 + 2
+#define S_GROUP_ADDRESS 4 + 2
+#define S_FUNCTIONAL_ADDRESS 4 + 2
+#define S_FRAME_FORWARD 252 + 2
+#define S_TRANSMIT_STATUS_CODE 2 + 2
+
+#define ISB_IMC_RES0 0x0000 /* */
+#define ISB_IMC_MAC_TYPE_3 0x0001 /* MAC_ARC_INDICATE */
+#define ISB_IMC_MAC_ERROR_COUNTERS 0x0002 /* */
+#define ISB_IMC_RES1 0x0003 /* */
+#define ISB_IMC_MAC_TYPE_2 0x0004 /* QUE_MAC_INDICATE */
+#define ISB_IMC_TX_FRAME 0x0005 /* */
+#define ISB_IMC_END_OF_TX_QUEUE 0x0006 /* */
+#define ISB_IMC_NON_MAC_RX_RESOURCE 0x0007 /* */
+#define ISB_IMC_MAC_RX_RESOURCE 0x0008 /* */
+#define ISB_IMC_NON_MAC_RX_FRAME 0x0009 /* */
+#define ISB_IMC_MAC_RX_FRAME 0x000A /* */
+#define ISB_IMC_TRC_FIFO_STATUS 0x000B /* */
+#define ISB_IMC_COMMAND_STATUS 0x000C /* */
+#define ISB_IMC_MAC_TYPE_1 0x000D /* Self Removed */
+#define ISB_IMC_TRC_INTRNL_TST_STATUS 0x000E /* */
+#define ISB_IMC_RES2 0x000F /* */
+
+#define NON_MAC_RX_RESOURCE_BW 0x10 /* shifted right 8 bits */
+#define NON_MAC_RX_RESOURCE_FW 0x20 /* shifted right 8 bits */
+#define NON_MAC_RX_RESOURCE_BE 0x40 /* shifted right 8 bits */
+#define NON_MAC_RX_RESOURCE_FE 0x80 /* shifted right 8 bits */
+#define RAW_NON_MAC_RX_RESOURCE_BW 0x1000 /* */
+#define RAW_NON_MAC_RX_RESOURCE_FW 0x2000 /* */
+#define RAW_NON_MAC_RX_RESOURCE_BE 0x4000 /* */
+#define RAW_NON_MAC_RX_RESOURCE_FE 0x8000 /* */
+
+#define MAC_RX_RESOURCE_BW 0x10 /* shifted right 8 bits */
+#define MAC_RX_RESOURCE_FW 0x20 /* shifted right 8 bits */
+#define MAC_RX_RESOURCE_BE 0x40 /* shifted right 8 bits */
+#define MAC_RX_RESOURCE_FE 0x80 /* shifted right 8 bits */
+#define RAW_MAC_RX_RESOURCE_BW 0x1000 /* */
+#define RAW_MAC_RX_RESOURCE_FW 0x2000 /* */
+#define RAW_MAC_RX_RESOURCE_BE 0x4000 /* */
+#define RAW_MAC_RX_RESOURCE_FE 0x8000 /* */
+
+#define TRC_FIFO_STATUS_TX_UNDERRUN 0x40 /* shifted right 8 bits */
+#define TRC_FIFO_STATUS_RX_OVERRUN 0x80 /* shifted right 8 bits */
+#define RAW_TRC_FIFO_STATUS_TX_UNDERRUN 0x4000 /* */
+#define RAW_TRC_FIFO_STATUS_RX_OVERRUN 0x8000 /* */
+
+#define CSR_CLRTINT 0x08
+
+#define MSB(X) ((__u8)((__u16) X >> 8))
+#define LSB(X) ((__u8)((__u16) X & 0xff))
+
+#define AC_FC_LOBE_MEDIA_TEST ((3<<13) | 0)
+#define S_WRAP_DATA 248 + 2 /* 500 + 2 */
+#define WRAP_DATA 0x26
+#define LOBE_MEDIA_TEST 0x08
+
+/* Destination Class (dc) */
+
+#define DC_MASK 0xF0
+#define DC_RS 0x00
+#define DC_CRS 0x40
+#define DC_RPS 0x50
+#define DC_REM 0x60
+
+/* Source Classes (sc) */
+
+#define SC_MASK 0x0F
+#define SC_RS 0x00
+#define SC_CRS 0x04
+#define SC_RPS 0x05
+#define SC_REM 0x06
+
+#define PR 0x11
+#define PR_PAGE_MASK 0x0C000
+
+#define MICROCHANNEL 0x0008
+#define INTERFACE_CHIP 0x0010
+#define BOARD_16BIT 0x0040
+#define PAGED_RAM 0x0080
+#define WD8115TA (TOKEN_MEDIA | MICROCHANNEL | INTERFACE_CHIP | PAGED_RAM)
+#define WD8115T (TOKEN_MEDIA | INTERFACE_CHIP | BOARD_16BIT | PAGED_RAM)
+
+#define BRD_ID_8316 0x50
+
+#define r587_SER 0x001
+#define SER_DIN 0x80
+#define SER_DOUT 0x40
+#define SER_CLK 0x20
+#define SER_ECS 0x10
+#define SER_E806 0x08
+#define SER_PNP 0x04
+#define SER_BIO 0x02
+#define SER_16B 0x01
+
+#define r587_IDR 0x004
+#define IDR_IRQ_MASK 0x0F0
+#define IDR_DCS_MASK 0x007
+#define IDR_RWS 0x008
+
+
+#define r587_BIO 0x003
+#define BIO_ENB 0x080
+#define BIO_MASK 0x03F
+
+#define r587_PCR 0x005
+#define PCR_RAMS 0x040
+
+
+
+#define NUM_ADDR_BITS 8
+
+#define ISA_MAX_ADDRESS 0x00ffffff
+
+#define SMCTR_MAX_ADAPTERS 7
+
+#define MC_TABLE_ENTRIES 16
+
+#define MAXFRAGMENTS 32
+
+#define CHIP_REV_MASK 0x3000
+
+#define MAX_TX_QS 8
+#define NUM_TX_QS_USED 3
+
+#define MAX_RX_QS 2
+#define NUM_RX_QS_USED 2
+
+#define INTEL_DATA_FORMAT 0x4000
+#define INTEL_ADDRESS_POINTER_FORMAT 0x8000
+#define PAGE_POINTER(X) ((((unsigned long)(X) - tp->ram_access) & tp->page_offset_mask) + tp->ram_access)
+#define SWAP_WORDS(X) (((X & 0xFFFF) << 16) | (X >> 16))
+
+#define INTERFACE_CHIP 0x0010 /* Soft Config Adapter */
+#define ADVANCED_FEATURES 0x0020 /* Adv. netw. interface features */
+#define BOARD_16BIT 0x0040 /* 16 bit capability */
+#define PAGED_RAM 0x0080 /* Adapter has paged RAM */
+
+#define PAGED_ROM 0x0100 /* Adapter has paged ROM */
+
+#define RAM_SIZE_UNKNOWN 0x0000 /* Unknown RAM size */
+#define RAM_SIZE_0K 0x0001 /* 0K RAM */
+#define RAM_SIZE_8K 0x0002 /* 8k RAM */
+#define RAM_SIZE_16K 0x0003 /* 16k RAM */
+#define RAM_SIZE_32K 0x0004 /* 32k RAM */
+#define RAM_SIZE_64K 0x0005 /* 64k RAM */
+#define RAM_SIZE_RESERVED_6 0x0006 /* Reserved RAM size */
+#define RAM_SIZE_RESERVED_7 0x0007 /* Reserved RAM size */
+#define RAM_SIZE_MASK 0x0007 /* Isolates RAM Size */
+
+#define TOKEN_MEDIA 0x0005
+
+#define BID_REG_0 0x00
+#define BID_REG_1 0x01
+#define BID_REG_2 0x02
+#define BID_REG_3 0x03
+#define BID_REG_4 0x04
+#define BID_REG_5 0x05
+#define BID_REG_6 0x06
+#define BID_REG_7 0x07
+#define BID_LAR_0 0x08
+#define BID_LAR_1 0x09
+#define BID_LAR_2 0x0A
+#define BID_LAR_3 0x0B
+#define BID_LAR_4 0x0C
+#define BID_LAR_5 0x0D
+
+#define BID_BOARD_ID_BYTE 0x0E
+#define BID_CHCKSM_BYTE 0x0F
+#define BID_LAR_OFFSET 0x08
+
+#define BID_MSZ_583_BIT 0x08
+#define BID_SIXTEEN_BIT_BIT 0x01
+
+#define BID_BOARD_REV_MASK 0x1E
+
+#define BID_MEDIA_TYPE_BIT 0x01
+#define BID_SOFT_CONFIG_BIT 0x20
+#define BID_RAM_SIZE_BIT 0x40
+#define BID_BUS_TYPE_BIT 0x80
+
+#define BID_CR 0x10
+
+#define BID_TXP 0x04 /* Transmit Packet Command */
+
+#define BID_TCR_DIFF 0x0D /* Transmit Configuration Register */
+
+#define BID_TCR_VAL 0x18 /* Value to Test 8390 or 690 */
+#define BID_PS0 0x00 /* Register Page Select 0 */
+#define BID_PS1 0x40 /* Register Page Select 1 */
+#define BID_PS2 0x80 /* Register Page Select 2 */
+#define BID_PS_MASK 0x3F /* For Masking Off Page Select Bits */
+
+#define BID_EEPROM_0 0x08
+#define BID_EEPROM_1 0x09
+#define BID_EEPROM_2 0x0A
+#define BID_EEPROM_3 0x0B
+#define BID_EEPROM_4 0x0C
+#define BID_EEPROM_5 0x0D
+#define BID_EEPROM_6 0x0E
+#define BID_EEPROM_7 0x0F
+
+#define BID_OTHER_BIT 0x02
+#define BID_ICR_MASK 0x0C
+#define BID_EAR_MASK 0x0F
+#define BID_ENGR_PAGE 0x0A0
+#define BID_RLA 0x10
+#define BID_EA6 0x80
+#define BID_RECALL_DONE_MASK 0x10
+#define BID_BID_EEPROM_OVERRIDE 0xFFB0
+#define BID_EXTRA_EEPROM_OVERRIDE 0xFFD0
+#define BID_EEPROM_MEDIA_MASK 0x07
+#define BID_STARLAN_TYPE 0x00
+#define BID_ETHERNET_TYPE 0x01
+#define BID_TP_TYPE 0x02
+#define BID_EW_TYPE 0x03
+#define BID_TOKEN_RING_TYPE 0x04
+#define BID_UTP2_TYPE 0x05
+#define BID_EEPROM_IRQ_MASK 0x18
+#define BID_PRIMARY_IRQ 0x00
+#define BID_ALTERNATE_IRQ_1 0x08
+#define BID_ALTERNATE_IRQ_2 0x10
+#define BID_ALTERNATE_IRQ_3 0x18
+#define BID_EEPROM_RAM_SIZE_MASK 0xE0
+#define BID_EEPROM_RAM_SIZE_RES1 0x00
+#define BID_EEPROM_RAM_SIZE_RES2 0x20
+#define BID_EEPROM_RAM_SIZE_8K 0x40
+#define BID_EEPROM_RAM_SIZE_16K 0x60
+#define BID_EEPROM_RAM_SIZE_32K 0x80
+#define BID_EEPROM_RAM_SIZE_64K 0xA0
+#define BID_EEPROM_RAM_SIZE_RES3 0xC0
+#define BID_EEPROM_RAM_SIZE_RES4 0xE0
+#define BID_EEPROM_BUS_TYPE_MASK 0x07
+#define BID_EEPROM_BUS_TYPE_AT 0x00
+#define BID_EEPROM_BUS_TYPE_MCA 0x01
+#define BID_EEPROM_BUS_TYPE_EISA 0x02
+#define BID_EEPROM_BUS_TYPE_NEC 0x03
+#define BID_EEPROM_BUS_SIZE_MASK 0x18
+#define BID_EEPROM_BUS_SIZE_8BIT 0x00
+#define BID_EEPROM_BUS_SIZE_16BIT 0x08
+#define BID_EEPROM_BUS_SIZE_32BIT 0x10
+#define BID_EEPROM_BUS_SIZE_64BIT 0x18
+#define BID_EEPROM_BUS_MASTER 0x20
+#define BID_EEPROM_RAM_PAGING 0x40
+#define BID_EEPROM_ROM_PAGING 0x80
+#define BID_EEPROM_PAGING_MASK 0xC0
+#define BID_EEPROM_LOW_COST 0x08
+#define BID_EEPROM_IO_MAPPED 0x10
+#define BID_EEPROM_HMI 0x01
+#define BID_EEPROM_AUTO_MEDIA_DETECT 0x01
+#define BID_EEPROM_CHIP_REV_MASK 0x0C
+
+#define BID_EEPROM_LAN_ADDR 0x30
+
+#define BID_EEPROM_MEDIA_OPTION 0x54
+#define BID_EEPROM_MEDIA_UTP 0x01
+#define BID_EEPROM_4MB_RING 0x08
+#define BID_EEPROM_16MB_RING 0x10
+#define BID_EEPROM_MEDIA_STP 0x40
+
+#define BID_EEPROM_MISC_DATA 0x56
+#define BID_EEPROM_EARLY_TOKEN_RELEASE 0x02
+
+#define CNFG_ID_8003E 0x6fc0
+#define CNFG_ID_8003S 0x6fc1
+#define CNFG_ID_8003W 0x6fc2
+#define CNFG_ID_8115TRA 0x6ec6
+#define CNFG_ID_8013E 0x61C8
+#define CNFG_ID_8013W 0x61C9
+#define CNFG_ID_BISTRO03E 0xEFE5
+#define CNFG_ID_BISTRO13E 0xEFD5
+#define CNFG_ID_BISTRO13W 0xEFD4
+#define CNFG_MSR_583 0x0
+#define CNFG_ICR_583 0x1
+#define CNFG_IAR_583 0x2
+#define CNFG_BIO_583 0x3
+#define CNFG_EAR_583 0x3
+#define CNFG_IRR_583 0x4
+#define CNFG_LAAR_584 0x5
+#define CNFG_GP2 0x7
+#define CNFG_LAAR_MASK 0x1F
+#define CNFG_LAAR_ZWS 0x20
+#define CNFG_LAAR_L16E 0x40
+#define CNFG_ICR_IR2_584 0x04
+#define CNFG_ICR_MASK 0x08
+#define CNFG_ICR_MSZ 0x08
+#define CNFG_ICR_RLA 0x10
+#define CNFG_ICR_STO 0x80
+#define CNFG_IRR_IRQS 0x60
+#define CNFG_IRR_IEN 0x80
+#define CNFG_IRR_ZWS 0x01
+#define CNFG_GP2_BOOT_NIBBLE 0x0F
+#define CNFG_IRR_OUT2 0x04
+#define CNFG_IRR_OUT1 0x02
+
+#define CNFG_SIZE_8KB 8
+#define CNFG_SIZE_16KB 16
+#define CNFG_SIZE_32KB 32
+#define CNFG_SIZE_64KB 64
+#define CNFG_SIZE_128KB 128
+#define CNFG_SIZE_256KB 256
+#define ROM_DISABLE 0x0
+
+#define CNFG_SLOT_ENABLE_BIT 0x08
+
+#define CNFG_POS_CONTROL_REG 0x096
+#define CNFG_POS_REG0 0x100
+#define CNFG_POS_REG1 0x101
+#define CNFG_POS_REG2 0x102
+#define CNFG_POS_REG3 0x103
+#define CNFG_POS_REG4 0x104
+#define CNFG_POS_REG5 0x105
+
+#define CNFG_ADAPTER_TYPE_MASK 0x0e
+
+#define SLOT_16BIT 0x0008
+#define INTERFACE_5X3_CHIP 0x0000 /* 0000 = 583 or 593 chips */
+#define NIC_690_BIT 0x0010 /* NIC is 690 */
+#define ALTERNATE_IRQ_BIT 0x0020 /* Alternate IRQ is used */
+#define INTERFACE_584_CHIP 0x0040 /* 0001 = 584 chip */
+#define INTERFACE_594_CHIP 0x0080 /* 0010 = 594 chip */
+#define INTERFACE_585_CHIP 0x0100 /* 0100 = 585/790 chip */
+#define INTERFACE_CHIP_MASK 0x03C0 /* Isolates Intfc Chip Type */
+
+#define BOARD_16BIT 0x0040
+#define NODE_ADDR_CKSUM 0xEE
+#define BRD_ID_8115T 0x04
+
+#define NIC_825_BIT 0x0400 /* TRC 83C825 NIC */
+#define NIC_790_BIT 0x0800 /* NIC is 83C790 Ethernet */
+
+#define CHIP_REV_MASK 0x3000
+
+#define HWR_CBUSY 0x02
+#define HWR_CA 0x01
+
+#define MAC_QUEUE 0
+#define NON_MAC_QUEUE 1
+#define BUG_QUEUE 2 /* NO RECEIVE QUEUE, ONLY TX */
+
+#define NUM_MAC_TX_FCBS 8
+#define NUM_MAC_TX_BDBS NUM_MAC_TX_FCBS
+#define NUM_MAC_RX_FCBS 7
+#define NUM_MAC_RX_BDBS 8
+
+#define NUM_NON_MAC_TX_FCBS 6
+#define NUM_NON_MAC_TX_BDBS NUM_NON_MAC_TX_FCBS
+
+#define NUM_NON_MAC_RX_BDBS 0 /* CALCULATED DYNAMICALLY */
+
+#define NUM_BUG_TX_FCBS 8
+#define NUM_BUG_TX_BDBS NUM_BUG_TX_FCBS
+
+#define MAC_TX_BUFFER_MEMORY 1024
+#define NON_MAC_TX_BUFFER_MEMORY (20 * 1024)
+#define BUG_TX_BUFFER_MEMORY (NUM_BUG_TX_FCBS * 32)
+
+#define RX_BUFFER_MEMORY 0 /* CALCULATED DYNAMICALLY */
+#define RX_DATA_BUFFER_SIZE 256
+#define RX_BDB_SIZE_SHIFT 3 /* log2(RX_DATA_BUFFER_SIZE)-log2(sizeof(BDBlock)) */
+#define RX_BDB_SIZE_MASK (sizeof(BDBlock) - 1)
+#define RX_DATA_BUFFER_SIZE_MASK (RX_DATA_BUFFER_SIZE-1)
+
+#define NUM_OF_INTERRUPTS 0x20
+
+#define NOT_TRANSMITING 0
+#define TRANSMITING 1
+
+#define TRC_INTERRUPT_ENABLE_MASK 0x7FF6
+
+#define UCODE_VERSION 0x58
+
+#define UCODE_SIZE_OFFSET 0x0000 /* WORD */
+#define UCODE_CHECKSUM_OFFSET 0x0002 /* WORD */
+#define UCODE_VERSION_OFFSET 0x0004 /* BYTE */
+
+#define CS_RAM_SIZE 0X2000
+#define CS_RAM_CHECKSUM_OFFSET 0x1FFE /* WORD 1FFE(MSB)-1FFF(LSB)*/
+#define CS_RAM_VERSION_OFFSET 0x1FFC /* WORD 1FFC(MSB)-1FFD(LSB)*/
+
+#define MISC_DATA_SIZE 128
+#define NUM_OF_ACBS 1
+
+#define ACB_COMMAND_NOT_DONE 0x0000 /* Init, command not done */
+#define ACB_COMMAND_DONE 0x8000 /* TRC says command done */
+#define ACB_COMMAND_STATUS_MASK 0x00FF /* low byte is status */
+#define ACB_COMMAND_SUCCESSFUL 0x0000 /* means cmd was successful */
+#define ACB_NOT_CHAIN_END 0x0000 /* tell TRC more CBs in chain */
+#define ACB_CHAIN_END 0x8000 /* tell TRC last CB in chain */
+#define ACB_COMMAND_NO_INTERRUPT 0x0000 /* tell TRC no INT after CB */
+#define ACB_COMMAND_INTERRUPT 0x2000 /* tell TRC to INT after CB */
+#define ACB_SUB_CMD_NOP 0x0000
+#define ACB_CMD_HIC_NOP 0x0080
+#define ACB_CMD_MCT_NOP 0x0000
+#define ACB_CMD_MCT_TEST 0x0001
+#define ACB_CMD_HIC_TEST 0x0081
+#define ACB_CMD_INSERT 0x0002
+#define ACB_CMD_REMOVE 0x0003
+#define ACB_CMD_MCT_WRITE_VALUE 0x0004
+#define ACB_CMD_HIC_WRITE_VALUE 0x0084
+#define ACB_CMD_MCT_READ_VALUE 0x0005
+#define ACB_CMD_HIC_READ_VALUE 0x0085
+#define ACB_CMD_INIT_TX_RX 0x0086
+#define ACB_CMD_INIT_TRC_TIMERS 0x0006
+#define ACB_CMD_READ_TRC_STATUS 0x0007
+#define ACB_CMD_CHANGE_JOIN_STATE 0x0008
+#define ACB_CMD_RESERVED_9 0x0009
+#define ACB_CMD_RESERVED_A 0x000A
+#define ACB_CMD_RESERVED_B 0x000B
+#define ACB_CMD_RESERVED_C 0x000C
+#define ACB_CMD_RESERVED_D 0x000D
+#define ACB_CMD_RESERVED_E 0x000E
+#define ACB_CMD_RESERVED_F 0x000F
+
+#define TRC_MAC_REGISTERS_TEST 0x0000
+#define TRC_INTERNAL_LOOPBACK 0x0001
+#define TRC_TRI_LOOPBACK 0x0002
+#define TRC_INTERNAL_ROM_TEST 0x0003
+#define TRC_LOBE_MEDIA_TEST 0x0004
+#define TRC_ANALOG_TEST 0x0005
+#define TRC_HOST_INTERFACE_REG_TEST 0x0003
+
+#define TEST_DMA_1 0x0000
+#define TEST_DMA_2 0x0001
+#define TEST_MCT_ROM 0x0002
+#define HIC_INTERNAL_DIAG 0x0003
+
+#define ABORT_TRANSMIT_PRIORITY_0 0x0001
+#define ABORT_TRANSMIT_PRIORITY_1 0x0002
+#define ABORT_TRANSMIT_PRIORITY_2 0x0004
+#define ABORT_TRANSMIT_PRIORITY_3 0x0008
+#define ABORT_TRANSMIT_PRIORITY_4 0x0010
+#define ABORT_TRANSMIT_PRIORITY_5 0x0020
+#define ABORT_TRANSMIT_PRIORITY_6 0x0040
+#define ABORT_TRANSMIT_PRIORITY_7 0x0080
+
+#define TX_PENDING_PRIORITY_0 0x0001
+#define TX_PENDING_PRIORITY_1 0x0002
+#define TX_PENDING_PRIORITY_2 0x0004
+#define TX_PENDING_PRIORITY_3 0x0008
+#define TX_PENDING_PRIORITY_4 0x0010
+#define TX_PENDING_PRIORITY_5 0x0020
+#define TX_PENDING_PRIORITY_6 0x0040
+#define TX_PENDING_PRIORITY_7 0x0080
+
+#define FCB_FRAME_LENGTH 0x100
+#define FCB_COMMAND_DONE 0x8000 /* FCB Word 0 */
+#define FCB_NOT_CHAIN_END 0x0000 /* FCB Word 1 */
+#define FCB_CHAIN_END 0x8000
+#define FCB_NO_WARNING 0x0000
+#define FCB_WARNING 0x4000
+#define FCB_INTERRUPT_DISABLE 0x0000
+#define FCB_INTERRUPT_ENABLE 0x2000
+
+#define FCB_ENABLE_IMA 0x0008
+#define FCB_ENABLE_TES 0x0004 /* Guarantee Tx before Int */
+#define FCB_ENABLE_TFS 0x0002 /* Post Tx Frame Status */
+#define FCB_ENABLE_NTC 0x0001 /* No Tx CRC */
+
+#define FCB_TX_STATUS_CR2 0x0004
+#define FCB_TX_STATUS_AR2 0x0008
+#define FCB_TX_STATUS_CR1 0x0040
+#define FCB_TX_STATUS_AR1 0x0080
+#define FCB_TX_AC_BITS (FCB_TX_STATUS_AR1+FCB_TX_STATUS_AR2+FCB_TX_STATUS_CR1+FCB_TX_STATUS_CR2)
+#define FCB_TX_STATUS_E 0x0100
+
+#define FCB_RX_STATUS_ANY_ERROR 0x0001
+#define FCB_RX_STATUS_FCS_ERROR 0x0002
+
+#define FCB_RX_STATUS_IA_MATCHED 0x0400
+#define FCB_RX_STATUS_IGA_BSGA_MATCHED 0x0500
+#define FCB_RX_STATUS_FA_MATCHED 0x0600
+#define FCB_RX_STATUS_BA_MATCHED 0x0700
+#define FCB_RX_STATUS_DA_MATCHED 0x0400
+#define FCB_RX_STATUS_SOURCE_ROUTING 0x0800
+
+#define BDB_BUFFER_SIZE 0x100
+#define BDB_NOT_CHAIN_END 0x0000
+#define BDB_CHAIN_END 0x8000
+#define BDB_NO_WARNING 0x0000
+#define BDB_WARNING 0x4000
+
+#define ERROR_COUNTERS_CHANGED 0x0001
+#define TI_NDIS_RING_STATUS_CHANGED 0x0002
+#define UNA_CHANGED 0x0004
+#define READY_TO_SEND_RQ_INIT 0x0008
+
+#define SCGB_ADDRESS_POINTER_FORMAT INTEL_ADDRESS_POINTER_FORMAT
+#define SCGB_DATA_FORMAT INTEL_DATA_FORMAT
+#define SCGB_MULTI_WORD_CONTROL 0
+#define SCGB_BURST_LENGTH 0x000E /* DMA Burst Length */
+
+#define SCGB_CONFIG (INTEL_ADDRESS_POINTER_FORMAT+INTEL_DATA_FORMAT+SCGB_BURST_LENGTH)
+
+#define ISCP_BLOCK_SIZE 0x0A
+#define RAM_SIZE 0x10000
+#define INIT_SYS_CONFIG_PTR_OFFSET (RAM_SIZE-ISCP_BLOCK_SIZE)
+#define SCGP_BLOCK_OFFSET 0
+
+#define SCLB_NOT_VALID 0x0000 /* Initially, SCLB not valid */
+#define SCLB_VALID 0x8000 /* Host tells TRC SCLB valid */
+#define SCLB_PROCESSED 0x0000 /* TRC says SCLB processed */
+#define SCLB_RESUME_CONTROL_NOT_VALID 0x0000 /* Initially, RC not valid */
+#define SCLB_RESUME_CONTROL_VALID 0x4000 /* Host tells TRC RC valid */
+#define SCLB_IACK_CODE_NOT_VALID 0x0000 /* Initially, IACK not valid */
+#define SCLB_IACK_CODE_VALID 0x2000 /* Host tells TRC IACK valid */
+#define SCLB_CMD_NOP 0x0000
+#define SCLB_CMD_REMOVE 0x0001
+#define SCLB_CMD_SUSPEND_ACB_CHAIN 0x0002
+#define SCLB_CMD_SET_INTERRUPT_MASK 0x0003
+#define SCLB_CMD_CLEAR_INTERRUPT_MASK 0x0004
+#define SCLB_CMD_RESERVED_5 0x0005
+#define SCLB_CMD_RESERVED_6 0x0006
+#define SCLB_CMD_RESERVED_7 0x0007
+#define SCLB_CMD_RESERVED_8 0x0008
+#define SCLB_CMD_RESERVED_9 0x0009
+#define SCLB_CMD_RESERVED_A 0x000A
+#define SCLB_CMD_RESERVED_B 0x000B
+#define SCLB_CMD_RESERVED_C 0x000C
+#define SCLB_CMD_RESERVED_D 0x000D
+#define SCLB_CMD_RESERVED_E 0x000E
+#define SCLB_CMD_RESERVED_F 0x000F
+
+#define SCLB_RC_ACB 0x0001 /* Action Command Block Chain */
+#define SCLB_RC_RES0 0x0002 /* Always Zero */
+#define SCLB_RC_RES1 0x0004 /* Always Zero */
+#define SCLB_RC_RES2 0x0008 /* Always Zero */
+#define SCLB_RC_RX_MAC_FCB 0x0010 /* RX_MAC_FCB Chain */
+#define SCLB_RC_RX_MAC_BDB 0x0020 /* RX_MAC_BDB Chain */
+#define SCLB_RC_RX_NON_MAC_FCB 0x0040 /* RX_NON_MAC_FCB Chain */
+#define SCLB_RC_RX_NON_MAC_BDB 0x0080 /* RX_NON_MAC_BDB Chain */
+#define SCLB_RC_TFCB0 0x0100 /* TX Priority 0 FCB Chain */
+#define SCLB_RC_TFCB1 0x0200 /* TX Priority 1 FCB Chain */
+#define SCLB_RC_TFCB2 0x0400 /* TX Priority 2 FCB Chain */
+#define SCLB_RC_TFCB3 0x0800 /* TX Priority 3 FCB Chain */
+#define SCLB_RC_TFCB4 0x1000 /* TX Priority 4 FCB Chain */
+#define SCLB_RC_TFCB5 0x2000 /* TX Priority 5 FCB Chain */
+#define SCLB_RC_TFCB6 0x4000 /* TX Priority 6 FCB Chain */
+#define SCLB_RC_TFCB7 0x8000 /* TX Priority 7 FCB Chain */
+
+#define SCLB_IMC_RES0 0x0001 /* */
+#define SCLB_IMC_MAC_TYPE_3 0x0002 /* MAC_ARC_INDICATE */
+#define SCLB_IMC_MAC_ERROR_COUNTERS 0x0004 /* */
+#define SCLB_IMC_RES1 0x0008 /* */
+#define SCLB_IMC_MAC_TYPE_2 0x0010 /* QUE_MAC_INDICATE */
+#define SCLB_IMC_TX_FRAME 0x0020 /* */
+#define SCLB_IMC_END_OF_TX_QUEUE 0x0040 /* */
+#define SCLB_IMC_NON_MAC_RX_RESOURCE 0x0080 /* */
+#define SCLB_IMC_MAC_RX_RESOURCE 0x0100 /* */
+#define SCLB_IMC_NON_MAC_RX_FRAME 0x0200 /* */
+#define SCLB_IMC_MAC_RX_FRAME 0x0400 /* */
+#define SCLB_IMC_TRC_FIFO_STATUS 0x0800 /* */
+#define SCLB_IMC_COMMAND_STATUS 0x1000 /* */
+#define SCLB_IMC_MAC_TYPE_1 0x2000 /* Self Removed */
+#define SCLB_IMC_TRC_INTRNL_TST_STATUS 0x4000 /* */
+#define SCLB_IMC_RES2 0x8000 /* */
+
+#define DMA_TRIGGER 0x0004
+#define FREQ_16MB_BIT 0x0010
+#define THDREN 0x0020
+#define CFG0_RSV1 0x0040
+#define CFG0_RSV2 0x0080
+#define ETREN 0x0100
+#define RX_OWN_BIT 0x0200
+#define RXATMAC 0x0400
+#define PROMISCUOUS_BIT 0x0800
+#define USETPT 0x1000
+#define SAVBAD_BIT 0x2000
+#define ONEQUE 0x4000
+#define NO_AUTOREMOVE 0x8000
+
+#define RX_FCB_AREA_8316 0x00000000
+#define RX_BUFF_AREA_8316 0x00000000
+
+#define TRC_POINTER(X) ((unsigned long)(X) - tp->ram_access)
+#define RX_FCB_TRC_POINTER(X) ((unsigned long)(X) - tp->ram_access + RX_FCB_AREA_8316)
+#define RX_BUFF_TRC_POINTER(X) ((unsigned long)(X) - tp->ram_access + RX_BUFF_AREA_8316)
+
+// Offset 0: MSR - Memory Select Register
+//
+#define r587_MSR 0x000 // Register Offset
+//#define MSR_RST 0x080 // LAN Controller Reset
+#define MSR_MENB 0x040 // Shared Memory Enable
+#define MSR_RA18 0x020 // Ram Address bit 18 (583, 584, 587)
+#define MSR_RA17 0x010 // Ram Address bit 17 (583, 584, 585/790)
+#define MSR_RA16 0x008 // Ram Address bit 16 (583, 584, 585/790)
+#define MSR_RA15 0x004 // Ram Address bit 15 (583, 584, 585/790)
+#define MSR_RA14 0x002 // Ram Address bit 14 (583, 584, 585/790)
+#define MSR_RA13 0x001 // Ram Address bit 13 (583, 584, 585/790)
+
+#define MSR_MASK 0x03F // Mask for Address bits RA18-RA13 (583, 584, 587)
+
+#define MSR 0x00
+#define IRR 0x04
+#define HWR 0x04
+#define LAAR 0x05
+#define IMCCR 0x05
+#define LAR0 0x08
+#define BDID 0x0E // Adapter ID byte register offset
+#define CSR 0x10
+#define PR 0x11
+
+#define MSR_RST 0x80
+#define MSR_MEMB 0x40
+#define MSR_0WS 0x20
+
+#define FORCED_16BIT_MODE 0x0002
+
+#define INTERFRAME_SPACING_16 0x0003 /* 6 bytes */
+#define INTERFRAME_SPACING_4 0x0001 /* 2 bytes */
+#define MULTICAST_ADDRESS_BIT 0x0010
+#define NON_SRC_ROUTING_BIT 0x0020
+
+#define LOOPING_MODE_MASK 0x0007
+
+/*
+ * Decode firmware defines.
+ */
+#define SWAP_BYTES(X) ((X & 0xff) << 8) | (X >> 8)
+#define WEIGHT_OFFSET 5
+#define TREE_SIZE_OFFSET 9
+#define TREE_OFFSET 11
+
+/* The Huffman Encoding Tree is constructed of these nodes. */
+typedef struct {
+ __u8 llink; /* Short version of above node. */
+ __u8 tag;
+ __u8 info; /* This node is used on decodes. */
+ __u8 rlink;
+} DECODE_TREE_NODE;
+
+#define ROOT 0 /* Branch value. */
+#define LEAF 0 /* Tag field value. */
+#define BRANCH 1 /* Tag field value. */
+
+/*
+ * Multicast Table Structure
+ */
+typedef struct {
+ __u8 address[6];
+ __u8 instance_count;
+} McTable;
+
+/*
+ * Fragment Descriptor Definition
+ */
+typedef struct {
+ __u8 *fragment_ptr;
+ __u32 fragment_length;
+} FragmentStructure;
+
+/*
+ * Data Buffer Structure Definition
+ */
+typedef struct {
+ __u32 fragment_count;
+ FragmentStructure fragment_list[MAXFRAGMENTS];
+} DataBufferStructure;
+
+#pragma pack(1)
+typedef struct {
+ __u8 IType;
+ __u8 ISubtype;
+} Interrupt_Status_Word;
+
+#pragma pack(1)
+typedef struct BDBlockType {
+ __u16 info; /* 02 */
+ __u32 trc_next_ptr; /* 06 */
+ __u32 trc_data_block_ptr; /* 10 */
+ __u16 buffer_length; /* 12 */
+
+ __u16 *data_block_ptr; /* 16 */
+ struct BDBlockType *next_ptr; /* 20 */
+ struct BDBlockType *back_ptr; /* 24 */
+ __u8 filler[8]; /* 32 */
+} BDBlock;
+
+#pragma pack(1)
+typedef struct FCBlockType {
+ __u16 frame_status; /* 02 */
+ __u16 info; /* 04 */
+ __u32 trc_next_ptr; /* 08 */
+ __u32 trc_bdb_ptr; /* 12 */
+ __u16 frame_length; /* 14 */
+
+ BDBlock *bdb_ptr; /* 18 */
+ struct FCBlockType *next_ptr; /* 22 */
+ struct FCBlockType *back_ptr; /* 26 */
+ __u16 memory_alloc; /* 28 */
+ __u8 filler[4]; /* 32 */
+
+} FCBlock;
+
+#pragma pack(1)
+typedef struct SBlockType{
+ __u8 Internal_Error_Count;
+ __u8 Line_Error_Count;
+ __u8 AC_Error_Count;
+ __u8 Burst_Error_Count;
+ __u8 RESERVED_COUNTER_0;
+ __u8 AD_TRANS_Count;
+ __u8 RCV_Congestion_Count;
+ __u8 Lost_FR_Error_Count;
+ __u8 FREQ_Error_Count;
+ __u8 FR_Copied_Error_Count;
+ __u8 RESERVED_COUNTER_1;
+ __u8 Token_Error_Count;
+
+ __u16 TI_NDIS_Ring_Status;
+ __u16 BCN_Type;
+ __u16 Error_Code;
+ __u16 SA_of_Last_AMP_SMP[3];
+ __u16 UNA[3];
+ __u16 Ucode_Version_Number;
+ __u16 Status_CHG_Indicate;
+ __u16 RESERVED_STATUS_0;
+} SBlock;
+
+#pragma pack(1)
+typedef struct ACBlockType {
+ __u16 cmd_done_status; /* 02 */
+ __u16 cmd_info; /* 04 */
+ __u32 trc_next_ptr; /* 08 */
+ __u16 cmd; /* 10 */
+ __u16 subcmd; /* 12 */
+ __u16 data_offset_lo; /* 14 */
+ __u16 data_offset_hi; /* 16 */
+
+ struct ACBlockType *next_ptr; /* 20 */
+
+ __u8 filler[12]; /* 32 */
+} ACBlock;
+
+#define NUM_OF_INTERRUPTS 0x20
+
+#pragma pack(1)
+typedef struct {
+ Interrupt_Status_Word IStatus[NUM_OF_INTERRUPTS];
+} ISBlock;
+
+#pragma pack(1)
+typedef struct {
+ __u16 valid_command; /* 02 */
+ __u16 iack_code; /* 04 */
+ __u16 resume_control; /* 06 */
+ __u16 int_mask_control; /* 08 */
+ __u16 int_mask_state; /* 10 */
+
+ __u8 filler[6]; /* 16 */
+} SCLBlock;
+
+#pragma pack(1)
+typedef struct
+{
+ __u16 config; /* 02 */
+ __u32 trc_sclb_ptr; /* 06 */
+ __u32 trc_acb_ptr; /* 10 */
+ __u32 trc_isb_ptr; /* 14 */
+ __u16 isbsiz; /* 16 */
+
+ SCLBlock *sclb_ptr; /* 20 */
+ ACBlock *acb_ptr; /* 24 */
+ ISBlock *isb_ptr; /* 28 */
+
+ __u16 Non_Mac_Rx_Bdbs; /* 30 DEBUG */
+ __u8 filler[2]; /* 32 */
+
+} SCGBlock;
+
+#pragma pack(1)
+typedef struct
+{
+ __u32 trc_scgb_ptr;
+ SCGBlock *scgb_ptr;
+} ISCPBlock;
+#pragma pack()
+
+typedef struct net_local {
+ ISCPBlock *iscpb_ptr;
+ SCGBlock *scgb_ptr;
+ SCLBlock *sclb_ptr;
+ ISBlock *isb_ptr;
+
+ ACBlock *acb_head;
+ ACBlock *acb_curr;
+ ACBlock *acb_next;
+
+ __u8 adapter_name[12];
+
+ __u16 num_rx_bdbs [NUM_RX_QS_USED];
+ __u16 num_rx_fcbs [NUM_RX_QS_USED];
+
+ __u16 num_tx_bdbs [NUM_TX_QS_USED];
+ __u16 num_tx_fcbs [NUM_TX_QS_USED];
+
+ __u16 num_of_tx_buffs;
+
+ __u16 tx_buff_size [NUM_TX_QS_USED];
+ __u16 tx_buff_used [NUM_TX_QS_USED];
+ __u16 tx_queue_status [NUM_TX_QS_USED];
+
+ FCBlock *tx_fcb_head[NUM_TX_QS_USED];
+ FCBlock *tx_fcb_curr[NUM_TX_QS_USED];
+ FCBlock *tx_fcb_end[NUM_TX_QS_USED];
+ BDBlock *tx_bdb_head[NUM_TX_QS_USED];
+ __u16 *tx_buff_head[NUM_TX_QS_USED];
+ __u16 *tx_buff_end[NUM_TX_QS_USED];
+ __u16 *tx_buff_curr[NUM_TX_QS_USED];
+ __u16 num_tx_fcbs_used[NUM_TX_QS_USED];
+
+ FCBlock *rx_fcb_head[NUM_RX_QS_USED];
+ FCBlock *rx_fcb_curr[NUM_RX_QS_USED];
+ BDBlock *rx_bdb_head[NUM_RX_QS_USED];
+ BDBlock *rx_bdb_curr[NUM_RX_QS_USED];
+ BDBlock *rx_bdb_end[NUM_RX_QS_USED];
+ __u16 *rx_buff_head[NUM_RX_QS_USED];
+ __u16 *rx_buff_end[NUM_RX_QS_USED];
+
+ __u32 *ptr_local_ring_num;
+
+ __u32 sh_mem_used;
+
+ __u16 page_offset_mask;
+
+ __u16 authorized_function_classes;
+ __u16 authorized_access_priority;
+
+ __u16 num_acbs;
+ __u16 num_acbs_used;
+ __u16 acb_pending;
+
+ __u16 current_isb_index;
+
+ __u8 monitor_state;
+ __u8 monitor_state_ready;
+ __u16 ring_status;
+ __u8 ring_status_flags;
+ __u8 current_ring_status;
+ __u8 state;
+
+ __u8 join_state;
+
+ __u32 *ptr_una;
+ __u32 *ptr_bcn_type;
+ __u32 *ptr_tx_fifo_underruns;
+ __u32 *ptr_rx_fifo_underruns;
+ __u32 *ptr_rx_fifo_overruns;
+ __u32 *ptr_tx_fifo_overruns;
+ __u32 *ptr_tx_fcb_overruns;
+ __u32 *ptr_rx_fcb_overruns;
+ __u32 *ptr_tx_bdb_overruns;
+ __u32 *ptr_rx_bdb_overruns;
+
+ __u16 receive_queue_number;
+
+ __u8 rx_fifo_overrun_count;
+ __u8 tx_fifo_overrun_count;
+
+ __u16 adapter_flags;
+ __u16 adapter_flags1;
+ __u16 *misc_command_data;
+ __u16 max_packet_size;
+
+ __u16 config_word0;
+ __u16 config_word1;
+
+ __u8 trc_mask;
+
+ __u16 source_ring_number;
+ __u16 target_ring_number;
+
+ __u16 microcode_version;
+
+ __u16 bic_type;
+ __u16 nic_type;
+ __u16 board_id;
+
+ __u16 rom_size;
+ __u32 rom_base;
+ __u16 ram_size;
+ __u16 ram_usable;
+ __u32 ram_base;
+ __u32 ram_access;
+
+ __u16 extra_info;
+ __u16 mode_bits;
+ __u16 media_menu;
+ __u16 media_type;
+ __u16 adapter_bus;
+
+ __u16 status;
+ __u16 receive_mask;
+
+ __u16 group_address_0;
+ __u16 group_address[2];
+ __u16 functional_address_0;
+ __u16 functional_address[2];
+ __u16 bitwise_group_address[2];
+
+ __u8 *ptr_ucode;
+
+ __u8 cleanup;
+
+ struct sk_buff_head SendSkbQueue;
+ __u16 QueueSkb;
+
+ struct tr_statistics MacStat; /* MAC statistics structure */
+} NET_LOCAL;
+
+/************************************
+ * SNMP-ON-BOARD Agent Link Structure
+ ************************************/
+
+typedef struct {
+ __u8 LnkSigStr[12]; /* signature string "SmcLinkTable" */
+ __u8 LnkDrvTyp; /* 1=Redbox ODI, 2=ODI DOS, 3=ODI OS/2, 4=NDIS DOS */
+ __u8 LnkFlg; /* 0 if no agent linked, 1 if agent linked */
+ void *LnkNfo; /* routine which returns pointer to NIC info */
+ void *LnkAgtRcv; /* pointer to agent receive trap entry */
+ void *LnkAgtXmt; /* pointer to agent transmit trap
+entry */
+void *LnkGet; /* pointer to NIC receive data
+copy routine */
+ void *LnkSnd; /* pointer to NIC send routine
+*/
+ void *LnkRst; /* pointer to NIC driver reset
+routine */
+ void *LnkMib; /* pointer to MIB data base */
+ void *LnkMibAct; /* pointer to MIB action routine list */
+ __u16 LnkCntOffset; /* offset to error counters */
+ __u16 LnkCntNum; /* number of error counters */
+ __u16 LnkCntSize; /* size of error counters i.e. 32 = 32 bits */
+ void *LnkISR; /* pointer to interrupt vector */
+ __u8 LnkFrmTyp; /* 1=Ethernet, 2=Token Ring */
+ __u8 LnkDrvVer1 ; /* driver major version */
+ __u8 LnkDrvVer2 ; /* driver minor version */
+} AgentLink;
+
+/*
+ * Definitions for pcm_card_flags(bit_mapped)
+ */
+#define REG_COMPLETE 0x0001
+#define INSERTED 0x0002
+#define PCC_INSERTED 0x0004 /* 1=currently inserted, 0=cur removed */
+
+/*
+ * Adapter RAM test patterns
+ */
+#define RAM_PATTERN_1 0x55AA
+#define RAM_PATTERN_2 0x9249
+#define RAM_PATTERN_3 0xDB6D
+
+/*
+ * definitions for RAM test
+ */
+#define ROM_SIGNATURE 0xAA55
+#define MIN_ROM_SIZE 0x2000
+
+/*
+ * Return Codes
+ */
+#define SUCCESS 0x0000
+#define ADAPTER_AND_CONFIG 0x0001
+#define ADAPTER_NO_CONFIG 0x0002
+#define NOT_MY_INTERRUPT 0x0003
+#define FRAME_REJECTED 0x0004
+#define EVENTS_DISABLED 0x0005
+#define OUT_OF_RESOURCES 0x0006
+#define INVALID_PARAMETER 0x0007
+#define INVALID_FUNCTION 0x0008
+#define INITIALIZE_FAILED 0x0009
+#define CLOSE_FAILED 0x000A
+#define MAX_COLLISIONS 0x000B
+#define NO_SUCH_DESTINATION 0x000C
+#define BUFFER_TOO_SMALL_ERROR 0x000D
+#define ADAPTER_CLOSED 0x000E
+#define UCODE_NOT_PRESENT 0x000F
+#define FIFO_UNDERRUN 0x0010
+#define DEST_OUT_OF_RESOURCES 0x0011
+#define ADAPTER_NOT_INITIALIZED 0x0012
+#define PENDING 0x0013
+#define UCODE_PRESENT 0x0014
+#define NOT_INIT_BY_BRIDGE 0x0015
+
+#define OPEN_FAILED 0x0080
+#define HARDWARE_FAILED 0x0081
+#define SELF_TEST_FAILED 0x0082
+#define RAM_TEST_FAILED 0x0083
+#define RAM_CONFLICT 0x0084
+#define ROM_CONFLICT 0x0085
+#define UNKNOWN_ADAPTER 0x0086
+#define CONFIG_ERROR 0x0087
+#define CONFIG_WARNING 0x0088
+#define NO_FIXED_CNFG 0x0089
+#define EEROM_CKSUM_ERROR 0x008A
+#define ROM_SIGNATURE_ERROR 0x008B
+#define ROM_CHECKSUM_ERROR 0x008C
+#define ROM_SIZE_ERROR 0x008D
+#define UNSUPPORTED_NIC_CHIP 0x008E
+#define NIC_REG_ERROR 0x008F
+#define BIC_REG_ERROR 0x0090
+#define MICROCODE_TEST_ERROR 0x0091
+#define LOBE_MEDIA_TEST_FAILED 0x0092
+
+#define ADAPTER_FOUND_LAN_CORRUPT 0x009B
+
+#define ADAPTER_NOT_FOUND 0xFFFF
+
+#define ILLEGAL_FUNCTION INVALID_FUNCTION
+
+/* Errors */
+#define IO_BASE_INVALID 0x0001
+#define IO_BASE_RANGE 0x0002
+#define IRQ_INVALID 0x0004
+#define IRQ_RANGE 0x0008
+#define RAM_BASE_INVALID 0x0010
+#define RAM_BASE_RANGE 0x0020
+#define RAM_SIZE_RANGE 0x0040
+#define MEDIA_INVALID 0x0800
+
+/* Warnings */
+#define IRQ_MISMATCH 0x0080
+#define RAM_BASE_MISMATCH 0x0100
+#define RAM_SIZE_MISMATCH 0x0200
+#define BUS_MODE_MISMATCH 0x0400
+
+#define RX_CRC_ERROR 0x01
+#define RX_ALIGNMENT_ERROR 0x02
+#define RX_HW_FAILED 0x80
+
+/*
+ * Definitions for the field RING_STATUS_FLAGS
+ */
+#define RING_STATUS_CHANGED 0X01
+#define MONITOR_STATE_CHANGED 0X02
+#define JOIN_STATE_CHANGED 0X04
+
+/*
+ * Definitions for the field JOIN_STATE
+ */
+#define JS_BYPASS_STATE 0x00
+#define JS_LOBE_TEST_STATE 0x01
+#define JS_DETECT_MONITOR_PRESENT_STATE 0x02
+#define JS_AWAIT_NEW_MONITOR_STATE 0x03
+#define JS_DUPLICATE_ADDRESS_TEST_STATE 0x04
+#define JS_NEIGHBOR_NOTIFICATION_STATE 0x05
+#define JS_REQUEST_INITIALIZATION_STATE 0x06
+#define JS_JOIN_COMPLETE_STATE 0x07
+#define JS_BYPASS_WAIT_STATE 0x08
+
+/*
+ * Definitions for the field MONITOR_STATE
+ */
+#define MS_MONITOR_FSM_INACTIVE 0x00
+#define MS_REPEAT_BEACON_STATE 0x01
+#define MS_REPEAT_CLAIM_TOKEN_STATE 0x02
+#define MS_TRANSMIT_CLAIM_TOKEN_STATE 0x03
+#define MS_STANDBY_MONITOR_STATE 0x04
+#define MS_TRANSMIT_BEACON_STATE 0x05
+#define MS_ACTIVE_MONITOR_STATE 0x06
+#define MS_TRANSMIT_RING_PURGE_STATE 0x07
+#define MS_BEACON_TEST_STATE 0x09
+
+/*
+ * Definitions for the bit-field RING_STATUS
+ */
+#define SIGNAL_LOSS 0x8000
+#define HARD_ERROR 0x4000
+#define SOFT_ERROR 0x2000
+#define TRANSMIT_BEACON 0x1000
+#define LOBE_WIRE_FAULT 0x0800
+#define AUTO_REMOVAL_ERROR 0x0400
+#define REMOVE_RECEIVED 0x0100
+#define COUNTER_OVERFLOW 0x0080
+#define SINGLE_STATION 0x0040
+#define RING_RECOVERY 0x0020
+
+/*
+ * Definitions for the field BUS_TYPE
+ */
+#define AT_BUS 0x00
+#define MCA_BUS 0x01
+#define EISA_BUS 0x02
+#define PCI_BUS 0x03
+#define PCMCIA_BUS 0x04
+
+/*
+ * Definitions for adapter_flags
+ */
+#define RX_VALID_LOOKAHEAD 0x0001
+#define FORCED_16BIT_MODE 0x0002
+#define ADAPTER_DISABLED 0x0004
+#define TRANSMIT_CHAIN_INT 0x0008
+#define EARLY_RX_FRAME 0x0010
+#define EARLY_TX 0x0020
+#define EARLY_RX_COPY 0x0040
+#define USES_PHYSICAL_ADDR 0x0080 /* Rsvd for DEC PCI and 9232 */
+#define NEEDS_PHYSICAL_ADDR 0x0100 /* Reserved*/
+#define RX_STATUS_PENDING 0x0200
+#define ERX_DISABLED 0x0400 /* EARLY_RX_ENABLE rcv_mask */
+#define ENABLE_TX_PENDING 0x0800
+#define ENABLE_RX_PENDING 0x1000
+#define PERM_CLOSE 0x2000
+#define IO_MAPPED 0x4000 /* IOmapped bus interface 795 */
+#define ETX_DISABLED 0x8000
+
+
+/*
+ * Definitions for adapter_flags1
+ */
+#define TX_PHY_RX_VIRT 0x0001
+#define NEEDS_HOST_RAM 0x0002
+#define NEEDS_MEDIA_TYPE 0x0004
+#define EARLY_RX_DONE 0x0008
+#define PNP_BOOT_BIT 0x0010 /* activates PnP & config on power-up */
+ /* clear => regular PnP operation */
+#define PNP_ENABLE 0x0020 /* regular PnP operation clear => */
+ /* no PnP, overrides PNP_BOOT_BIT */
+#define SATURN_ENABLE 0x0040
+
+#define ADAPTER_REMOVABLE 0x0080 /* adapter is hot swappable */
+#define TX_PHY 0x0100 /* Uses physical address for tx bufs */
+#define RX_PHY 0x0200 /* Uses physical address for rx bufs */
+#define TX_VIRT 0x0400 /* Uses virtual addr for tx bufs */
+#define RX_VIRT 0x0800
+#define NEEDS_SERVICE 0x1000
+
+/*
+ * Adapter Status Codes
+ */
+#define OPEN 0x0001
+#define INITIALIZED 0x0002
+#define CLOSED 0x0003
+#define FAILED 0x0005
+#define NOT_INITIALIZED 0x0006
+#define IO_CONFLICT 0x0007
+#define CARD_REMOVED 0x0008
+#define CARD_INSERTED 0x0009
+
+/*
+ * Mode Bit Definitions
+ */
+#define INTERRUPT_STATUS_BIT 0x8000 /* PC Interrupt Line: 0 = Not Enabled */
+#define BOOT_STATUS_MASK 0x6000 /* Mask to isolate BOOT_STATUS */
+#define BOOT_INHIBIT 0x0000 /* BOOT_STATUS is 'inhibited' */
+#define BOOT_TYPE_1 0x2000 /* Unused BOOT_STATUS value */
+#define BOOT_TYPE_2 0x4000 /* Unused BOOT_STATUS value */
+#define BOOT_TYPE_3 0x6000 /* Unused BOOT_STATUS value */
+#define ZERO_WAIT_STATE_MASK 0x1800 /* Mask to isolate Wait State flags */
+#define ZERO_WAIT_STATE_8_BIT 0x1000 /* 0 = Disabled (Inserts Wait States) */
+#define ZERO_WAIT_STATE_16_BIT 0x0800 /* 0 = Disabled (Inserts Wait States) */
+#define LOOPING_MODE_MASK 0x0007
+#define LOOPBACK_MODE_0 0x0000
+#define LOOPBACK_MODE_1 0x0001
+#define LOOPBACK_MODE_2 0x0002
+#define LOOPBACK_MODE_3 0x0003
+#define LOOPBACK_MODE_4 0x0004
+#define LOOPBACK_MODE_5 0x0005
+#define LOOPBACK_MODE_6 0x0006
+#define LOOPBACK_MODE_7 0x0007
+#define AUTO_MEDIA_DETECT 0x0008
+#define MANUAL_CRC 0x0010
+#define EARLY_TOKEN_REL 0x0020 /* Early Token Release for Token Ring */
+#define UMAC 0x0040
+#define UTP2_PORT 0x0080 /* For 8216T2, 0=port A, 1=Port B. */
+#define BNC_10BT_INTERFACE 0x0600 /* BNC and UTP current media set */
+#define UTP_INTERFACE 0x0500 /* Ethernet UTP Only. */
+#define BNC_INTERFACE 0x0400
+#define AUI_INTERFACE 0x0300
+#define AUI_10BT_INTERFACE 0x0200
+#define STARLAN_10_INTERFACE 0x0100
+#define INTERFACE_TYPE_MASK 0x0700
+
+/*
+ * Media Type Bit Definitions
+ *
+ * legend: TP = Twisted Pair
+ * STP = Shielded twisted pair
+ * UTP = Unshielded twisted pair
+ */
+
+#define CNFG_MEDIA_TYPE_MASK 0x001e /* POS Register 3 Mask */
+
+#define MEDIA_S10 0x0000 /* Ethernet adapter, TP. */
+#define MEDIA_AUI_UTP 0x0001 /* Ethernet adapter, AUI/UTP media */
+#define MEDIA_BNC 0x0002 /* Ethernet adapter, BNC media. */
+#define MEDIA_AUI 0x0003 /* Ethernet Adapter, AUI media. */
+#define MEDIA_STP_16 0x0004 /* TokenRing adap, 16Mbit STP. */
+#define MEDIA_STP_4 0x0005 /* TokenRing adap, 4Mbit STP. */
+#define MEDIA_UTP_16 0x0006 /* TokenRing adap, 16Mbit UTP. */
+#define MEDIA_UTP_4 0x0007 /* TokenRing adap, 4Mbit UTP. */
+#define MEDIA_UTP 0x0008 /* Ethernet adapter, UTP media (no AUI)
+*/
+#define MEDIA_BNC_UTP 0x0010 /* Ethernet adapter, BNC/UTP media */
+#define MEDIA_UTPFD 0x0011 /* Ethernet adapter, TP full duplex */
+#define MEDIA_UTPNL 0x0012 /* Ethernet adapter, TP with link integrity test disabled */
+#define MEDIA_AUI_BNC 0x0013 /* Ethernet adapter, AUI/BNC media */
+#define MEDIA_AUI_BNC_UTP 0x0014 /* Ethernet adapter, AUI_BNC/UTP */
+#define MEDIA_UTPA 0x0015 /* Ethernet UTP-10Mbps Ports A */
+#define MEDIA_UTPB 0x0016 /* Ethernet UTP-10Mbps Ports B */
+#define MEDIA_STP_16_UTP_16 0x0017 /* Token Ring STP-16Mbps/UTP-16Mbps */
+#define MEDIA_STP_4_UTP_4 0x0018 /* Token Ring STP-4Mbps/UTP-4Mbps */
+
+#define MEDIA_STP100_UTP100 0x0020 /* Ethernet STP-100Mbps/UTP-100Mbps */
+#define MEDIA_UTP100FD 0x0021 /* Ethernet UTP-100Mbps, full duplex */
+#define MEDIA_UTP100 0x0022 /* Ethernet UTP-100Mbps */
+
+
+#define MEDIA_UNKNOWN 0xFFFF /* Unknown adapter/media type */
+
+/*
+ * Definitions for the field:
+ * media_type2
+ */
+#define MEDIA_TYPE_MII 0x0001
+#define MEDIA_TYPE_UTP 0x0002
+#define MEDIA_TYPE_BNC 0x0004
+#define MEDIA_TYPE_AUI 0x0008
+#define MEDIA_TYPE_S10 0x0010
+#define MEDIA_TYPE_AUTO_SENSE 0x1000
+#define MEDIA_TYPE_AUTO_DETECT 0x4000
+#define MEDIA_TYPE_AUTO_NEGOTIATE 0x8000
+
+/*
+ * Definitions for the field:
+ * line_speed
+ */
+#define LINE_SPEED_UNKNOWN 0x0000
+#define LINE_SPEED_4 0x0001
+#define LINE_SPEED_10 0x0002
+#define LINE_SPEED_16 0x0004
+#define LINE_SPEED_100 0x0008
+#define LINE_SPEED_T4 0x0008 /* 100BaseT4 aliased for 9332BVT */
+#define LINE_SPEED_FULL_DUPLEX 0x8000
+
+/*
+ * Definitions for the field:
+ * bic_type (Bus interface chip type)
+ */
+#define BIC_NO_CHIP 0x0000 /* Bus interface chip not implemented */#define BIC_583_CHIP 0x0001 /* 83C583 bus interface chip */
+#define BIC_584_CHIP 0x0002 /* 83C584 bus interface chip */
+#define BIC_585_CHIP 0x0003 /* 83C585 bus interface chip */
+#define BIC_593_CHIP 0x0004 /* 83C593 bus interface chip */
+#define BIC_594_CHIP 0x0005 /* 83C594 bus interface chip */
+#define BIC_564_CHIP 0x0006 /* PCMCIA Bus interface chip */
+#define BIC_790_CHIP 0x0007 /* 83C790 bus i-face/Ethernet NIC chip */
+#define BIC_571_CHIP 0x0008 /* 83C571 EISA bus master i-face */
+#define BIC_587_CHIP 0x0009 /* Token Ring AT bus master i-face */
+#define BIC_574_CHIP 0x0010 /* FEAST bus interface chip */
+#define BIC_8432_CHIP 0x0011 /* 8432 bus i-face/Ethernet NIC(DEC PCI) */
+#define BIC_9332_CHIP 0x0012 /* 9332 bus i-face/100Mbps Ether NIC(DEC PCI) */
+#define BIC_8432E_CHIP 0x0013 /* 8432 Enhanced bus iface/Ethernet NIC(DEC) */
+#define BIC_EPIC100_CHIP 0x0014 /* EPIC/100 10/100 Mbps Ethernet BIC/NIC */
+#define BIC_C94_CHIP 0x0015 /* 91C94 bus i-face in PCMCIA mode */
+#define BIC_X8020_CHIP 0x0016 /* Xilinx PCMCIA multi-func i-face */
+
+/*
+ * Definitions for the field:
+ * nic_type (Bus interface chip type)
+ */
+#define NIC_UNK_CHIP 0x0000 /* Unknown NIC chip */
+#define NIC_8390_CHIP 0x0001 /* DP8390 Ethernet NIC */
+#define NIC_690_CHIP 0x0002 /* 83C690 Ethernet NIC */
+#define NIC_825_CHIP 0x0003 /* 83C825 Token Ring NIC */
+/* #define NIC_???_CHIP 0x0004 */ /* Not used */
+/* #define NIC_???_CHIP 0x0005 */ /* Not used */
+/* #define NIC_???_CHIP 0x0006 */ /* Not used */
+#define NIC_790_CHIP 0x0007 /* 83C790 bus i-face/Ethernet NIC chip */
+#define NIC_C100_CHIP 0x0010 /* FEAST 100Mbps Ethernet NIC */
+#define NIC_8432_CHIP 0x0011 /* 8432 bus i-face/Ethernet NIC(DEC PCI) */
+#define NIC_9332_CHIP 0x0012 /* 9332 bus i-face/100Mbps Ether NIC(DEC PCI) */
+#define NIC_8432E_CHIP 0x0013 /* 8432 enhanced bus iface/Ethernet NIC(DEC) */
+#define NIC_EPIC100_CHIP 0x0014 /* EPIC/100 10/100 Mbps Ethernet BIC/NIC */
+#define NIC_C94_CHIP 0x0015 /* 91C94 PC Card with multi func */
+
+/*
+ * Definitions for the field:
+ * adapter_type The adapter_type field describes the adapter/bus
+ * configuration.
+ */
+#define BUS_UNK_TYPE 0x0000 /* */
+#define BUS_ISA16_TYPE 0x0001 /* 16 bit adap in 16 bit (E)ISA slot */
+#define BUS_ISA8_TYPE 0x0002 /* 8/16b adap in 8 bit XT/(E)ISA slot */
+#define BUS_MCA_TYPE 0x0003 /* Micro Channel adapter */#define BUS_EISA32M_TYPE 0x0004 /* EISA 32 bit bus master adapter */#define BUS_EISA32S_TYPE 0x0005 /* EISA 32 bit bus slave adapter */#define BUS_PCMCIA_TYPE 0x0006 /* PCMCIA adapter */
+#define BUS_PCI_TYPE 0x0007 /* PCI bus */
+
+/*
+ * Receive Mask definitions
+ */
+#define ACCEPT_MULTICAST 0x0001
+#define ACCEPT_BROADCAST 0x0002
+#define PROMISCUOUS_MODE 0x0004
+#define ACCEPT_SOURCE_ROUTING 0x0008
+#define ACCEPT_ERR_PACKETS 0x0010
+#define ACCEPT_ATT_MAC_FRAMES 0x0020
+#define ACCEPT_MULTI_PROM 0x0040
+#define TRANSMIT_ONLY 0x0080
+#define ACCEPT_EXT_MAC_FRAMES 0x0100
+#define EARLY_RX_ENABLE 0x0200
+#define PKT_SIZE_NOT_NEEDED 0x0400
+#define ACCEPT_SOURCE_ROUTING_SPANNING 0x0808
+
+#define ACCEPT_ALL_MAC_FRAMES 0x0120
+
+/*
+ * config_mode defs
+ */
+#define STORE_EEROM 0x0001 /* Store config in EEROM. */
+#define STORE_REGS 0x0002 /* Store config in register set. */
+
+/*
+ * equates for lmac_flags in adapter structure (Ethernet)
+ */
+#define MEM_DISABLE 0x0001
+#define RX_STATUS_POLL 0x0002
+#define USE_RE_BIT 0x0004
+/*#define RESERVED 0x0008 */
+/*#define RESERVED 0x0010 */
+/*#define RESERVED 0x0020 */
+/*#define RESERVED 0x0040 */
+/*#define RESERVED 0x0080 */
+/*#define RESERVED 0x0100 */
+/*#define RESERVED 0x0200 */
+/*#define RESERVED 0x0400 */
+/*#define RESERVED 0x0800 */
+/*#define RESERVED 0x1000 */
+/*#define RESERVED 0x2000 */
+/*#define RESERVED 0x4000 */
+/*#define RESERVED 0x8000 */
+
+/* media_opts & media_set Fields bit defs for Ethernet ... */
+#define MED_OPT_BNC 0x01
+#define MED_OPT_UTP 0x02
+#define MED_OPT_AUI 0x04
+#define MED_OPT_10MB 0x08
+#define MED_OPT_100MB 0x10
+#define MED_OPT_S10 0x20
+
+/* media_opts & media_set Fields bit defs for Token Ring ... */
+#define MED_OPT_4MB 0x08
+#define MED_OPT_16MB 0x10
+#define MED_OPT_STP 0x40
+
+#define MAX_8023_SIZE 1500 /* Max 802.3 size of frame. */
+#define DEFAULT_ERX_VALUE 4 /* Number of 16-byte blocks for 790B early Rx. */
+#define DEFAULT_ETX_VALUE 32 /* Number of bytes for 790B early Tx. */#define DEFAULT_TX_RETRIES 3 /* Number of transmit retries */
+#define LPBK_FRAME_SIZE 1024 /* Default loopback frame for Rx calibration test. */
+#define MAX_LOOKAHEAD_SIZE 252 /* Max lookahead size for ethernet. */
+
+#define RW_MAC_STATE 0x1101
+#define RW_SA_OF_LAST_AMP_OR_SMP 0x2803
+#define RW_PHYSICAL_DROP_NUMBER 0x3B02
+#define RW_UPSTREAM_NEIGHBOR_ADDRESS 0x3E03
+#define RW_PRODUCT_INSTANCE_ID 0x4B09
+
+#define RW_TRC_STATUS_BLOCK 0x5412
+
+#define RW_MAC_ERROR_COUNTERS_NO_CLEAR 0x8006
+#define RW_MAC_ERROR_COUNTER_CLEAR 0x7A06
+#define RW_CONFIG_REGISTER_0 0xA001
+#define RW_CONFIG_REGISTER_1 0xA101
+#define RW_PRESCALE_TIMER_THRESHOLD 0xA201
+#define RW_TPT_THRESHOLD 0xA301
+#define RW_TQP_THRESHOLD 0xA401
+#define RW_TNT_THRESHOLD 0xA501
+#define RW_TBT_THRESHOLD 0xA601
+#define RW_TSM_THRESHOLD 0xA701
+#define RW_TAM_THRESHOLD 0xA801
+#define RW_TBR_THRESHOLD 0xA901
+#define RW_TER_THRESHOLD 0xAA01
+#define RW_TGT_THRESHOLD 0xAB01
+#define RW_THT_THRESHOLD 0xAC01
+#define RW_TRR_THRESHOLD 0xAD01
+#define RW_TVX_THRESHOLD 0xAE01
+#define RW_INDIVIDUAL_MAC_ADDRESS 0xB003
+
+#define RW_INDIVIDUAL_GROUP_ADDRESS 0xB303 /* all of group addr */
+#define RW_INDIVIDUAL_GROUP_ADDR_WORD_0 0xB301 /* 1st word of group addr */
+#define RW_INDIVIDUAL_GROUP_ADDR 0xB402 /* 2nd-3rd word of group addr */
+#define RW_FUNCTIONAL_ADDRESS 0xB603 /* all of functional addr */
+#define RW_FUNCTIONAL_ADDR_WORD_0 0xB601 /* 1st word of func addr */
+#define RW_FUNCTIONAL_ADDR 0xB702 /* 2nd-3rd word func addr */
+
+#define RW_BIT_SIGNIFICANT_GROUP_ADDR 0xB902
+#define RW_SOURCE_RING_BRIDGE_NUMBER 0xBB01
+#define RW_TARGET_RING_NUMBER 0xBC01
+
+#define RW_HIC_INTERRUPT_MASK 0xC601
+
+#define SOURCE_ROUTING_SPANNING_BITS 0x00C0 /* Spanning Tree Frames */
+#define SOURCE_ROUTING_EXPLORER_BIT 0x0040 /* Explorer and Single Route */
+
+ /* write */
+
+#define CSR_MSK_ALL 0x80 // Bic 587 Only
+#define CSR_MSKTINT 0x20
+#define CSR_MSKCBUSY 0x10
+#define CSR_CLRTINT 0x08
+#define CSR_CLRCBUSY 0x04
+#define CSR_WCSS 0x02
+#define CSR_CA 0x01
+
+ /* read */
+
+#define CSR_TINT 0x20
+#define CSR_CINT 0x10
+#define CSR_TSTAT 0x08
+#define CSR_CSTAT 0x04
+#define CSR_FAULT 0x02
+#define CSR_CBUSY 0x01
+
+#define LAAR_MEM16ENB 0x80
+#define Zws16 0x20
+
+#define IRR_IEN 0x80
+#define Zws8 0x01
+
+#define IMCCR_EIL 0x04
+
+typedef struct {
+ __u8 ac; /* Access Control */
+ __u8 fc; /* Frame Control */
+ __u8 da[6]; /* Dest Addr */
+ __u8 sa[6]; /* Source Addr */
+
+ __u16 vl; /* Vector Length */
+ __u8 dc_sc; /* Dest/Source Class */
+ __u8 vc; /* Vector Code */
+ } MAC_HEADER;
+
+#define MAX_SUB_VECTOR_INFO (RX_DATA_BUFFER_SIZE - sizeof(MAC_HEADER) - 2)
+
+typedef struct
+ {
+ __u8 svl; /* Sub-vector Length */
+ __u8 svi; /* Sub-vector Code */
+ __u8 svv[MAX_SUB_VECTOR_INFO]; /* Sub-vector Info */
+ } MAC_SUB_VECTOR;
+
+#endif /* __KERNEL__ */
+#endif /* __LINUX_SMCTR_H */
--- /dev/null
+/*
+ * The firmware this driver downloads into the tokenring card is a
+ * seperate program and is not GPL'd source code, even though the Linux
+ * side driver and the routine that loads this data into the card are.
+ *
+ * This firmware is licensed to you strictly for use in conjunction
+ * with the use of SMC TokenRing adapters. There is no waranty
+ * expressed or implied about its fitness for any purpose.
+ */
+
+/* smctr_firmware.h: SMC TokenRing driver firmware dump for Linux.
+ *
+ * Notes:
+ * - This is an 8K binary image. (MCT.BIN v6.3C1 03/01/95)
+ *
+ * Authors:
+ * - Jay Schulist <jschlst@turbolinux.com>
+ */
+
+#include <linux/config.h>
+
+#if defined(CONFIG_SMCTR) || defined(CONFIG_SMCTR_MODULE)
+
+unsigned char smctr_code[] = {
+ 0x0BC, 0x01D, 0x012, 0x03B, 0x063, 0x0B4, 0x0E9, 0x000,
+ 0x000, 0x01F, 0x000, 0x001, 0x001, 0x000, 0x002, 0x005,
+ 0x001, 0x000, 0x006, 0x003, 0x001, 0x000, 0x004, 0x009,
+ 0x001, 0x000, 0x00A, 0x007, 0x001, 0x000, 0x008, 0x00B,
+ 0x001, 0x000, 0x00C, 0x000, 0x000, 0x000, 0x000, 0x00F,
+ 0x001, 0x000, 0x010, 0x00D, 0x001, 0x000, 0x00E, 0x013,
+ 0x001, 0x000, 0x014, 0x011, 0x001, 0x000, 0x012, 0x000,
+ 0x000, 0x005, 0x000, 0x015, 0x001, 0x000, 0x016, 0x019,
+ 0x001, 0x000, 0x01A, 0x017, 0x001, 0x000, 0x018, 0x000,
+ 0x000, 0x00E, 0x000, 0x000, 0x000, 0x001, 0x000, 0x000,
+ 0x000, 0x004, 0x000, 0x01B, 0x001, 0x000, 0x01C, 0x000,
+ 0x000, 0x007, 0x000, 0x000, 0x000, 0x00F, 0x000, 0x000,
+ 0x000, 0x00B, 0x000, 0x01D, 0x001, 0x000, 0x01E, 0x000,
+ 0x000, 0x008, 0x000, 0x000, 0x000, 0x002, 0x000, 0x000,
+ 0x000, 0x00C, 0x000, 0x000, 0x000, 0x006, 0x000, 0x000,
+ 0x000, 0x00D, 0x000, 0x000, 0x000, 0x003, 0x000, 0x000,
+ 0x000, 0x00A, 0x000, 0x000, 0x000, 0x009, 0x000, 0x004,
+ 0x078, 0x0C6, 0x0BC, 0x001, 0x094, 0x004, 0x093, 0x080,
+ 0x0C8, 0x040, 0x062, 0x0E9, 0x0DA, 0x01C, 0x02C, 0x015,
+ 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x058,
+ 0x00B, 0x0E9, 0x0E5, 0x0D5, 0x095, 0x0C1, 0x09D, 0x077,
+ 0x0CE, 0x0BB, 0x0A0, 0x06E, 0x01C, 0x005, 0x0F6, 0x077,
+ 0x0C6, 0x002, 0x0FA, 0x096, 0x070, 0x0E8, 0x01D, 0x0C0,
+ 0x017, 0x00E, 0x002, 0x0FA, 0x058, 0x07D, 0x0C0, 0x05F,
+ 0x072, 0x0CE, 0x0EC, 0x0A4, 0x0C3, 0x084, 0x090, 0x07A,
+ 0x030, 0x0CD, 0x08D, 0x079, 0x019, 0x0E7, 0x06C, 0x024,
+ 0x027, 0x09C, 0x008, 0x039, 0x007, 0x038, 0x0A8, 0x04A,
+ 0x04C, 0x0EA, 0x04D, 0x098, 0x09B, 0x024, 0x04C, 0x0C0,
+ 0x026, 0x0D3, 0x0E7, 0x054, 0x05A, 0x04D, 0x0F2, 0x04C,
+ 0x00C, 0x013, 0x023, 0x049, 0x090, 0x032, 0x06E, 0x0A4,
+ 0x0DF, 0x093, 0x071, 0x013, 0x077, 0x026, 0x0E1, 0x026,
+ 0x0F8, 0x026, 0x00C, 0x04C, 0x012, 0x026, 0x008, 0x009,
+ 0x082, 0x082, 0x060, 0x0A9, 0x030, 0x079, 0x036, 0x0B0,
+ 0x0B2, 0x0A8, 0x0A7, 0x072, 0x064, 0x08F, 0x09B, 0x033,
+ 0x033, 0x0F9, 0x0B8, 0x039, 0x0D5, 0x011, 0x073, 0x0AA,
+ 0x075, 0x026, 0x05D, 0x026, 0x051, 0x093, 0x02A, 0x049,
+ 0x094, 0x0C9, 0x095, 0x089, 0x0BC, 0x04D, 0x0C8, 0x09B,
+ 0x080, 0x09B, 0x0A0, 0x099, 0x006, 0x04C, 0x086, 0x026,
+ 0x058, 0x09B, 0x0A4, 0x09B, 0x099, 0x037, 0x062, 0x06C,
+ 0x067, 0x09B, 0x033, 0x030, 0x0BF, 0x036, 0x066, 0x061,
+ 0x0BF, 0x036, 0x0EC, 0x0C5, 0x0BD, 0x066, 0x082, 0x05A,
+ 0x050, 0x031, 0x0D5, 0x09D, 0x098, 0x018, 0x029, 0x03C,
+ 0x098, 0x086, 0x04C, 0x017, 0x026, 0x03E, 0x02C, 0x0B8,
+ 0x069, 0x03B, 0x049, 0x02E, 0x0B4, 0x008, 0x043, 0x01A,
+ 0x0A4, 0x0F9, 0x0B3, 0x051, 0x0F1, 0x010, 0x0F3, 0x043,
+ 0x0CD, 0x008, 0x06F, 0x063, 0x079, 0x0B3, 0x033, 0x00E,
+ 0x013, 0x098, 0x049, 0x098, 0x004, 0x0DA, 0x07C, 0x0E0,
+ 0x052, 0x079, 0x031, 0x00C, 0x098, 0x02E, 0x04D, 0x0AC,
+ 0x02C, 0x084, 0x014, 0x0EE, 0x04C, 0x0FE, 0x067, 0x05E,
+ 0x0E4, 0x09A, 0x075, 0x029, 0x0D7, 0x0A9, 0x035, 0x03A,
+ 0x094, 0x05B, 0x0D5, 0x09B, 0x058, 0x0B4, 0x0AF, 0x075,
+ 0x066, 0x0AF, 0x014, 0x0A9, 0x0EF, 0x040, 0x095, 0x025,
+ 0x008, 0x0B9, 0x0AD, 0x042, 0x0FC, 0x0D8, 0x0D9, 0x08C,
+ 0x033, 0x00E, 0x013, 0x098, 0x066, 0x01E, 0x045, 0x0AC,
+ 0x0B0, 0x00C, 0x042, 0x0D3, 0x0CC, 0x0A6, 0x012, 0x062,
+ 0x0DE, 0x0B4, 0x0B1, 0x080, 0x049, 0x07D, 0x0A2, 0x0DE,
+ 0x0B4, 0x018, 0x0C0, 0x024, 0x084, 0x0E6, 0x054, 0x0F5,
+ 0x083, 0x046, 0x001, 0x068, 0x01A, 0x063, 0x00C, 0x0C6,
+ 0x012, 0x064, 0x0FA, 0x04C, 0x035, 0x01C, 0x02C, 0x00E,
+ 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA,
+ 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AD, 0x0D7, 0x002,
+ 0x070, 0x0E0, 0x04C, 0x0F3, 0x0A1, 0x0C1, 0x0D5, 0x0C0,
+ 0x03C, 0x0B9, 0x069, 0x039, 0x060, 0x04E, 0x058, 0x077,
+ 0x002, 0x067, 0x093, 0x03C, 0x099, 0x0E4, 0x0CF, 0x038,
+ 0x01C, 0x097, 0x02E, 0x040, 0x01B, 0x090, 0x031, 0x046,
+ 0x0A3, 0x05E, 0x00E, 0x088, 0x034, 0x06A, 0x035, 0x0E0,
+ 0x0E8, 0x0AA, 0x035, 0x01A, 0x0A9, 0x0F5, 0x015, 0x046,
+ 0x0A3, 0x0EA, 0x07D, 0x04A, 0x0A3, 0x051, 0x0AA, 0x09F,
+ 0x070, 0x054, 0x0A6, 0x057, 0x02E, 0x0B4, 0x0CD, 0x0C8,
+ 0x0A3, 0x00C, 0x0C1, 0x0DA, 0x0C6, 0x0E1, 0x0CB, 0x07A,
+ 0x0D4, 0x01C, 0x068, 0x0FF, 0x0CF, 0x055, 0x0A8, 0x0C0,
+ 0x02D, 0x085, 0x011, 0x017, 0x044, 0x02A, 0x030, 0x00B,
+ 0x04A, 0x088, 0x0C2, 0x04D, 0x0B5, 0x020, 0x0D5, 0x026,
+ 0x001, 0x069, 0x051, 0x069, 0x052, 0x019, 0x052, 0x060,
+ 0x016, 0x095, 0x016, 0x082, 0x096, 0x054, 0x098, 0x005,
+ 0x0A5, 0x045, 0x0F3, 0x0DD, 0x06A, 0x0F9, 0x028, 0x018,
+ 0x0EF, 0x000, 0x030, 0x030, 0x051, 0x04E, 0x044, 0x05D,
+ 0x012, 0x0D1, 0x043, 0x0E6, 0x012, 0x06F, 0x09E, 0x0BA,
+ 0x0CC, 0x0DF, 0x025, 0x003, 0x01D, 0x0E0, 0x006, 0x006,
+ 0x00A, 0x030, 0x0CC, 0x0A9, 0x0EB, 0x02D, 0x000, 0x086,
+ 0x0A6, 0x012, 0x065, 0x04F, 0x056, 0x0D6, 0x065, 0x049,
+ 0x05F, 0x03D, 0x0E8, 0x037, 0x0C9, 0x040, 0x0C7, 0x078,
+ 0x001, 0x081, 0x082, 0x08C, 0x033, 0x018, 0x049, 0x080,
+ 0x0AE, 0x040, 0x0C5, 0x018, 0x005, 0x09C, 0x06D, 0x018,
+ 0x066, 0x00E, 0x0F3, 0x0A0, 0x0C6, 0x012, 0x062, 0x0DE,
+ 0x0F5, 0x004, 0x0B4, 0x0AC, 0x06B, 0x0C6, 0x019, 0x091,
+ 0x073, 0x005, 0x048, 0x02E, 0x072, 0x094, 0x080, 0x073,
+ 0x0A1, 0x0C8, 0x047, 0x036, 0x066, 0x064, 0x02F, 0x036,
+ 0x066, 0x064, 0x007, 0x099, 0x002, 0x091, 0x08E, 0x072,
+ 0x0D1, 0x00F, 0x09D, 0x006, 0x031, 0x073, 0x0A0, 0x0C3,
+ 0x051, 0x06A, 0x01A, 0x020, 0x0BF, 0x03A, 0x00C, 0x02C,
+ 0x073, 0x087, 0x043, 0x05E, 0x060, 0x002, 0x023, 0x0FC,
+ 0x0E0, 0x0D6, 0x035, 0x0EF, 0x09E, 0x0F5, 0x0EF, 0x092,
+ 0x081, 0x08E, 0x0F0, 0x003, 0x003, 0x005, 0x018, 0x066,
+ 0x045, 0x0CC, 0x00B, 0x048, 0x02E, 0x070, 0x00A, 0x040,
+ 0x039, 0x0D0, 0x0E4, 0x023, 0x09B, 0x033, 0x032, 0x017,
+ 0x09B, 0x033, 0x032, 0x003, 0x0CC, 0x085, 0x048, 0x0C7,
+ 0x038, 0x014, 0x0A5, 0x0CE, 0x029, 0x07E, 0x0D2, 0x080,
+ 0x0A1, 0x0A8, 0x0B4, 0x048, 0x088, 0x02F, 0x0CE, 0x083,
+ 0x00B, 0x01C, 0x0E1, 0x0D0, 0x0D7, 0x098, 0x004, 0x088,
+ 0x087, 0x0CE, 0x096, 0x031, 0x073, 0x0A5, 0x08F, 0x0F3,
+ 0x083, 0x058, 0x0D7, 0x0BE, 0x07B, 0x082, 0x0AF, 0x092,
+ 0x081, 0x08E, 0x0F0, 0x003, 0x003, 0x005, 0x018, 0x066,
+ 0x045, 0x0CC, 0x015, 0x020, 0x0B9, 0x0C8, 0x029, 0x000,
+ 0x0E7, 0x043, 0x090, 0x08E, 0x06C, 0x0CC, 0x0C8, 0x05E,
+ 0x06C, 0x0CC, 0x0C8, 0x00F, 0x032, 0x005, 0x023, 0x01C,
+ 0x0E4, 0x050, 0x0D4, 0x05A, 0x017, 0x088, 0x02F, 0x0CE,
+ 0x083, 0x010, 0x0F9, 0x0D0, 0x023, 0x017, 0x03A, 0x004,
+ 0x035, 0x0E6, 0x000, 0x022, 0x016, 0x039, 0x0C3, 0x0A3,
+ 0x0FC, 0x0E0, 0x0D6, 0x035, 0x0E0, 0x0BF, 0x0F4, 0x018,
+ 0x0F2, 0x02D, 0x04D, 0x043, 0x051, 0x06E, 0x05A, 0x022,
+ 0x01F, 0x030, 0x0D4, 0x017, 0x0E7, 0x041, 0x091, 0x073,
+ 0x005, 0x048, 0x02E, 0x077, 0x069, 0x000, 0x0E7, 0x043,
+ 0x090, 0x08E, 0x06C, 0x0CC, 0x0C8, 0x05E, 0x06C, 0x0CC,
+ 0x0C8, 0x00F, 0x032, 0x005, 0x023, 0x01C, 0x0EF, 0x04C,
+ 0x04E, 0x006, 0x004, 0x0C9, 0x09E, 0x00B, 0x0FF, 0x041,
+ 0x08F, 0x022, 0x0D4, 0x0D4, 0x035, 0x016, 0x0E5, 0x0A2,
+ 0x021, 0x0F3, 0x05A, 0x082, 0x0FC, 0x0E8, 0x032, 0x02E,
+ 0x060, 0x0A9, 0x005, 0x0CE, 0x013, 0x048, 0x007, 0x03A,
+ 0x01C, 0x084, 0x073, 0x066, 0x066, 0x042, 0x0F3, 0x066,
+ 0x066, 0x040, 0x079, 0x090, 0x029, 0x018, 0x0E7, 0x00A,
+ 0x098, 0x09C, 0x00A, 0x09E, 0x0B5, 0x012, 0x05C, 0x07C,
+ 0x0C3, 0x031, 0x08B, 0x098, 0x02A, 0x07C, 0x0D3, 0x0ED,
+ 0x038, 0x0E9, 0x0D3, 0x04E, 0x074, 0x0ED, 0x049, 0x09E,
+ 0x00B, 0x0FF, 0x041, 0x08F, 0x022, 0x0D4, 0x0D4, 0x035,
+ 0x016, 0x0E5, 0x0A2, 0x02D, 0x0EB, 0x045, 0x033, 0x08F,
+ 0x0FC, 0x0F7, 0x0A0, 0x05F, 0x025, 0x003, 0x01D, 0x0E4,
+ 0x00E, 0x006, 0x00A, 0x030, 0x0CC, 0x00C, 0x0F3, 0x0EB,
+ 0x040, 0x0DE, 0x061, 0x0A8, 0x070, 0x092, 0x00A, 0x000,
+ 0x0E1, 0x024, 0x01E, 0x000, 0x0E1, 0x024, 0x01E, 0x000,
+ 0x0E1, 0x024, 0x01E, 0x000, 0x0E1, 0x024, 0x01E, 0x000,
+ 0x0E1, 0x024, 0x01E, 0x001, 0x00F, 0x098, 0x02A, 0x00B,
+ 0x0F3, 0x0A0, 0x0C8, 0x0B9, 0x0A2, 0x0A4, 0x017, 0x03A,
+ 0x069, 0x000, 0x0E7, 0x043, 0x090, 0x08E, 0x075, 0x048,
+ 0x05E, 0x070, 0x069, 0x001, 0x0E6, 0x000, 0x052, 0x031,
+ 0x0CC, 0x018, 0x014, 0x0A5, 0x0CC, 0x009, 0x082, 0x094,
+ 0x073, 0x00C, 0x0A0, 0x091, 0x0F5, 0x025, 0x0CC, 0x007,
+ 0x006, 0x084, 0x084, 0x09F, 0x030, 0x0A2, 0x0A4, 0x07D,
+ 0x050, 0x075, 0x0A6, 0x065, 0x001, 0x04A, 0x08E, 0x0B4,
+ 0x0CC, 0x0C4, 0x035, 0x054, 0x075, 0x066, 0x0A4, 0x097,
+ 0x07A, 0x089, 0x050, 0x053, 0x013, 0x080, 0x019, 0x0E3,
+ 0x049, 0x05C, 0x06D, 0x0CE, 0x0A9, 0x040, 0x035, 0x006,
+ 0x078, 0x0D2, 0x057, 0x006, 0x0F1, 0x0B3, 0x02A, 0x08D,
+ 0x097, 0x023, 0x062, 0x092, 0x05D, 0x069, 0x099, 0x01C,
+ 0x06A, 0x036, 0x0E6, 0x0CD, 0x046, 0x012, 0x06F, 0x09E,
+ 0x0E1, 0x0AB, 0x0E4, 0x0A3, 0x00C, 0x0C0, 0x0DE, 0x0AC,
+ 0x0D4, 0x00D, 0x028, 0x01B, 0x0D0, 0x012, 0x0A5, 0x000,
+ 0x0F8, 0x04B, 0x0AD, 0x033, 0x028, 0x006, 0x0A0, 0x0DE,
+ 0x014, 0x097, 0x03A, 0x089, 0x05D, 0x0C0, 0x00D, 0x0E3,
+ 0x006, 0x090, 0x092, 0x05D, 0x069, 0x098, 0x066, 0x0B9,
+ 0x019, 0x095, 0x0E4, 0x0A8, 0x0CF, 0x09D, 0x033, 0x018,
+ 0x049, 0x0BE, 0x07B, 0x086, 0x0AF, 0x092, 0x08C, 0x033,
+ 0x024, 0x014, 0x00C, 0x0F4, 0x083, 0x024, 0x021, 0x0C2,
+ 0x070, 0x0BF, 0x0F4, 0x018, 0x0F2, 0x02D, 0x04D, 0x043,
+ 0x051, 0x06E, 0x05A, 0x022, 0x01F, 0x032, 0x0A8, 0x02F,
+ 0x0CE, 0x083, 0x022, 0x0E6, 0x005, 0x0A4, 0x017, 0x03A,
+ 0x069, 0x000, 0x0E7, 0x043, 0x090, 0x08E, 0x075, 0x048,
+ 0x05E, 0x070, 0x069, 0x001, 0x0E6, 0x042, 0x0A4, 0x063,
+ 0x098, 0x002, 0x029, 0x04B, 0x09A, 0x029, 0x078, 0x0E9,
+ 0x040, 0x053, 0x013, 0x081, 0x081, 0x032, 0x067, 0x082,
+ 0x0FF, 0x0D0, 0x063, 0x0C8, 0x0B5, 0x035, 0x00D, 0x045,
+ 0x0AE, 0x050, 0x008, 0x07C, 0x0E0, 0x0D0, 0x05F, 0x09D,
+ 0x006, 0x045, 0x0CC, 0x001, 0x0A4, 0x017, 0x03A, 0x069,
+ 0x000, 0x0E7, 0x043, 0x090, 0x08E, 0x075, 0x048, 0x05E,
+ 0x070, 0x069, 0x001, 0x0E6, 0x059, 0x0A4, 0x063, 0x098,
+ 0x01C, 0x052, 0x097, 0x03B, 0x030, 0x052, 0x08E, 0x07D,
+ 0x02A, 0x009, 0x01F, 0x051, 0x0EB, 0x0A4, 0x0A4, 0x00A,
+ 0x0B9, 0x094, 0x087, 0x0AE, 0x0C5, 0x031, 0x038, 0x002,
+ 0x0FF, 0x0D0, 0x063, 0x0C8, 0x0B5, 0x035, 0x00D, 0x045,
+ 0x0AE, 0x050, 0x008, 0x07C, 0x0EA, 0x020, 0x0BF, 0x03A,
+ 0x00C, 0x08B, 0x09A, 0x016, 0x090, 0x05C, 0x0E9, 0x0A4,
+ 0x003, 0x09D, 0x00E, 0x042, 0x039, 0x0D5, 0x021, 0x079,
+ 0x095, 0x048, 0x00F, 0x030, 0x00A, 0x091, 0x08E, 0x060,
+ 0x0EB, 0x029, 0x073, 0x000, 0x009, 0x054, 0x004, 0x0CA,
+ 0x082, 0x065, 0x052, 0x065, 0x0E4, 0x0CA, 0x022, 0x065,
+ 0x072, 0x065, 0x009, 0x032, 0x0E0, 0x099, 0x072, 0x04C,
+ 0x0C4, 0x0E0, 0x00B, 0x0FF, 0x041, 0x08F, 0x022, 0x0D4,
+ 0x0D4, 0x035, 0x016, 0x0B9, 0x040, 0x021, 0x0F3, 0x08A,
+ 0x082, 0x0FC, 0x0E8, 0x032, 0x02E, 0x060, 0x0A9, 0x005,
+ 0x0CE, 0x09A, 0x040, 0x039, 0x0D0, 0x0E4, 0x023, 0x09D,
+ 0x052, 0x017, 0x099, 0x054, 0x061, 0x099, 0x001, 0x0E6,
+ 0x040, 0x0A4, 0x063, 0x098, 0x004, 0x0B1, 0x084, 0x098,
+ 0x018, 0x0EF, 0x02D, 0x003, 0x005, 0x031, 0x038, 0x002,
+ 0x0FF, 0x0D0, 0x063, 0x0C8, 0x0B5, 0x035, 0x00D, 0x045,
+ 0x0B9, 0x068, 0x088, 0x07C, 0x0E0, 0x050, 0x05F, 0x09D,
+ 0x006, 0x045, 0x0CC, 0x081, 0x048, 0x02E, 0x071, 0x034,
+ 0x08F, 0x048, 0x001, 0x048, 0x015, 0x021, 0x005, 0x021,
+ 0x0E9, 0x00A, 0x052, 0x003, 0x0CE, 0x05A, 0x046, 0x039,
+ 0x0CF, 0x047, 0x08E, 0x060, 0x0AB, 0x01A, 0x0F3, 0x053,
+ 0x043, 0x0EB, 0x035, 0x024, 0x0B8, 0x01B, 0x030, 0x007,
+ 0x009, 0x08A, 0x074, 0x02F, 0x07E, 0x041, 0x074, 0x01E,
+ 0x01D, 0x00D, 0x087, 0x046, 0x049, 0x0D5, 0x095, 0x0D1,
+ 0x0D5, 0x0D5, 0x0BB, 0x0A9, 0x04E, 0x082, 0x09D, 0x005,
+ 0x03A, 0x00A, 0x074, 0x014, 0x0E8, 0x029, 0x0D0, 0x042,
+ 0x074, 0x05B, 0x0CE, 0x050, 0x0C4, 0x007, 0x045, 0x0BC,
+ 0x0E2, 0x00C, 0x040, 0x074, 0x05B, 0x0CE, 0x083, 0x004,
+ 0x0F9, 0x095, 0x04D, 0x013, 0x063, 0x05E, 0x06F, 0x031,
+ 0x03B, 0x0A0, 0x08B, 0x0A2, 0x0C5, 0x039, 0x08D, 0x078,
+ 0x03A, 0x022, 0x0A0, 0x000, 0x06B, 0x0C1, 0x0D1, 0x054,
+ 0x060, 0x016, 0x0D9, 0x091, 0x0A2, 0x0E7, 0x043, 0x08C,
+ 0x024, 0x0DC, 0x01C, 0x0E0, 0x051, 0x017, 0x039, 0x06B,
+ 0x03B, 0x0CC, 0x04B, 0x042, 0x02E, 0x06B, 0x050, 0x0BF,
+ 0x036, 0x036, 0x065, 0x04F, 0x07A, 0x018, 0x055, 0x025,
+ 0x078, 0x098, 0x023, 0x0E7, 0x050, 0x03E, 0x0F3, 0x081,
+ 0x04C, 0x002, 0x06D, 0x03E, 0x071, 0x053, 0x0AF, 0x078,
+ 0x0A9, 0x0D4, 0x0A6, 0x029, 0x0B1, 0x0BC, 0x0D9, 0x099,
+ 0x0B2, 0x08E, 0x062, 0x08F, 0x022, 0x02E, 0x075, 0x016,
+ 0x0B0, 0x0B2, 0x0AB, 0x023, 0x028, 0x016, 0x054, 0x052,
+ 0x031, 0x0BC, 0x0D9, 0x099, 0x0B2, 0x08E, 0x066, 0x019,
+ 0x002, 0x02E, 0x075, 0x016, 0x050, 0x02C, 0x0A9, 0x0C8,
+ 0x0C6, 0x0F5, 0x020, 0x0D3, 0x0E4, 0x07F, 0x04F, 0x09C,
+ 0x00A, 0x0D6, 0x016, 0x07F, 0x090, 0x0EE, 0x04C, 0x0EB,
+ 0x0CF, 0x0E2, 0x088, 0x0BA, 0x02F, 0x042, 0x086, 0x0AE,
+ 0x0BD, 0x0E5, 0x0A7, 0x052, 0x09F, 0x093, 0x063, 0x079,
+ 0x0EB, 0x033, 0x008, 0x0F9, 0x094, 0x052, 0x047, 0x0CD,
+ 0x099, 0x025, 0x06F, 0x03A, 0x00C, 0x013, 0x0E6, 0x055,
+ 0x034, 0x04C, 0x05A, 0x04D, 0x0B5, 0x023, 0x095, 0x0A5,
+ 0x048, 0x011, 0x05A, 0x00A, 0x043, 0x095, 0x0AC, 0x02C,
+ 0x0BA, 0x024, 0x005, 0x049, 0x0B1, 0x0BC, 0x0CA, 0x0A7,
+ 0x072, 0x06C, 0x06B, 0x0C5, 0x0BD, 0x0E8, 0x031, 0x069,
+ 0x052, 0x05D, 0x006, 0x012, 0x065, 0x03E, 0x0B1, 0x050,
+ 0x04C, 0x07D, 0x04F, 0x0AC, 0x00A, 0x030, 0x00B, 0x036,
+ 0x064, 0x011, 0x073, 0x08A, 0x083, 0x08E, 0x075, 0x012,
+ 0x09F, 0x07B, 0x0D2, 0x099, 0x058, 0x0EE, 0x082, 0x02E,
+ 0x077, 0x0A0, 0x0E3, 0x09D, 0x05D, 0x04F, 0x0BC, 0x02A,
+ 0x053, 0x029, 0x053, 0x0DE, 0x093, 0x024, 0x0BA, 0x0B3,
+ 0x036, 0x0AA, 0x04A, 0x0C6, 0x079, 0x0D4, 0x0B9, 0x0DE,
+ 0x062, 0x05A, 0x011, 0x073, 0x050, 0x050, 0x0BF, 0x037,
+ 0x036, 0x06F, 0x013, 0x023, 0x0BA, 0x00C, 0x024, 0x0CE,
+ 0x0BD, 0x0E2, 0x0A7, 0x052, 0x0B2, 0x08E, 0x06B, 0x060,
+ 0x062, 0x02E, 0x075, 0x013, 0x030, 0x0AC, 0x0A0, 0x059,
+ 0x0CA, 0x064, 0x063, 0x079, 0x0B3, 0x033, 0x065, 0x01C,
+ 0x0CC, 0x032, 0x004, 0x05C, 0x0EA, 0x02C, 0x0A0, 0x059,
+ 0x0DF, 0x023, 0x01B, 0x0D4, 0x083, 0x052, 0x047, 0x0DD,
+ 0x079, 0x096, 0x0D4, 0x09E, 0x0B3, 0x052, 0x04B, 0x0A2,
+ 0x05A, 0x01A, 0x08D, 0x05D, 0x07B, 0x082, 0x0A7, 0x052,
+ 0x0B2, 0x08E, 0x066, 0x019, 0x002, 0x02E, 0x075, 0x016,
+ 0x050, 0x02C, 0x08C, 0x032, 0x01D, 0x07B, 0x08E, 0x0A7,
+ 0x052, 0x0B1, 0x0BC, 0x0D9, 0x099, 0x098, 0x004, 0x0DA,
+ 0x07C, 0x0E2, 0x0AC, 0x0FE, 0x066, 0x019, 0x002, 0x02E,
+ 0x065, 0x050, 0x0BF, 0x033, 0x066, 0x064, 0x0FE, 0x074,
+ 0x018, 0x086, 0x04C, 0x017, 0x026, 0x0D6, 0x016, 0x052,
+ 0x039, 0x018, 0x0DE, 0x07A, 0x0CC, 0x0C2, 0x03E, 0x065,
+ 0x014, 0x091, 0x0F3, 0x066, 0x049, 0x008, 0x06E, 0x083,
+ 0x009, 0x033, 0x0AF, 0x031, 0x0ED, 0x00D, 0x09D, 0x006,
+ 0x012, 0x062, 0x02A, 0x031, 0x08D, 0x06D, 0x0E7, 0x041,
+ 0x082, 0x07C, 0x0CA, 0x0A6, 0x089, 0x087, 0x009, 0x02E,
+ 0x029, 0x0B1, 0x0AF, 0x010, 0x039, 0x0D6, 0x064, 0x097,
+ 0x030, 0x01D, 0x042, 0x075, 0x093, 0x044, 0x002, 0x08C,
+ 0x024, 0x0D2, 0x07A, 0x0B3, 0x050, 0x0F6, 0x089, 0x005,
+ 0x043, 0x05E, 0x061, 0x098, 0x0C0, 0x02C, 0x092, 0x025,
+ 0x03C, 0x08B, 0x024, 0x089, 0x049, 0x005, 0x049, 0x0E7,
+ 0x00C, 0x0B9, 0x084, 0x098, 0x0B7, 0x0AD, 0x033, 0x044,
+ 0x0AE, 0x05A, 0x051, 0x086, 0x060, 0x09F, 0x038, 0x0A9,
+ 0x0A2, 0x06C, 0x06B, 0x0C4, 0x08E, 0x0F4, 0x05E, 0x049,
+ 0x046, 0x012, 0x062, 0x0DE, 0x0B4, 0x0CD, 0x021, 0x05C,
+ 0x0B4, 0x0A3, 0x00C, 0x0C1, 0x03E, 0x072, 0x029, 0x0A2,
+ 0x06C, 0x06B, 0x0C6, 0x012, 0x062, 0x047, 0x0F0, 0x0E8,
+ 0x0C3, 0x032, 0x004, 0x035, 0x040, 0x092, 0x0A4, 0x082,
+ 0x088, 0x010, 0x092, 0x07C, 0x0CB, 0x0D4, 0x02F, 0x0A4,
+ 0x002, 0x011, 0x084, 0x098, 0x0B7, 0x0AD, 0x033, 0x044,
+ 0x0AE, 0x05A, 0x051, 0x086, 0x060, 0x09F, 0x038, 0x0A9,
+ 0x0A2, 0x06C, 0x06B, 0x0C4, 0x08E, 0x0F4, 0x05E, 0x049,
+ 0x044, 0x008, 0x049, 0x03E, 0x065, 0x0EA, 0x017, 0x0D2,
+ 0x001, 0x008, 0x0C2, 0x04C, 0x05B, 0x0D6, 0x099, 0x0A4,
+ 0x02B, 0x096, 0x094, 0x061, 0x098, 0x027, 0x0CE, 0x045,
+ 0x034, 0x04D, 0x08D, 0x078, 0x081, 0x009, 0x027, 0x0CC,
+ 0x0BD, 0x012, 0x028, 0x06C, 0x058, 0x0AF, 0x0B6, 0x0F3,
+ 0x0A0, 0x0C1, 0x03E, 0x065, 0x053, 0x044, 0x0D8, 0x0D7,
+ 0x092, 0x08E, 0x07D, 0x04B, 0x0C2, 0x0FA, 0x061, 0x026,
+ 0x006, 0x03A, 0x0B3, 0x06B, 0x003, 0x005, 0x049, 0x0E7,
+ 0x00C, 0x0B9, 0x06F, 0x05A, 0x066, 0x095, 0x05C, 0x0B4,
+ 0x0A3, 0x00C, 0x0C1, 0x03E, 0x070, 0x029, 0x0A2, 0x06E,
+ 0x0A4, 0x0DF, 0x093, 0x071, 0x013, 0x077, 0x026, 0x0E1,
+ 0x026, 0x0F8, 0x026, 0x0C6, 0x0BC, 0x094, 0x073, 0x0F9,
+ 0x02F, 0x00B, 0x0E9, 0x084, 0x098, 0x018, 0x0EA, 0x0CC,
+ 0x0EC, 0x00C, 0x015, 0x027, 0x09C, 0x032, 0x0FF, 0x03D,
+ 0x056, 0x0AF, 0x092, 0x08B, 0x07A, 0x0D3, 0x035, 0x0D5,
+ 0x0CB, 0x04A, 0x030, 0x0CC, 0x013, 0x0E7, 0x002, 0x09A,
+ 0x026, 0x0C6, 0x0BC, 0x094, 0x073, 0x041, 0x097, 0x091,
+ 0x0F4, 0x083, 0x0CE, 0x004, 0x020, 0x062, 0x08B, 0x005,
+ 0x016, 0x049, 0x08C, 0x024, 0x0C0, 0x0C7, 0x056, 0x090,
+ 0x0C0, 0x0C1, 0x052, 0x079, 0x0C3, 0x02E, 0x05B, 0x0D5,
+ 0x0A6, 0x072, 0x0D2, 0x094, 0x0FA, 0x0AD, 0x058, 0x0C8,
+ 0x0FA, 0x09F, 0x054, 0x0B3, 0x032, 0x04B, 0x0B9, 0x054,
+ 0x0A6, 0x051, 0x086, 0x06B, 0x079, 0x0D0, 0x060, 0x09F,
+ 0x032, 0x005, 0x034, 0x04D, 0x08D, 0x07A, 0x04D, 0x01E,
+ 0x07A, 0x0B3, 0x051, 0x000, 0x0A9, 0x03D, 0x059, 0x0A8,
+ 0x07B, 0x044, 0x082, 0x0A1, 0x0AF, 0x04A, 0x08D, 0x052,
+ 0x0A9, 0x052, 0x041, 0x049, 0x04F, 0x03A, 0x02E, 0x040,
+ 0x0A4, 0x099, 0x050, 0x0BE, 0x090, 0x008, 0x052, 0x079,
+ 0x0C3, 0x02E, 0x061, 0x026, 0x02D, 0x0EB, 0x04C, 0x0D0,
+ 0x015, 0x0CB, 0x04A, 0x030, 0x0CC, 0x013, 0x0E7, 0x002,
+ 0x09A, 0x026, 0x0C6, 0x0BC, 0x048, 0x0FE, 0x01D, 0x025,
+ 0x046, 0x0A9, 0x054, 0x0A9, 0x020, 0x0A4, 0x0A7, 0x09D,
+ 0x017, 0x020, 0x052, 0x04C, 0x0A8, 0x05F, 0x048, 0x004,
+ 0x023, 0x009, 0x031, 0x06F, 0x05A, 0x066, 0x080, 0x0AE,
+ 0x05A, 0x051, 0x086, 0x060, 0x09F, 0x038, 0x014, 0x0D1,
+ 0x036, 0x035, 0x0E4, 0x0A7, 0x09D, 0x017, 0x020, 0x052,
+ 0x04C, 0x0A2, 0x045, 0x00D, 0x08B, 0x015, 0x0F4, 0x091,
+ 0x0DE, 0x08B, 0x0C9, 0x028, 0x0C2, 0x04C, 0x05B, 0x0D6,
+ 0x099, 0x0A9, 0x05C, 0x0B4, 0x0A3, 0x00C, 0x0D6, 0x0F3,
+ 0x0A0, 0x0C1, 0x03E, 0x064, 0x00A, 0x068, 0x09B, 0x01A,
+ 0x0F1, 0x06D, 0x04C, 0x0AA, 0x092, 0x0E0, 0x036, 0x094,
+ 0x070, 0x09B, 0x029, 0x078, 0x013, 0x0AE, 0x0B3, 0x0AA,
+ 0x085, 0x0D4, 0x043, 0x075, 0x009, 0x03A, 0x0C9, 0x0EB,
+ 0x035, 0x024, 0x0B8, 0x01B, 0x032, 0x08E, 0x013, 0x048,
+ 0x07E, 0x04E, 0x0FD, 0x040, 0x0FD, 0x040, 0x0FD, 0x040,
+ 0x0FD, 0x040, 0x0FD, 0x040, 0x0FC, 0x013, 0x0F4, 0x021,
+ 0x0F9, 0x017, 0x045, 0x08A, 0x030, 0x00B, 0x033, 0x05F,
+ 0x083, 0x0A2, 0x02A, 0x030, 0x00B, 0x033, 0x05F, 0x083,
+ 0x0A2, 0x0A8, 0x0C0, 0x02D, 0x0B3, 0x020, 0x070, 0x092,
+ 0x013, 0x09A, 0x0DE, 0x074, 0x018, 0x027, 0x0CC, 0x0AA,
+ 0x068, 0x09B, 0x01A, 0x0F7, 0x007, 0x045, 0x051, 0x080,
+ 0x05B, 0x066, 0x047, 0x007, 0x038, 0x0A8, 0x023, 0x0E7,
+ 0x051, 0x011, 0x03F, 0x0E0, 0x0E8, 0x085, 0x046, 0x001,
+ 0x06D, 0x099, 0x006, 0x012, 0x065, 0x04F, 0x07A, 0x020,
+ 0x024, 0x0BA, 0x0B3, 0x032, 0x015, 0x025, 0x07B, 0x0AD,
+ 0x033, 0x078, 0x0AE, 0x00E, 0x073, 0x0D0, 0x047, 0x0CE,
+ 0x0A7, 0x030, 0x0CC, 0x044, 0x0FF, 0x083, 0x0A2, 0x0A8,
+ 0x0C0, 0x02C, 0x0D9, 0x091, 0x0C1, 0x0D1, 0x015, 0x018,
+ 0x005, 0x09B, 0x032, 0x008, 0x0BA, 0x02C, 0x051, 0x080,
+ 0x059, 0x0B3, 0x020, 0x070, 0x092, 0x0E2, 0x098, 0x089,
+ 0x0FD, 0x0BC, 0x0EE, 0x018, 0x090, 0x0FC, 0x08B, 0x0A2,
+ 0x0C5, 0x02B, 0x00D, 0x078, 0x03A, 0x022, 0x0A5, 0x061,
+ 0x0AF, 0x007, 0x045, 0x051, 0x080, 0x05B, 0x066, 0x044,
+ 0x09E, 0x0B3, 0x052, 0x04B, 0x083, 0x0AD, 0x0C7, 0x009,
+ 0x0BE, 0x01F, 0x09F, 0x074, 0x065, 0x05D, 0x00A, 0x017,
+ 0x07C, 0x0AB, 0x0A0, 0x0C2, 0x04C, 0x038, 0x049, 0x012,
+ 0x02E, 0x038, 0x049, 0x007, 0x0A3, 0x00C, 0x0C1, 0x03E,
+ 0x065, 0x053, 0x044, 0x0D8, 0x0D7, 0x0AD, 0x0E7, 0x000,
+ 0x032, 0x04B, 0x09B, 0x033, 0x034, 0x04A, 0x003, 0x000,
+ 0x09D, 0x025, 0x0CE, 0x083, 0x024, 0x0B8, 0x019, 0x099,
+ 0x08C, 0x002, 0x012, 0x04B, 0x0A1, 0x099, 0x0D8, 0x0C0,
+ 0x027, 0x049, 0x073, 0x0CF, 0x0F9, 0x03C, 0x0F4, 0x07C,
+ 0x0E7, 0x098, 0x004, 0x0E9, 0x02E, 0x07F, 0x039, 0x0E3,
+ 0x04F, 0x046, 0x053, 0x0C0, 0x060, 0x013, 0x0A4, 0x0B9,
+ 0x0E5, 0x03C, 0x003, 0x0DE, 0x08F, 0x09C, 0x0F3, 0x000,
+ 0x09C, 0x06F, 0x0CF, 0x03E, 0x085, 0x0F9, 0x0A3, 0x036,
+ 0x002, 0x01E, 0x060, 0x038, 0x092, 0x03E, 0x063, 0x01A,
+ 0x010, 0x09F, 0x0CF, 0x018, 0x010, 0x092, 0x0BC, 0x0D0,
+ 0x0A4, 0x00C, 0x0DC, 0x0C0, 0x00F, 0x09C, 0x097, 0x034,
+ 0x062, 0x0B6, 0x0E7, 0x0F3, 0x0F3, 0x0A5, 0x0CF, 0x018,
+ 0x042, 0x034, 0x01C, 0x0C2, 0x0CA, 0x0FA, 0x08E, 0x068,
+ 0x052, 0x006, 0x0AF, 0x03C, 0x0A3, 0x00D, 0x0BF, 0x09E,
+ 0x050, 0x0E1, 0x0D1, 0x073, 0x0CA, 0x0E0, 0x03A, 0x0FC,
+ 0x0C1, 0x009, 0x01A, 0x01E, 0x06A, 0x05C, 0x05B, 0x08E,
+ 0x063, 0x04E, 0x077, 0x073, 0x0CC, 0x061, 0x067, 0x0DD,
+ 0x0E6, 0x06C, 0x048, 0x0D1, 0x0F3, 0x01B, 0x024, 0x069,
+ 0x051, 0x008, 0x0D4, 0x042, 0x01B, 0x0F4, 0x067, 0x0D1,
+ 0x080, 0x04E, 0x02F, 0x0D0, 0x08C, 0x0D8, 0x030, 0x009,
+ 0x0C2, 0x01E, 0x080, 0x01C, 0x046, 0x001, 0x03A, 0x047,
+ 0x0D0, 0x031, 0x0A1, 0x006, 0x001, 0x03A, 0x07F, 0x046,
+ 0x030, 0x021, 0x018, 0x004, 0x0E9, 0x05E, 0x084, 0x029,
+ 0x000, 0x0C0, 0x027, 0x0CD, 0x0D0, 0x000, 0x07C, 0x098,
+ 0x004, 0x0F9, 0x02E, 0x084, 0x062, 0x08C, 0x002, 0x07D,
+ 0x0BA, 0x03E, 0x07E, 0x04C, 0x002, 0x07D, 0x02E, 0x08C,
+ 0x061, 0x008, 0x030, 0x009, 0x0F4, 0x01D, 0x001, 0x065,
+ 0x073, 0x000, 0x09F, 0x051, 0x0D0, 0x085, 0x020, 0x018,
+ 0x004, 0x0FA, 0x0BD, 0x019, 0x046, 0x018, 0x0C0, 0x027,
+ 0x0DF, 0x0D1, 0x094, 0x038, 0x04C, 0x002, 0x07D, 0x017,
+ 0x046, 0x057, 0x001, 0x030, 0x009, 0x0F5, 0x0FA, 0x001,
+ 0x009, 0x006, 0x001, 0x03E, 0x087, 0x0A1, 0x04B, 0x088,
+ 0x0C0, 0x027, 0x0DC, 0x074, 0x00D, 0x039, 0x0D3, 0x000,
+ 0x09F, 0x073, 0x0D0, 0x030, 0x0B3, 0x098, 0x004, 0x0FB,
+ 0x0BD, 0x006, 0x0C4, 0x083, 0x000, 0x09F, 0x047, 0x0D0,
+ 0x036, 0x048, 0x0CC, 0x002, 0x071, 0x0BF, 0x03F, 0x09A,
+ 0x017, 0x0E6, 0x03F, 0x008, 0x021, 0x0E6, 0x092, 0x0A4,
+ 0x08F, 0x09A, 0x010, 0x031, 0x0A7, 0x0F3, 0x010, 0x0B1,
+ 0x084, 0x0AF, 0x03A, 0x0AC, 0x0DC, 0x0F7, 0x073, 0x0F2,
+ 0x05C, 0x0C6, 0x02A, 0x0DB, 0x09E, 0x07E, 0x07E, 0x097,
+ 0x031, 0x008, 0x063, 0x0D0, 0x073, 0x07B, 0x043, 0x0A8,
+ 0x0E6, 0x03D, 0x034, 0x0EA, 0x0F3, 0x0E3, 0x015, 0x0BF,
+ 0x09F, 0x018, 0x05F, 0x045, 0x0CF, 0x0E8, 0x09F, 0x05F,
+ 0x09A, 0x05B, 0x003, 0x0D0, 0x0F3, 0x0D3, 0x0CE, 0x037,
+ 0x01C, 0x0D0, 0x00F, 0x0BB, 0x09E, 0x068, 0x078, 0x03B,
+ 0x0BC, 0x0CA, 0x031, 0x0E8, 0x0F9, 0x0A2, 0x002, 0x012,
+ 0x0A2, 0x073, 0x051, 0x008, 0x06F, 0x0D1, 0x0F3, 0x046,
+ 0x001, 0x038, 0x0BF, 0x040, 0x0FC, 0x023, 0x000, 0x09C,
+ 0x021, 0x0E8, 0x049, 0x051, 0x080, 0x04E, 0x091, 0x0F4,
+ 0x021, 0x003, 0x019, 0x080, 0x04E, 0x09F, 0x0D0, 0x021,
+ 0x063, 0x006, 0x001, 0x03A, 0x056, 0x08C, 0x002, 0x074,
+ 0x0FE, 0x075, 0x049, 0x05E, 0x063, 0x0D3, 0x04A, 0x054,
+ 0x042, 0x035, 0x013, 0x0A7, 0x0D1, 0x080, 0x04E, 0x095,
+ 0x0E8, 0x01E, 0x09A, 0x04C, 0x002, 0x07C, 0x0DD, 0x01B,
+ 0x0B9, 0x0E6, 0x001, 0x03E, 0x04B, 0x0A0, 0x062, 0x0A3,
+ 0x000, 0x09F, 0x06E, 0x08C, 0x0FC, 0x0F3, 0x000, 0x09F,
+ 0x04B, 0x0A0, 0x042, 0x018, 0x0CC, 0x002, 0x07D, 0x007,
+ 0x043, 0x0DA, 0x013, 0x000, 0x09F, 0x051, 0x0D0, 0x03D,
+ 0x034, 0x098, 0x004, 0x0FA, 0x0BD, 0x01C, 0x062, 0x08C,
+ 0x002, 0x07D, 0x0FD, 0x01C, 0x061, 0x073, 0x000, 0x09F,
+ 0x045, 0x0D1, 0x0F4, 0x04E, 0x060, 0x013, 0x0EB, 0x0F4,
+ 0x025, 0x0B0, 0x033, 0x000, 0x09F, 0x043, 0x0D1, 0x0A7,
+ 0x09C, 0x018, 0x004, 0x0FB, 0x08E, 0x084, 0x003, 0x0E9,
+ 0x080, 0x04F, 0x0B9, 0x0E8, 0x043, 0x0C1, 0x030, 0x009,
+ 0x0F7, 0x07A, 0x00A, 0x031, 0x098, 0x004, 0x0FA, 0x03E,
+ 0x084, 0x040, 0x041, 0x080, 0x04E, 0x082, 0x0E7, 0x041,
+ 0x087, 0x009, 0x023, 0x004, 0x023, 0x000, 0x09D, 0x005,
+ 0x0CE, 0x096, 0x01C, 0x024, 0x08C, 0x010, 0x08C, 0x002,
+ 0x074, 0x017, 0x03A, 0x004, 0x038, 0x049, 0x018, 0x021,
+ 0x018, 0x004, 0x0E8, 0x02E, 0x074, 0x050, 0x0E1, 0x024,
+ 0x060, 0x084, 0x060, 0x013, 0x0A0, 0x0B9, 0x0D4, 0x011,
+ 0x0C2, 0x048, 0x0C1, 0x008, 0x0C0, 0x027, 0x041, 0x073,
+ 0x0A8, 0x023, 0x084, 0x091, 0x082, 0x011, 0x080, 0x04E,
+ 0x082, 0x0E7, 0x052, 0x08E, 0x012, 0x046, 0x008, 0x046,
+ 0x001, 0x03A, 0x00B, 0x09D, 0x040, 0x01C, 0x024, 0x08C,
+ 0x010, 0x08C, 0x002, 0x074, 0x017, 0x03A, 0x009, 0x00E,
+ 0x012, 0x046, 0x008, 0x046, 0x001, 0x03A, 0x00B, 0x098,
+ 0x06A, 0x01C, 0x024, 0x0B0, 0x0E1, 0x018, 0x004, 0x0E8,
+ 0x02E, 0x06B, 0x050, 0x0E1, 0x025, 0x087, 0x008, 0x0C0,
+ 0x027, 0x041, 0x073, 0x005, 0x043, 0x084, 0x096, 0x01C,
+ 0x023, 0x000, 0x09D, 0x005, 0x0CC, 0x0AA, 0x01C, 0x024,
+ 0x0B0, 0x0E1, 0x018, 0x004, 0x0E8, 0x02E, 0x070, 0x068,
+ 0x070, 0x092, 0x0C3, 0x084, 0x060, 0x013, 0x0E5, 0x044,
+ 0x0F9, 0x040, 0x09D, 0x005, 0x0CE, 0x05A, 0x01C, 0x024,
+ 0x0B0, 0x0E1, 0x018, 0x004, 0x0F9, 0x0D1, 0x03E, 0x070,
+ 0x027, 0x0CF, 0x013, 0x0E5, 0x044, 0x02C, 0x0A0, 0x042,
+ 0x0CB, 0x089, 0x0F2, 0x021, 0x03A, 0x00B, 0x09C, 0x00A,
+ 0x01C, 0x024, 0x0B0, 0x0E1, 0x018, 0x004, 0x0F9, 0x0D1,
+ 0x00B, 0x038, 0x010, 0x0B3, 0x0C4, 0x021, 0x039, 0x036,
+ 0x05C, 0x042, 0x0C8, 0x084, 0x02B, 0x079, 0x0D0, 0x061,
+ 0x0C2, 0x074, 0x015, 0x024, 0x0BA, 0x0D3, 0x031, 0x0E5,
+ 0x059, 0x008, 0x029, 0x008, 0x0E0, 0x066, 0x063, 0x042,
+ 0x095, 0x012, 0x081, 0x000, 0x029, 0x00B, 0x0C1, 0x051,
+ 0x024, 0x0B8, 0x019, 0x099, 0x090, 0x022, 0x090, 0x0B4,
+ 0x018, 0x0A0, 0x091, 0x041, 0x001, 0x041, 0x041, 0x041,
+ 0x052, 0x083, 0x0CA, 0x040, 0x028, 0x068, 0x029, 0x008,
+ 0x0BA, 0x016, 0x010, 0x09C, 0x099, 0x00B, 0x056, 0x094,
+ 0x090, 0x052, 0x015, 0x074, 0x0C0, 0x027, 0x01A, 0x02A,
+ 0x0D2, 0x090, 0x025, 0x0D3, 0x000, 0x09D, 0x028, 0x0AB,
+ 0x04A, 0x042, 0x017, 0x04C, 0x002, 0x070, 0x0D4, 0x084,
+ 0x02E, 0x098, 0x004, 0x0E1, 0x02A, 0x042, 0x017, 0x04C,
+ 0x002, 0x070, 0x082, 0x090, 0x04B, 0x0A6, 0x001, 0x038,
+ 0x051, 0x048, 0x042, 0x0E9, 0x080, 0x04E, 0x015, 0x0A4,
+ 0x021, 0x074, 0x0C0, 0x027, 0x00F, 0x0A4, 0x012, 0x0E9,
+ 0x080, 0x04E, 0x082, 0x0AC, 0x080, 0x0AC, 0x0A0, 0x0AC,
+ 0x0A9, 0x059, 0x0E5, 0x064, 0x045, 0x065, 0x0CA, 0x0C8,
+ 0x04A, 0x0CE, 0x00A, 0x0CE, 0x04A, 0x0CE, 0x095, 0x091,
+ 0x095, 0x094, 0x095, 0x093, 0x029, 0x025, 0x0C0, 0x0CC,
+ 0x0CC, 0x088, 0x0A4, 0x097, 0x056, 0x036, 0x064, 0x072,
+ 0x090, 0x054, 0x08A, 0x09C, 0x045, 0x008, 0x0B9, 0x0B7,
+ 0x066, 0x012, 0x093, 0x009, 0x0C9, 0x0B2, 0x074, 0x08E,
+ 0x0BA, 0x060, 0x013, 0x0E5, 0x034, 0x08E, 0x0BA, 0x060,
+ 0x013, 0x0E4, 0x074, 0x08E, 0x0BA, 0x060, 0x013, 0x0E5,
+ 0x069, 0x01D, 0x074, 0x0C0, 0x027, 0x0CA, 0x029, 0x01D,
+ 0x074, 0x0C0, 0x027, 0x0CE, 0x0D2, 0x025, 0x0D3, 0x000,
+ 0x09F, 0x038, 0x0A4, 0x04B, 0x0A6, 0x001, 0x03E, 0x05E,
+ 0x091, 0x02E, 0x098, 0x004, 0x0F9, 0x015, 0x022, 0x05D,
+ 0x030, 0x009, 0x0F3, 0x0E9, 0x012, 0x0E9, 0x080, 0x04F,
+ 0x090, 0x052, 0x025, 0x0D3, 0x000, 0x09D, 0x0C5, 0x048,
+ 0x025, 0x0D3, 0x000, 0x09C, 0x045, 0x0CE, 0x0CD, 0x009,
+ 0x0C9, 0x0B2, 0x01A, 0x044, 0x0BA, 0x060, 0x013, 0x0E7,
+ 0x034, 0x089, 0x074, 0x0C0, 0x027, 0x01C, 0x027, 0x0B7,
+ 0x09C, 0x080, 0x0C2, 0x0D7, 0x076, 0x059, 0x09B, 0x093,
+ 0x00C, 0x064, 0x0C3, 0x01D, 0x01B, 0x0F4, 0x045, 0x04B,
+ 0x0C7, 0x0C6, 0x03A, 0x037, 0x0E8, 0x081, 0x04B, 0x0C7,
+ 0x0C6, 0x03A, 0x037, 0x0E8, 0x091, 0x04B, 0x0C7, 0x0C6,
+ 0x032, 0x061, 0x08E, 0x0B3, 0x0BC, 0x0C3, 0x04A, 0x022,
+ 0x0E6, 0x0B5, 0x024, 0x097, 0x071, 0x0C9, 0x087, 0x0B4,
+ 0x031, 0x0AE, 0x073, 0x0A2, 0x0CF, 0x039, 0x0D2, 0x05D,
+ 0x004, 0x044, 0x042, 0x0C0, 0x0D6, 0x0DE, 0x071, 0x006,
+ 0x016, 0x0BB, 0x0DB, 0x0CE, 0x083, 0x00C, 0x064, 0x0C3,
+ 0x01D, 0x031, 0x013, 0x004, 0x0F9, 0x095, 0x04D, 0x013,
+ 0x032, 0x093, 0x063, 0x05E, 0x066, 0x014, 0x0CC, 0x029,
+ 0x02A, 0x053, 0x030, 0x0A6, 0x061, 0x04C, 0x0C2, 0x099,
+ 0x085, 0x03A, 0x072, 0x0CC, 0x0C2, 0x099, 0x085, 0x006,
+ 0x01B, 0x0B3, 0x00A, 0x066, 0x014, 0x014, 0x024, 0x099,
+ 0x085, 0x033, 0x00A, 0x008, 0x0B1, 0x086, 0x061, 0x04C,
+ 0x0C2, 0x084, 0x021, 0x068, 0x073, 0x03B, 0x030, 0x0A6,
+ 0x061, 0x041, 0x04E, 0x0A5, 0x098, 0x053, 0x030, 0x0AC,
+ 0x059, 0x076, 0x061, 0x04C, 0x0C2, 0x0B0, 0x08D, 0x0D6,
+ 0x061, 0x04C, 0x0C2, 0x0B0, 0x02C, 0x0F6, 0x061, 0x04C,
+ 0x0C2, 0x0B1, 0x08C, 0x0A5, 0x098, 0x053, 0x030, 0x0AC,
+ 0x00F, 0x024, 0x0CC, 0x029, 0x098, 0x056, 0x00F, 0x028,
+ 0x066, 0x015, 0x092, 0x01A, 0x019, 0x085, 0x033, 0x00A,
+ 0x0CA, 0x085, 0x00C, 0x0C2, 0x099, 0x085, 0x065, 0x0C3,
+ 0x0D9, 0x085, 0x033, 0x00A, 0x0CE, 0x070, 0x086, 0x061,
+ 0x04C, 0x0C2, 0x0B3, 0x097, 0x071, 0x00C, 0x099, 0x03B,
+ 0x0CC, 0x083, 0x058, 0x00B, 0x0EA, 0x077, 0x09D, 0x006,
+ 0x04A, 0x0BE, 0x004, 0x074, 0x060, 0x0E0, 0x0D1, 0x04E,
+ 0x038, 0x04C, 0x03E, 0x0EE, 0x03E, 0x0EE, 0x03E, 0x0EE,
+ 0x03E, 0x0EE, 0x030, 0x0BB, 0x0CA, 0x0E1, 0x01F, 0x077,
+ 0x01F, 0x077, 0x01F, 0x077, 0x01F, 0x077, 0x027, 0x070,
+ 0x08F, 0x0BB, 0x080, 0x00E, 0x011, 0x0F7, 0x071, 0x0F7,
+ 0x07C, 0x06F, 0x03C, 0x0B3, 0x036, 0x002, 0x0FB, 0x08D,
+ 0x0E6, 0x055, 0x070, 0x07F, 0x02D, 0x024, 0x069, 0x055,
+ 0x04F, 0x058, 0x0A9, 0x023, 0x01F, 0x054, 0x0F7, 0x08A,
+ 0x095, 0x025, 0x02B, 0x075, 0x00C, 0x0CC, 0x0AC, 0x056,
+ 0x051, 0x0CC, 0x051, 0x0E4, 0x045, 0x0CE, 0x0A2, 0x012,
+ 0x039, 0x0C0, 0x0A0, 0x0AF, 0x056, 0x06A, 0x049, 0x07F,
+ 0x002, 0x08C, 0x009, 0x0F8, 0x00B, 0x0EB, 0x0AF, 0x056,
+ 0x076, 0x067, 0x052, 0x0B2, 0x08E, 0x069, 0x0A7, 0x011,
+ 0x073, 0x0A8, 0x0B1, 0x0BC, 0x0CA, 0x0A0, 0x0A9, 0x036,
+ 0x050, 0x02C, 0x098, 0x0E7, 0x00A, 0x0F5, 0x066, 0x0A4,
+ 0x097, 0x0E2, 0x05A, 0x030, 0x027, 0x0BA, 0x0F7, 0x083,
+ 0x04E, 0x0A5, 0x033, 0x00A, 0x066, 0x015, 0x08D, 0x0E6,
+ 0x055, 0x039, 0x0D2, 0x0A7, 0x0AC, 0x054, 0x060, 0x016,
+ 0x070, 0x01B, 0x072, 0x08E, 0x062, 0x08F, 0x022, 0x02E,
+ 0x075, 0x016, 0x002, 0x0FB, 0x08D, 0x0E6, 0x00A, 0x095,
+ 0x03D, 0x062, 0x0A3, 0x000, 0x0B7, 0x001, 0x0B5, 0x053,
+ 0x0DE, 0x02A, 0x054, 0x094, 0x0AD, 0x0D4, 0x033, 0x032,
+ 0x0B1, 0x059, 0x047, 0x031, 0x047, 0x091, 0x017, 0x03A,
+ 0x088, 0x048, 0x0E7, 0x002, 0x0B0, 0x017, 0x0DC, 0x067,
+ 0x09D, 0x04B, 0x08D, 0x0E7, 0x052, 0x0AA, 0x07B, 0x0D4,
+ 0x0AA, 0x092, 0x0BD, 0x0D6, 0x099, 0x0BC, 0x056, 0x002,
+ 0x0FB, 0x08C, 0x0F3, 0x066, 0x066, 0x0C6, 0x0F3, 0x066,
+ 0x066, 0x062, 0x099, 0x02A, 0x0F8, 0x018, 0x068, 0x070,
+ 0x0B0, 0x08A, 0x00D, 0x055, 0x055, 0x055, 0x055, 0x052,
+ 0x032, 0x0E1, 0x040, 0x05C, 0x038, 0x00B, 0x0EA, 0x09B,
+ 0x087, 0x001, 0x07D, 0x0C0, 0x05F, 0x070, 0x017, 0x0DC,
+ 0x005, 0x0F5, 0x0DC, 0x09B, 0x001, 0x07D, 0x061, 0x04D,
+ 0x080, 0x0BE, 0x0A7, 0x079, 0x082, 0x0A2, 0x01F, 0x050,
+ 0x015, 0x02A, 0x08F, 0x08B, 0x01C, 0x0E5, 0x0A5, 0x013,
+ 0x084, 0x058, 0x0E7, 0x002, 0x091, 0x054, 0x005, 0x002,
+ 0x04B, 0x0BD, 0x022, 0x01A, 0x094, 0x07F, 0x09C, 0x01A,
+ 0x0C0, 0x05F, 0x042, 0x01A, 0x021, 0x0D1, 0x080, 0x059,
+ 0x0C0, 0x06D, 0x01C, 0x02C, 0x00A, 0x083, 0x055, 0x055,
+ 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+ 0x055, 0x054, 0x01C, 0x0B8, 0x05C, 0x06E, 0x017, 0x09C,
+ 0x02F, 0x038, 0x05E, 0x070, 0x0E7, 0x0B8, 0x05E, 0x070,
+ 0x0BC, 0x0E1, 0x079, 0x0C2, 0x0F3, 0x085, 0x0E7, 0x00B,
+ 0x0CE, 0x017, 0x09C, 0x029, 0x09C, 0x029, 0x09C, 0x029,
+ 0x09C, 0x023, 0x00F, 0x058, 0x014, 0x0EE, 0x035, 0x077,
+ 0x026, 0x021, 0x093, 0x005, 0x0C9, 0x0B0, 0x017, 0x0D2,
+ 0x01D, 0x018, 0x08A, 0x021, 0x093, 0x005, 0x0C9, 0x0B0,
+ 0x017, 0x0D1, 0x087, 0x0AC, 0x00A, 0x074, 0x00F, 0x0AE,
+ 0x0F5, 0x05A, 0x082, 0x0A3, 0x0E4, 0x03A, 0x031, 0x014,
+ 0x0BB, 0x0D7, 0x059, 0x099, 0x074, 0x0A2, 0x019, 0x030,
+ 0x05C, 0x09B, 0x001, 0x07D, 0x018, 0x07A, 0x0C0, 0x0A7,
+ 0x040, 0x0F8, 0x043, 0x0D4, 0x063, 0x089, 0x025, 0x0D0,
+ 0x010, 0x0D6, 0x01C, 0x06A, 0x010, 0x0F5, 0x055, 0x089,
+ 0x025, 0x0D1, 0x051, 0x066, 0x01F, 0x051, 0x0F5, 0x091,
+ 0x049, 0x02E, 0x089, 0x015, 0x098, 0x06A, 0x0A3, 0x0E0,
+ 0x08A, 0x094, 0x065, 0x064, 0x00E, 0x013, 0x017, 0x038,
+ 0x0A8, 0x086, 0x04C, 0x017, 0x026, 0x0C0, 0x05F, 0x046,
+ 0x01E, 0x0B0, 0x028, 0x063, 0x01F, 0x008, 0x07A, 0x08C,
+ 0x071, 0x024, 0x0BA, 0x002, 0x01A, 0x0D0, 0x00D, 0x042,
+ 0x01E, 0x0AA, 0x0B1, 0x024, 0x0BA, 0x02A, 0x02D, 0x031,
+ 0x0F5, 0x01F, 0x058, 0x074, 0x092, 0x0E8, 0x087, 0x05A,
+ 0x063, 0x052, 0x0DE, 0x0F4, 0x051, 0x069, 0x04A, 0x03E,
+ 0x009, 0x069, 0x046, 0x050, 0x0F0, 0x0E1, 0x031, 0x073,
+ 0x005, 0x045, 0x0BD, 0x059, 0x08D, 0x08B, 0x04A, 0x07C,
+ 0x0D3, 0x0ED, 0x038, 0x0E9, 0x0D3, 0x04E, 0x074, 0x0ED,
+ 0x044, 0x032, 0x060, 0x0B9, 0x036, 0x002, 0x0FA, 0x05B,
+ 0x0DE, 0x08A, 0x02D, 0x029, 0x0D0, 0x0E1, 0x021, 0x0F5,
+ 0x0A3, 0x092, 0x021, 0x0F2, 0x019, 0x030, 0x05C, 0x09B,
+ 0x001, 0x07D, 0x021, 0x0F5, 0x0A0, 0x0C6, 0x001, 0x067,
+ 0x001, 0x0B4, 0x045, 0x0CE, 0x0A5, 0x012, 0x039, 0x0D4,
+ 0x01C, 0x005, 0x0F4, 0x040, 0x0A1, 0x0C2, 0x0C3, 0x050,
+ 0x06A, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA,
+ 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x0AA, 0x081, 0x0AF,
+ 0x086, 0x09F, 0x019, 0x01B, 0x0E7, 0x081, 0x0F3, 0x065,
+ 0x0F2, 0x080, 0x0BE, 0x070, 0x017, 0x0DF, 0x0DF, 0x038,
+ 0x00B, 0x0EB, 0x00D, 0x0C3, 0x080, 0x0BE, 0x0A7, 0x00F,
+ 0x095, 0x04F, 0x05A, 0x094, 0x0C0, 0x02C, 0x0D8, 0x0B1,
+ 0x0A7, 0x0CE, 0x05A, 0x011, 0x073, 0x0A8, 0x03A, 0x0C2,
+ 0x0CC, 0x0B6, 0x030, 0x017, 0x0DC, 0x06F, 0x035, 0x0A9,
+ 0x080, 0x04D, 0x0A7, 0x0CE, 0x02A, 0x018, 0x079, 0x0C5,
+ 0x049, 0x0DE, 0x061, 0x0A8, 0x022, 0x0E7, 0x050, 0x033,
+ 0x0F9, 0x098, 0x064, 0x008, 0x0B9, 0x095, 0x042, 0x0FC,
+ 0x0CC, 0x0D9, 0x095, 0x03D, 0x062, 0x0A2, 0x048, 0x0D4,
+ 0x048, 0x0E7, 0x002, 0x088, 0x0B9, 0x0C1, 0x0A0, 0x0E3,
+ 0x09D, 0x04E, 0x062, 0x0E6, 0x0CC, 0x0C6, 0x06B, 0x0CE,
+ 0x083, 0x010, 0x0C9, 0x082, 0x0E4, 0x0DA, 0x0C2, 0x0C8,
+ 0x01E, 0x0C3, 0x0B9, 0x036, 0x002, 0x0FA, 0x0A9, 0x0EB,
+ 0x04E, 0x030, 0x030, 0x0FA, 0x00D, 0x0F0, 0x0A9, 0x0EB,
+ 0x040, 0x0B9, 0x00F, 0x0AA, 0x07A, 0x0D2, 0x0C2, 0x0C8,
+ 0x0FA, 0x0A7, 0x0AD, 0x041, 0x00A, 0x047, 0x0D5, 0x03D,
+ 0x068, 0x0AC, 0x0F1, 0x0F5, 0x04F, 0x05A, 0x097, 0x054,
+ 0x07D, 0x04F, 0x0A8, 0x0AA, 0x055, 0x01F, 0x011, 0x073,
+ 0x05A, 0x0B0, 0x017, 0x0DE, 0x05D, 0x059, 0x0A9, 0x025,
+ 0x0D0, 0x055, 0x02A, 0x046, 0x0BC, 0x0B8, 0x022, 0x0AE,
+ 0x045, 0x029, 0x03E, 0x014, 0x0FA, 0x0E1, 0x099, 0x094,
+ 0x0CA, 0x04A, 0x0BE, 0x03D, 0x0D6, 0x099, 0x092, 0x05D,
+ 0x015, 0x017, 0x0C8, 0x0D7, 0x0DC, 0x015, 0x017, 0x08A,
+ 0x040, 0x01F, 0x00A, 0x09E, 0x0AC, 0x0C9, 0x065, 0x049,
+ 0x05C, 0x01D, 0x010, 0x068, 0x04A, 0x03E, 0x05B, 0x0DE,
+ 0x083, 0x016, 0x095, 0x080, 0x0BE, 0x091, 0x074, 0x058,
+ 0x0A4, 0x000, 0x07C, 0x038, 0x0E7, 0x056, 0x030, 0x017,
+ 0x0DF, 0x075, 0x0A6, 0x064, 0x097, 0x045, 0x020, 0x09D,
+ 0x003, 0x05F, 0x070, 0x054, 0x05E, 0x029, 0x01D, 0x0F0,
+ 0x0A9, 0x0EA, 0x0CC, 0x086, 0x054, 0x095, 0x0C1, 0x0D1,
+ 0x006, 0x083, 0x00F, 0x0AA, 0x07B, 0x0D0, 0x065, 0x049,
+ 0x045, 0x0BD, 0x0E9, 0x062, 0x0D2, 0x091, 0x0DF, 0x004,
+ 0x05D, 0x016, 0x029, 0x01C, 0x07D, 0x04F, 0x0AC, 0x01A,
+ 0x047, 0x01A, 0x0A9, 0x0F5, 0x067, 0x066, 0x053, 0x028,
+ 0x0B7, 0x0BD, 0x02C, 0x05A, 0x052, 0x03B, 0x0E3, 0x0DD,
+ 0x059, 0x0A9, 0x025, 0x0D1, 0x0A8, 0x0AC, 0x008, 0x06B,
+ 0x0EE, 0x008, 0x0AB, 0x0C5, 0x020, 0x02F, 0x085, 0x04F,
+ 0x056, 0x066, 0x075, 0x049, 0x05C, 0x01C, 0x018, 0x01D,
+ 0x081, 0x0C2, 0x064, 0x005, 0x0F0, 0x080, 0x0BE, 0x035,
+ 0x05C, 0x0D0, 0x017, 0x0C2, 0x055, 0x0F0, 0x095, 0x07C,
+ 0x025, 0x05F, 0x008, 0x00B, 0x0E1, 0x001, 0x07C, 0x07B,
+ 0x0AB, 0x035, 0x024, 0x0BA, 0x010, 0x055, 0x093, 0x01A,
+ 0x0FB, 0x082, 0x02A, 0x0F1, 0x048, 0x0D7, 0x0C2, 0x0A7,
+ 0x0AB, 0x031, 0x0B2, 0x0A4, 0x0AC, 0x063, 0x09D, 0x04A,
+ 0x08D, 0x07C, 0x07B, 0x0AB, 0x035, 0x024, 0x0BA, 0x010,
+ 0x054, 0x030, 0x08D, 0x07D, 0x0C1, 0x015, 0x078, 0x0AC,
+ 0x06F, 0x05A, 0x094, 0x060, 0x01A, 0x0E3, 0x079, 0x0D4,
+ 0x0AA, 0x04F, 0x085, 0x04F, 0x056, 0x066, 0x0D5, 0x049,
+ 0x058, 0x0C7, 0x03A, 0x095, 0x049, 0x0F0, 0x045, 0x0D1,
+ 0x062, 0x094, 0x086, 0x0BC, 0x01D, 0x013, 0x0D2, 0x090,
+ 0x0FF, 0x0CF, 0x07A, 0x083, 0x0F2, 0x050, 0x031, 0x0DE,
+ 0x000, 0x060, 0x060, 0x0A1, 0x017, 0x035, 0x0A8, 0x05F,
+ 0x09B, 0x01B, 0x037, 0x007, 0x044, 0x01A, 0x030, 0x00B,
+ 0x038, 0x00D, 0x0BC, 0x01C, 0x0E0, 0x0D0, 0x047, 0x0CE,
+ 0x0A0, 0x0AA, 0x07A, 0x0A1, 0x098, 0x06A, 0x092, 0x095,
+ 0x03D, 0x068, 0x031, 0x080, 0x05B, 0x080, 0x0DA, 0x0A9,
+ 0x0EF, 0x041, 0x095, 0x025, 0x016, 0x0F7, 0x0A5, 0x08B,
+ 0x04A, 0x0C6, 0x079, 0x0B3, 0x033, 0x060, 0x02F, 0x0AA,
+ 0x09E, 0x0B1, 0x051, 0x080, 0x059, 0x09E, 0x0CA, 0x0A7,
+ 0x0AC, 0x00A, 0x030, 0x00B, 0x067, 0x0B2, 0x0AD, 0x0D5,
+ 0x0DA, 0x092, 0x05D, 0x017, 0x0A3, 0x000, 0x0B3, 0x02D,
+ 0x095, 0x06E, 0x008, 0x0A9, 0x058, 0x0A1, 0x017, 0x03A,
+ 0x08B, 0x001, 0x07D, 0x054, 0x0F7, 0x08E, 0x095, 0x025,
+ 0x008, 0x01C, 0x0E0, 0x056, 0x002, 0x0FB, 0x0C1, 0x0D1,
+ 0x015, 0x018, 0x005, 0x092, 0x06B, 0x03C, 0x01D, 0x012,
+ 0x028, 0x0C0, 0x02C, 0x0A5, 0x06C, 0x011, 0x070, 0x017,
+ 0x0B2, 0x038, 0x04D, 0x080, 0x0BE, 0x0E0, 0x02F, 0x0B4,
+ 0x0EC, 0x04A, 0x0ED, 0x0B3, 0x09E, 0x002, 0x0FB, 0x080,
+ 0x0BE, 0x0E0, 0x02F, 0x0B1, 0x039, 0x093, 0x03E, 0x06D,
+ 0x0E7, 0x010, 0x060, 0x09F, 0x032, 0x0A9, 0x0A2, 0x06C,
+ 0x005, 0x0F4, 0x040, 0x0E6, 0x00A, 0x095, 0x03D, 0x06A,
+ 0x023, 0x000, 0x0B3, 0x080, 0x0DA, 0x0A7, 0x0D6, 0x02A,
+ 0x003, 0x00D, 0x070, 0x017, 0x0D2, 0x02E, 0x076, 0x029,
+ 0x04F, 0x0BC, 0x054, 0x0A6, 0x051, 0x06F, 0x07A, 0x058,
+ 0x0B4, 0x0AC, 0x005, 0x0F4, 0x08B, 0x0A2, 0x0F4, 0x00E,
+ 0x035, 0x00D, 0x049, 0x02E, 0x0B4, 0x0CC, 0x018, 0x0A5,
+ 0x0C8, 0x0F8, 0x04A, 0x097, 0x023, 0x0E1, 0x005, 0x02E,
+ 0x047, 0x0C2, 0x08A, 0x05C, 0x08F, 0x085, 0x069, 0x072,
+ 0x03E, 0x01F, 0x04A, 0x0C3, 0x055, 0x01F, 0x056, 0x043,
+ 0x032, 0x08C, 0x0A3, 0x05E, 0x060, 0x0A8, 0x045, 0x0CE,
+ 0x00D, 0x060, 0x02F, 0x0A3, 0x084, 0x09D, 0x0D8, 0x0F0,
+ 0x017, 0x0D2, 0x02E, 0x00E, 0x01B, 0x023, 0x084, 0x0D8,
+ 0x00B, 0x0EB, 0x089, 0x0F3, 0x080, 0x0BE, 0x0E0, 0x02F,
+ 0x0BB, 0x039, 0x085, 0x0DF, 0x022, 0x003, 0x0E7, 0x001,
+ 0x07D, 0x0C0, 0x05F, 0x070, 0x017, 0x0D1, 0x017, 0x038,
+ 0x014, 0x05B, 0x0D6, 0x0A2, 0x074, 0x00D, 0x04B, 0x07A,
+ 0x0B3, 0x031, 0x096, 0x094, 0x06B, 0x0CC, 0x035, 0x023,
+ 0x0D7, 0x049, 0x048, 0x015, 0x073, 0x029, 0x00F, 0x05D,
+ 0x08A, 0x0C0, 0x05F, 0x04D, 0x079, 0x084, 0x035, 0x080,
+ 0x0BE, 0x088, 0x01C, 0x0C3, 0x052, 0x09F, 0x059, 0x068,
+ 0x0C0, 0x02C, 0x0E0, 0x036, 0x0AA, 0x07B, 0x0CD, 0x04A,
+ 0x092, 0x0BE, 0x0F3, 0x081, 0x04A, 0x07D, 0x05B, 0x059,
+ 0x094, 0x0CA, 0x01C, 0x024, 0x0EE, 0x0C7, 0x080, 0x0BE,
+ 0x088, 0x01C, 0x0C3, 0x052, 0x09F, 0x059, 0x068, 0x0C0,
+ 0x02C, 0x0E0, 0x036, 0x0AA, 0x07B, 0x0CD, 0x04A, 0x092,
+ 0x0BE, 0x0F3, 0x081, 0x043, 0x084, 0x09C, 0x07B, 0x038,
+ 0x00B, 0x0EB, 0x0AF, 0x070, 0x0D4, 0x0EA, 0x053, 0x000,
+ 0x09B, 0x04F, 0x09C, 0x054, 0x030, 0x0F3, 0x08A, 0x094,
+ 0x0FA, 0x0B6, 0x0B3, 0x029, 0x094, 0x022, 0x0E6, 0x01A,
+ 0x085, 0x0F9, 0x0B0, 0x059, 0x093, 0x0F9, 0x0D2, 0x0C4,
+ 0x032, 0x060, 0x0B9, 0x036, 0x0B0, 0x0B3, 0x090, 0x0D9,
+ 0x077, 0x026, 0x01C, 0x027, 0x022, 0x0E8, 0x096, 0x0B4,
+ 0x023, 0x0EA, 0x09E, 0x0B5, 0x011, 0x080, 0x059, 0x065,
+ 0x086, 0x020, 0x073, 0x096, 0x08D, 0x079, 0x0AD, 0x058,
+ 0x00B, 0x0E9, 0x017, 0x044, 0x08A, 0x04A, 0x007, 0x0D7,
+ 0x07A, 0x082, 0x0A1, 0x090, 0x0FA, 0x0EF, 0x001, 0x054,
+ 0x0BA, 0x050, 0x0D4, 0x059, 0x01E, 0x02C, 0x0E9, 0x0F3,
+ 0x08A, 0x099, 0x085, 0x06B, 0x00B, 0x023, 0x015, 0x097,
+ 0x072, 0x061, 0x017, 0x030, 0x0D4, 0x02C, 0x073, 0x087,
+ 0x048, 0x0AA, 0x002, 0x081, 0x025, 0x0DE, 0x091, 0x00D,
+ 0x04A, 0x0C0, 0x05F, 0x07E, 0x0D2, 0x080, 0x0A5, 0x03E,
+ 0x0B2, 0x0D0, 0x0C8, 0x06B, 0x080, 0x0BE, 0x088, 0x01C,
+ 0x0EA, 0x009, 0x017, 0x044, 0x01A, 0x037, 0x01A, 0x091,
+ 0x074, 0x058, 0x0A3, 0x071, 0x0AF, 0x007, 0x044, 0x054,
+ 0x06E, 0x035, 0x0E0, 0x0E8, 0x0AA, 0x064, 0x00F, 0x090,
+ 0x0FA, 0x0D0, 0x063, 0x000, 0x0B3, 0x080, 0x0DA, 0x02C,
+ 0x073, 0x087, 0x048, 0x0AA, 0x002, 0x081, 0x025, 0x0DE,
+ 0x091, 0x00D, 0x04A, 0x0C0, 0x05F, 0x048, 0x0BA, 0x027,
+ 0x0A3, 0x000, 0x0B7, 0x001, 0x0B7, 0x04F, 0x09C, 0x0B4,
+ 0x06B, 0x0CC, 0x035, 0x016, 0x0F5, 0x066, 0x063, 0x02D,
+ 0x029, 0x01E, 0x0BA, 0x04A, 0x040, 0x0AB, 0x099, 0x048,
+ 0x07A, 0x0EC, 0x050, 0x08B, 0x09C, 0x008, 0x022, 0x0FC,
+ 0x0F9, 0x0B2, 0x055, 0x03D, 0x062, 0x0A9, 0x023, 0x051,
+ 0x023, 0x09C, 0x00A, 0x03C, 0x073, 0x00D, 0x044, 0x05C,
+ 0x0E1, 0x050, 0x071, 0x0CE, 0x0A1, 0x01F, 0x0E7, 0x015,
+ 0x06B, 0x00B, 0x025, 0x0ED, 0x00B, 0x093, 0x060, 0x02F,
+ 0x0AA, 0x09E, 0x0AC, 0x036, 0x065, 0x049, 0x05F, 0x07A,
+ 0x020, 0x050, 0x008, 0x07F, 0x0EF, 0x039, 0x014, 0x049,
+ 0x001, 0x011, 0x081, 0x004, 0x060, 0x040, 0x0CC, 0x059,
+ 0x0C0, 0x0AD, 0x023, 0x0EB, 0x041, 0x0B0, 0x081, 0x0F2,
+ 0x03A, 0x041, 0x0AA, 0x050, 0x043, 0x0E4, 0x0D4, 0x086,
+ 0x054, 0x0A0, 0x087, 0x0C1, 0x052, 0x0CA, 0x093, 0x001,
+ 0x032, 0x054, 0x09D, 0x024, 0x002, 0x000, 0x000, 0x052,
+ 0x0AF, 0x016, 0x046, 0x0A7, 0x091, 0x067, 0x008, 0x0B4,
+ 0x004, 0x051, 0x0F1, 0x065, 0x019, 0x0B4, 0x06E, 0x02D,
+ 0x0C0, 0x0AD, 0x049, 0x000, 0x092, 0x057, 0x01B, 0x074,
+ 0x045, 0x05F, 0x023, 0x051, 0x0B7, 0x044, 0x00A, 0x010,
+ 0x006, 0x0A3, 0x06E, 0x08B, 0x06B, 0x008, 0x01F, 0x019,
+ 0x0D1, 0x0E6, 0x080, 0x082, 0x080, 0x054, 0x004, 0x02A,
+ 0x045, 0x091, 0x0A9, 0x0E4, 0x059, 0x0C2, 0x02D, 0x001,
+ 0x014, 0x004, 0x050, 0x0D3, 0x0FC, 0x055, 0x084, 0x061,
+ 0x0D9, 0x080, 0x051, 0x02F, 0x0E2, 0x01F, 0x046, 0x05F,
+ 0x040, 0x0E0, 0x020, 0x015, 0x04A, 0x0BC, 0x059, 0x01A,
+ 0x09E, 0x045, 0x09C, 0x022, 0x0D0, 0x011, 0x048, 0x0CB,
+ 0x0E8, 0x014, 0x008, 0x001, 0x054, 0x015, 0x0E2, 0x0C8,
+ 0x0D4, 0x0F2, 0x02C, 0x0E1, 0x016, 0x080, 0x08A, 0x046,
+ 0x05F, 0x052, 0x07C, 0x0D9, 0x0A8, 0x0F8, 0x088, 0x0D0,
+ 0x05A, 0x03C, 0x0D2, 0x05C, 0x05B, 0x080, 0x0DA, 0x0A7,
+ 0x0D6, 0x05A, 0x008, 0x086, 0x0A4, 0x05D, 0x017, 0x0A0,
+ 0x0C3, 0x052, 0x02E, 0x088, 0x0A8, 0x022, 0x01F, 0x053,
+ 0x0EA, 0x0DA, 0x0CC, 0x0A6, 0x050, 0x0E1, 0x027, 0x076,
+ 0x03C, 0x005, 0x0F5, 0x04F, 0x0AB, 0x06B, 0x032, 0x099,
+ 0x043, 0x084, 0x09C, 0x07B, 0x038, 0x00B, 0x0E9, 0x027,
+ 0x0AC, 0x0D4, 0x092, 0x0E0, 0x00E, 0x0DA, 0x038, 0x04D,
+ 0x080, 0x0BE, 0x0E6, 0x07D, 0x050, 0x0BA, 0x051, 0x0AE,
+ 0x066, 0x0EF, 0x0BC, 0x0DC, 0x07B, 0x087, 0x01E, 0x002,
+ 0x0FA, 0x093, 0x0E6, 0x0CD, 0x047, 0x0C4, 0x043, 0x0CD,
+ 0x00F, 0x034, 0x09D, 0x0A3, 0x000, 0x0B0, 0x055, 0x001,
+ 0x0AE, 0x003, 0x084, 0x004, 0x0CE, 0x001, 0x0D0, 0x0E1,
+ 0x070, 0x002, 0x080, 0x00E, 0x089, 0x0E9, 0x022, 0x01F,
+ 0x0E0, 0x0E8, 0x096, 0x0B0, 0x011, 0x0F4, 0x0C2, 0x0CE,
+ 0x003, 0x06A, 0x044, 0x02D, 0x0C0, 0x06D, 0x048, 0x005,
+ 0x0B8, 0x00D, 0x0A3, 0x000, 0x0B7, 0x076, 0x0D5, 0x0DE,
+ 0x0B1, 0x050, 0x0DC, 0x07D, 0x077, 0x0BC, 0x054, 0x0BA,
+ 0x052, 0x07F, 0x058, 0x014, 0x034, 0x00F, 0x09A, 0x0F3,
+ 0x081, 0x058, 0x00B, 0x0EA, 0x0EF, 0x058, 0x014, 0x060,
+ 0x016, 0x0A5, 0x06C, 0x02E, 0x0F7, 0x081, 0x04B, 0x0A5,
+ 0x06F, 0x07D, 0x05D, 0x0EE, 0x0B5, 0x02E, 0x095, 0x080,
+ 0x0BE, 0x0F0, 0x073, 0x0BD, 0x004, 0x07C, 0x0EA, 0x0FE,
+ 0x0EB, 0x04C, 0x0DE, 0x029, 0x053, 0x0DD, 0x06A, 0x054,
+ 0x094, 0x0A9, 0x0EA, 0x00A, 0x08C, 0x002, 0x0D6, 0x04C,
+ 0x03C, 0x005, 0x0F4, 0x000, 0x0EA, 0x0CD, 0x056, 0x0AF,
+ 0x0C0, 0x047, 0x0D2, 0x09C, 0x08D, 0x029, 0x0CA, 0x0E0,
+ 0x02F, 0x0AE, 0x0BD, 0x075, 0x099, 0x09D, 0x04A, 0x0F9,
+ 0x0EF, 0x051, 0x07C, 0x094, 0x00C, 0x077, 0x080, 0x018,
+ 0x018, 0x029, 0x02A, 0x0F8, 0x0E0, 0x0E8, 0x0AA, 0x030,
+ 0x00B, 0x02A, 0x098, 0x07C, 0x01D, 0x011, 0x051, 0x080,
+ 0x059, 0x054, 0x0C3, 0x051, 0x0F5, 0x01B, 0x033, 0x024,
+ 0x0BB, 0x082, 0x0A5, 0x019, 0x05C, 0x01D, 0x010, 0x028,
+ 0x0C0, 0x02C, 0x09A, 0x0C7, 0x0C1, 0x0D1, 0x022, 0x08C,
+ 0x002, 0x0C9, 0x094, 0x064, 0x05C, 0x00C, 0x0D6, 0x08E,
+ 0x013, 0x060, 0x02F, 0x0B8, 0x00B, 0x0EA, 0x030, 0x0E3,
+ 0x0C0, 0x05F, 0x048, 0x0DC, 0x078, 0x00B, 0x0E8, 0x000,
+ 0x0E3, 0x0C0, 0x05F, 0x06C, 0x038, 0x0D5, 0x02E, 0x035,
+ 0x04F, 0x05A, 0x08A, 0x061, 0x0AA, 0x09F, 0x056, 0x01B,
+ 0x032, 0x099, 0x046, 0x042, 0x0C8, 0x001, 0x00C, 0x045,
+ 0x0CE, 0x0A5, 0x017, 0x0E6, 0x0C6, 0x0CE, 0x0A9, 0x0EB,
+ 0x015, 0x016, 0x046, 0x0A2, 0x047, 0x038, 0x014, 0x043,
+ 0x026, 0x022, 0x0E7, 0x03D, 0x060, 0x02F, 0x0AA, 0x09E,
+ 0x0B5, 0x012, 0x0E0, 0x07F, 0x001, 0x07D, 0x0E3, 0x0E7,
+ 0x002, 0x093, 0x0F9, 0x095, 0x044, 0x05C, 0x0E5, 0x0A0,
+ 0x0E3, 0x09D, 0x04A, 0x07F, 0x09C, 0x054, 0x0A9, 0x0EB,
+ 0x051, 0x005, 0x046, 0x0B9, 0x0FC, 0x0C0, 0x01B, 0x022,
+ 0x02E, 0x064, 0x054, 0x02F, 0x0CD, 0x046, 0x0CC, 0x0A7,
+ 0x0D5, 0x086, 0x0CC, 0x0A6, 0x050, 0x055, 0x0C6, 0x045,
+ 0x0CE, 0x05A, 0x00E, 0x039, 0x0D4, 0x0A7, 0x0F9, 0x0C5,
+ 0x04A, 0x09E, 0x0B5, 0x011, 0x080, 0x059, 0x0C0, 0x06D,
+ 0x0CF, 0x0E6, 0x000, 0x0D9, 0x011, 0x073, 0x022, 0x0A1,
+ 0x07E, 0x06A, 0x036, 0x065, 0x03E, 0x0AC, 0x036, 0x065,
+ 0x032, 0x0B0, 0x017, 0x0DD, 0x03E, 0x072, 0x0D2, 0x079,
+ 0x031, 0x00C, 0x098, 0x02E, 0x04C, 0x020, 0x073, 0x02A,
+ 0x08F, 0x0F3, 0x08A, 0x0AD, 0x0E7, 0x041, 0x082, 0x07C,
+ 0x0CA, 0x0A6, 0x089, 0x0B5, 0x085, 0x09F, 0x0B0, 0x0F0,
+ 0x017, 0x0D5, 0x01F, 0x054, 0x054, 0x025, 0x01A, 0x0A8,
+ 0x0FF, 0x02A, 0x094, 0x065, 0x011, 0x0D7, 0x049, 0x044,
+ 0x0D5, 0x0CC, 0x0A0, 0x055, 0x0D8, 0x0AE, 0x00E, 0x088,
+ 0x014, 0x060, 0x016, 0x04D, 0x063, 0x022, 0x0E0, 0x072,
+ 0x086, 0x038, 0x04D, 0x080, 0x0BE, 0x0E0, 0x02F, 0x0B8,
+ 0x00B, 0x0EE, 0x002, 0x0FB, 0x081, 0x038, 0x0F0, 0x017,
+ 0x0D7, 0x0D7, 0x01E, 0x002, 0x0FA, 0x0FA, 0x0E3, 0x0C0,
+ 0x05F, 0x04C, 0x085, 0x090, 0x002, 0x018, 0x0C8, 0x05B,
+ 0x080, 0x0DA, 0x030, 0x00B, 0x070, 0x01B, 0x04C, 0x022,
+ 0x0D3, 0x04C, 0x033, 0x003, 0x08C, 0x02E, 0x04C, 0x043,
+ 0x026, 0x0D0, 0x0F5, 0x063, 0x066, 0x0D0, 0x095, 0x0A7,
+ 0x0CE, 0x045, 0x033, 0x00A, 0x0D6, 0x016, 0x042, 0x038,
+ 0x06E, 0x0E4, 0x0CE, 0x0BD, 0x059, 0x02C, 0x0D2, 0x0AB,
+ 0x0BA, 0x094, 0x09D, 0x0E6, 0x01A, 0x0B0, 0x017, 0x0D5,
+ 0x04F, 0x05A, 0x08B, 0x009, 0x01A, 0x088, 0x0B9, 0x0C5,
+ 0x042, 0x047, 0x030, 0x0D4, 0x032, 0x016, 0x072, 0x088,
+ 0x065, 0x0BD, 0x059, 0x099, 0x025, 0x0A5, 0x060, 0x02F,
+ 0x0B8, 0x060, 0x0F3, 0x008, 0x0B7, 0x04A, 0x01A, 0x08F,
+ 0x0AB, 0x00D, 0x099, 0x046, 0x051, 0x0AF, 0x038, 0x0A8,
+ 0x08E, 0x090, 0x065, 0x013, 0x052, 0x018, 0x0A0, 0x054,
+ 0x0B1, 0x042, 0x02E, 0x061, 0x0A8, 0x048, 0x0E7, 0x02D,
+ 0x016, 0x0F7, 0x0A8, 0x005, 0x0A5, 0x060, 0x02F, 0x0A4,
+ 0x075, 0x0D2, 0x051, 0x035, 0x073, 0x028, 0x015, 0x076,
+ 0x02B, 0x083, 0x0A2, 0x005, 0x018, 0x005, 0x093, 0x058,
+ 0x0C8, 0x0B8, 0x006, 0x028, 0x063, 0x084, 0x0D8, 0x00B,
+ 0x0EE, 0x002, 0x0FB, 0x080, 0x0BE, 0x0E0, 0x02F, 0x0A0,
+ 0x043, 0x0A7, 0x001, 0x07D, 0x04C, 0x0E3, 0x0C0, 0x05F,
+ 0x070, 0x017, 0x0DC, 0x005, 0x0F4, 0x064, 0x02D, 0x0C0,
+ 0x06D, 0x018, 0x005, 0x0B8, 0x00D, 0x0A5, 0x0BD, 0x06A,
+ 0x023, 0x086, 0x0AA, 0x09E, 0x0B5, 0x011, 0x0A4, 0x06A,
+ 0x0A3, 0x0EA, 0x08A, 0x08D, 0x023, 0x0E1, 0x017, 0x038,
+ 0x034, 0x069, 0x071, 0x098, 0x045, 0x0A6, 0x098, 0x06A,
+ 0x03E, 0x0AC, 0x036, 0x065, 0x019, 0x046, 0x0BC, 0x0E2,
+ 0x0A2, 0x03A, 0x041, 0x094, 0x04D, 0x048, 0x062, 0x081,
+ 0x052, 0x0C5, 0x016, 0x0F7, 0x0A8, 0x08B, 0x04A, 0x054,
+ 0x0F5, 0x0A8, 0x08C, 0x002, 0x0DC, 0x006, 0x0D1, 0x003,
+ 0x09C, 0x0B4, 0x0A9, 0x0EE, 0x00A, 0x095, 0x025, 0x02A,
+ 0x07A, 0x0AD, 0x046, 0x001, 0x067, 0x001, 0x0B5, 0x0D7,
+ 0x0AC, 0x00A, 0x030, 0x00B, 0x06C, 0x049, 0x035, 0x0E6,
+ 0x0B5, 0x067, 0x0F3, 0x000, 0x06C, 0x088, 0x0B9, 0x091,
+ 0x050, 0x0BF, 0x031, 0x01B, 0x032, 0x0A7, 0x0B8, 0x068,
+ 0x095, 0x025, 0x07B, 0x0AD, 0x033, 0x078, 0x0A7, 0x0CD,
+ 0x03E, 0x0D3, 0x08E, 0x09D, 0x034, 0x0E7, 0x04E, 0x0D4,
+ 0x022, 0x0E7, 0x006, 0x084, 0x08E, 0x060, 0x0A8, 0x0FF,
+ 0x038, 0x0AB, 0x083, 0x09C, 0x02A, 0x008, 0x0F9, 0x0D4,
+ 0x020, 0x063, 0x0BC, 0x01A, 0x006, 0x00A, 0x0C0, 0x05F,
+ 0x046, 0x042, 0x0DC, 0x006, 0x0D1, 0x080, 0x05B, 0x080,
+ 0x0DA, 0x022, 0x0E6, 0x01A, 0x084, 0x08E, 0x072, 0x0D1,
+ 0x06F, 0x05A, 0x080, 0x087, 0x01A, 0x0AA, 0x07A, 0x0D4,
+ 0x048, 0x0C8, 0x0D5, 0x047, 0x0D5, 0x015, 0x023, 0x023,
+ 0x0E1, 0x017, 0x038, 0x034, 0x08C, 0x0BA, 0x04B, 0x07B,
+ 0x0D4, 0x002, 0x0D2, 0x08C, 0x022, 0x0DC, 0x006, 0x0D5,
+ 0x01F, 0x056, 0x01B, 0x032, 0x08C, 0x0A3, 0x05E, 0x071,
+ 0x051, 0x01D, 0x020, 0x0CA, 0x026, 0x0A4, 0x031, 0x040,
+ 0x0A9, 0x062, 0x0B0, 0x017, 0x0DF, 0x09E, 0x0F4, 0x0B7,
+ 0x0C9, 0x040, 0x0C7, 0x078, 0x001, 0x081, 0x082, 0x0B8,
+ 0x038, 0x039, 0x049, 0x01C, 0x026, 0x0C0, 0x05F, 0x070,
+ 0x017, 0x0D4, 0x0AB, 0x0E1, 0x02A, 0x0F8, 0x04A, 0x0BE,
+ 0x012, 0x0AF, 0x08F, 0x097, 0x04F, 0x0CB, 0x0A7, 0x001,
+ 0x07D, 0x0DA, 0x080, 0x0AA, 0x091, 0x064, 0x07F, 0x04A,
+ 0x081, 0x0D5, 0x022, 0x0C8, 0x0FE, 0x082, 0x080, 0x025,
+ 0x048, 0x0B2, 0x03E, 0x0BB, 0x0DC, 0x035, 0x02E, 0x094,
+ 0x007, 0x0E8, 0x08A, 0x09C, 0x003, 0x0E2, 0x04B, 0x0A5,
+ 0x077, 0x0AB, 0x0B3, 0x032, 0x0E9, 0x04B, 0x0BD, 0x059,
+ 0x086, 0x084, 0x097, 0x07A, 0x004, 0x0BA, 0x053, 0x0E1,
+ 0x032, 0x0EF, 0x050, 0x0D4, 0x0E6, 0x035, 0x053, 0x0EB,
+ 0x002, 0x09C, 0x0C7, 0x0D7, 0x07A, 0x0B3, 0x030, 0x0D2,
+ 0x05D, 0x0EA, 0x002, 0x0E9, 0x044, 0x05D, 0x016, 0x028,
+ 0x0C0, 0x02C, 0x0E0, 0x036, 0x091, 0x074, 0x045, 0x059,
+ 0x018, 0x0D5, 0x04F, 0x0AC, 0x00A, 0x0C4, 0x035, 0x030,
+ 0x08B, 0x038, 0x069, 0x02B, 0x0BD, 0x059, 0x098, 0x069,
+ 0x02E, 0x0F5, 0x012, 0x0E9, 0x058, 0x067, 0x04A, 0x0EF,
+ 0x050, 0x0D5, 0x08E, 0x03E, 0x01C, 0x0A4, 0x0B0, 0x0CE,
+ 0x093, 0x021, 0x06E, 0x01A, 0x048, 0x01F, 0x0A2, 0x02A,
+ 0x0C3, 0x00D, 0x057, 0x07A, 0x0B3, 0x00D, 0x009, 0x02E,
+ 0x0F4, 0x043, 0x05D, 0x028, 0x08B, 0x083, 0x020, 0x092,
+ 0x038, 0x04D, 0x080, 0x0BE, 0x0E0, 0x02F, 0x0AC, 0x017,
+ 0x049, 0x0B3, 0x0A5, 0x082, 0x0E9, 0x03E, 0x0E9, 0x036,
+ 0x074, 0x0E0, 0x02F, 0x0A6, 0x0CE, 0x09C, 0x005, 0x0F4,
+ 0x0C2, 0x02C, 0x08C, 0x052, 0x057, 0x07A, 0x0D4, 0x08D,
+ 0x048, 0x0FA, 0x0EF, 0x050, 0x0D5, 0x0AE, 0x035, 0x053,
+ 0x0EB, 0x002, 0x086, 0x021, 0x0AA, 0x0EF, 0x056, 0x066,
+ 0x01A, 0x04B, 0x0BD, 0x044, 0x0BA, 0x050, 0x0C4, 0x0E9,
+ 0x053, 0x0EB, 0x002, 0x086, 0x081, 0x0F5, 0x0DE, 0x0A1,
+ 0x0A8, 0x062, 0x01F, 0x05D, 0x0FE, 0x0A2, 0x05D, 0x029,
+ 0x077, 0x0A8, 0x06A, 0x061, 0x08D, 0x040, 0x0FD, 0x011,
+ 0x053, 0x00C, 0x06A, 0x0A7, 0x0D6, 0x005, 0x030, 0x0C7,
+ 0x0D7, 0x07F, 0x0A9, 0x057, 0x04A, 0x05D, 0x0EB, 0x048,
+ 0x01B, 0x00C, 0x07C, 0x08B, 0x09D, 0x08A, 0x053, 0x0EF,
+ 0x066, 0x094, 0x0CA, 0x054, 0x0F5, 0x0A0, 0x0C6, 0x001,
+ 0x06E, 0x003, 0x06A, 0x09F, 0x056, 0x076, 0x065, 0x032,
+ 0x08B, 0x07B, 0x0D2, 0x0C5, 0x0A5, 0x060, 0x02F, 0x0AA,
+ 0x07D, 0x065, 0x0A3, 0x000, 0x0B7, 0x001, 0x0B4, 0x0C8,
+ 0x05A, 0x007, 0x08F, 0x0ED, 0x001, 0x0D5, 0x027, 0x091,
+ 0x067, 0x001, 0x0B4, 0x08B, 0x09C, 0x054, 0x01C, 0x073,
+ 0x0A8, 0x084, 0x05C, 0x0C1, 0x050, 0x0BF, 0x036, 0x056,
+ 0x060, 0x0AB, 0x08C, 0x08B, 0x09C, 0x054, 0x01C, 0x073,
+ 0x0A8, 0x084, 0x05C, 0x0C1, 0x050, 0x0BF, 0x036, 0x056,
+ 0x06C, 0x005, 0x0F5, 0x053, 0x0D6, 0x0A2, 0x030, 0x00B,
+ 0x029, 0x05B, 0x019, 0x0FC, 0x0F6, 0x094, 0x045, 0x0CF,
+ 0x015, 0x00B, 0x0F3, 0x03C, 0x0B3, 0x02A, 0x07A, 0x0C5,
+ 0x046, 0x001, 0x064, 0x08A, 0x031, 0x023, 0x09C, 0x00A,
+ 0x05D, 0x0EA, 0x034, 0x033, 0x02E, 0x095, 0x0C7, 0x0CE,
+ 0x02A, 0x04F, 0x0E6, 0x050, 0x020, 0x0B9, 0x031, 0x00C,
+ 0x09B, 0x0EF, 0x039, 0x014, 0x045, 0x0CE, 0x045, 0x007,
+ 0x01C, 0x0EA, 0x046, 0x087, 0x0AB, 0x01B, 0x036, 0x084,
+ 0x0A7, 0x05E, 0x0AC, 0x096, 0x067, 0x052, 0x0B0, 0x017,
+ 0x0DC, 0x0FE, 0x07B, 0x04A, 0x022, 0x0E7, 0x08A, 0x085,
+ 0x0F9, 0x09E, 0x059, 0x097, 0x07A, 0x08D, 0x00C, 0x0CB,
+ 0x0A5, 0x027, 0x0F3, 0x0A0, 0x044, 0x032, 0x060, 0x0B9,
+ 0x037, 0x0DE, 0x072, 0x028, 0x08B, 0x09C, 0x08A, 0x00E,
+ 0x039, 0x0D4, 0x08C, 0x005, 0x0F7, 0x0E7, 0x0B8, 0x02A,
+ 0x0F9, 0x028, 0x018, 0x0EF, 0x000, 0x030, 0x030, 0x057,
+ 0x007, 0x044, 0x00A, 0x050, 0x08F, 0x0F0, 0x073, 0x091,
+ 0x041, 0x01F, 0x03A, 0x090, 0x045, 0x0C0, 0x0BB, 0x018,
+ 0x0E1, 0x036, 0x002, 0x0FB, 0x0FB, 0x09E, 0x002, 0x0FA,
+ 0x0EE, 0x0E7, 0x0F5, 0x0CF, 0x001, 0x07D, 0x010, 0x05C,
+ 0x0F0, 0x017, 0x0D1, 0x005, 0x0CF, 0x001, 0x07D, 0x053,
+ 0x0EB, 0x02D, 0x018, 0x005, 0x0B8, 0x00D, 0x0A6, 0x042,
+ 0x0DC, 0x006, 0x0D3, 0x017, 0x035, 0x0A8, 0x08B, 0x09C,
+ 0x00A, 0x00E, 0x039, 0x0D4, 0x00C, 0x0FE, 0x07B, 0x04A,
+ 0x022, 0x0E6, 0x055, 0x00B, 0x0F3, 0x031, 0x0B3, 0x060,
+ 0x02F, 0x0BC, 0x07C, 0x0E2, 0x0A4, 0x0FE, 0x065, 0x051,
+ 0x017, 0x038, 0x014, 0x01C, 0x073, 0x0A8, 0x019, 0x0FC,
+ 0x0F6, 0x094, 0x045, 0x0CC, 0x0AA, 0x017, 0x0E6, 0x063,
+ 0x066, 0x00A, 0x0B8, 0x0CC, 0x085, 0x0A1, 0x058, 0x0F6,
+ 0x0A2, 0x035, 0x048, 0x048, 0x07F, 0x04A, 0x089, 0x095,
+ 0x021, 0x021, 0x0FD, 0x005, 0x002, 0x054, 0x09E, 0x045,
+ 0x091, 0x00E, 0x03C, 0x005, 0x0F5, 0x007, 0x040, 0x055,
+ 0x048, 0x052, 0x03E, 0x086, 0x0A0, 0x075, 0x048, 0x052,
+ 0x03E, 0x0B5, 0x000, 0x04A, 0x09C, 0x000, 0x06B, 0x0C7,
+ 0x0CE, 0x045, 0x027, 0x0F3, 0x02A, 0x084, 0x037, 0x035,
+ 0x0DE, 0x0A0, 0x0AB, 0x023, 0x01A, 0x0AE, 0x0F5, 0x083,
+ 0x059, 0x018, 0x0D7, 0x043, 0x0DE, 0x02A, 0x0D0, 0x094,
+ 0x0EB, 0x0DE, 0x005, 0x03A, 0x095, 0x09F, 0x0CC, 0x0C3,
+ 0x020, 0x045, 0x0CC, 0x0AA, 0x017, 0x0E6, 0x066, 0x0CC,
+ 0x043, 0x026, 0x04F, 0x0E7, 0x041, 0x022, 0x02E, 0x070,
+ 0x068, 0x038, 0x0E7, 0x053, 0x0E0, 0x02F, 0x0AB, 0x0BC,
+ 0x012, 0x0D2, 0x0E9, 0x058, 0x00B, 0x0EA, 0x0A7, 0x0AD,
+ 0x045, 0x0A1, 0x01F, 0x0C0, 0x05F, 0x078, 0x039, 0x0C8,
+ 0x0A0, 0x08F, 0x09D, 0x048, 0x01C, 0x024, 0x0EE, 0x0C7,
+ 0x080, 0x0BE, 0x0BA, 0x0F5, 0x06D, 0x066, 0x049, 0x077,
+ 0x00D, 0x04E, 0x0A5, 0x030, 0x009, 0x0B4, 0x0F9, 0x0C5,
+ 0x043, 0x00F, 0x038, 0x0A9, 0x03F, 0x09D, 0x002, 0x0FB,
+ 0x0CE, 0x045, 0x011, 0x073, 0x091, 0x041, 0x0C7, 0x03A,
+ 0x091, 0x09F, 0x0CF, 0x069, 0x044, 0x05C, 0x0F1, 0x050,
+ 0x0BF, 0x033, 0x0CB, 0x032, 0x0A7, 0x0AC, 0x054, 0x090,
+ 0x08D, 0x044, 0x08E, 0x070, 0x029, 0x077, 0x0A8, 0x0D0,
+ 0x0CC, 0x0BA, 0x056, 0x0B0, 0x0B2, 0x09D, 0x08C, 0x086,
+ 0x04C, 0x017, 0x026, 0x077, 0x026, 0x01C, 0x027, 0x01C,
+ 0x024, 0x09E, 0x023, 0x061, 0x0BE, 0x08E, 0x012, 0x04F,
+ 0x011, 0x087, 0x01C, 0x0EA, 0x05C, 0x005, 0x0F5, 0x0D7,
+ 0x0B8, 0x06A, 0x075, 0x029, 0x077, 0x0AB, 0x00D, 0x099,
+ 0x074, 0x0A5, 0x04F, 0x072, 0x0A0, 0x0AA, 0x04A, 0x0C6,
+ 0x0F3, 0x066, 0x066, 0x0C6, 0x039, 0x082, 0x0AF, 0x075,
+ 0x0A6, 0x06F, 0x014, 0x06B, 0x0CE, 0x005, 0x070, 0x073,
+ 0x096, 0x082, 0x03E, 0x075, 0x028, 0x0E1, 0x03A, 0x0A7,
+ 0x0AD, 0x044, 0x060, 0x016, 0x052, 0x0B6, 0x01D, 0x07A,
+ 0x0B6, 0x0B3, 0x024, 0x0BB, 0x086, 0x0A7, 0x052, 0x098,
+ 0x004, 0x0DA, 0x07C, 0x0E2, 0x0A1, 0x087, 0x09C, 0x055,
+ 0x0F7, 0x09C, 0x0B5, 0x0AC, 0x02C, 0x095, 0x033, 0x0B9,
+ 0x031, 0x005, 0x0D9, 0x053, 0x0D6, 0x0A2, 0x030, 0x00B,
+ 0x029, 0x05B, 0x002, 0x02E, 0x061, 0x05A, 0x017, 0x0E6,
+ 0x09C, 0x0B3, 0x02A, 0x07A, 0x0C5, 0x040, 0x021, 0x0A8,
+ 0x091, 0x0CE, 0x005, 0x027, 0x0F3, 0x0A5, 0x088, 0x064,
+ 0x0C1, 0x072, 0x065, 0x04F, 0x058, 0x014, 0x00C, 0x08D,
+ 0x07E, 0x0F3, 0x081, 0x044, 0x05C, 0x0EF, 0x041, 0x0C7,
+ 0x03A, 0x0BE, 0x002, 0x0FA, 0x0A9, 0x0EA, 0x0CE, 0x0CC,
+ 0x0A9, 0x029, 0x053, 0x0D6, 0x0A2, 0x046, 0x047, 0x0DD,
+ 0x07A, 0x0C0, 0x0A3, 0x000, 0x086, 0x0E2, 0x09B, 0x029,
+ 0x078, 0x08B, 0x081, 0x009, 0x098, 0x070, 0x09B, 0x029,
+ 0x079, 0x05D, 0x0D9, 0x072, 0x0ED, 0x094, 0x0BC, 0x0B9,
+ 0x076, 0x013, 0x03B, 0x02A, 0x05D, 0x0B2, 0x097, 0x095,
+ 0x02E, 0x0D9, 0x04B, 0x0CA, 0x07D, 0x05B, 0x059, 0x094,
+ 0x0CA, 0x01C, 0x024, 0x0EE, 0x0C7, 0x094, 0x0BC, 0x0C0,
+ 0x026, 0x0D3, 0x0E7, 0x015, 0x00C, 0x03C, 0x0E2, 0x0AC,
+ 0x0FE, 0x07B, 0x04A, 0x022, 0x0E7, 0x08A, 0x085, 0x0F9,
+ 0x09E, 0x059, 0x097, 0x07A, 0x08D, 0x00C, 0x0CB, 0x0A5,
+ 0x027, 0x0F3, 0x0A0, 0x041, 0x072, 0x062, 0x019, 0x037,
+ 0x0DE, 0x070, 0x028, 0x08B, 0x09C, 0x08A, 0x00E, 0x039,
+ 0x0D4, 0x08D, 0x00F, 0x056, 0x036, 0x06D, 0x009, 0x04E,
+ 0x0BD, 0x059, 0x02C, 0x0CE, 0x0A5, 0x06B, 0x00B, 0x022,
+ 0x0D9, 0x09D, 0x0C9, 0x0B2, 0x097, 0x0BE, 0x0F3, 0x081,
+ 0x04A, 0x07D, 0x065, 0x0A3, 0x000, 0x093, 0x08F, 0x067,
+ 0x029, 0x078, 0x0C2, 0x04D, 0x0C1, 0x0D1, 0x006, 0x082,
+ 0x031, 0x0AF, 0x007, 0x038, 0x034, 0x011, 0x0F3, 0x0A8,
+ 0x02A, 0x09E, 0x0A8, 0x066, 0x01A, 0x0A4, 0x0A5, 0x04F,
+ 0x05A, 0x00C, 0x011, 0x08F, 0x0AA, 0x07B, 0x0D0, 0x065,
+ 0x049, 0x045, 0x0BD, 0x0E9, 0x062, 0x0D2, 0x0B1, 0x09E,
+ 0x06C, 0x0CC, 0x0C6, 0x019, 0x087, 0x009, 0x0C3, 0x08E,
+ 0x075, 0x041, 0x01F, 0x03A, 0x0A5, 0x013, 0x0D5, 0x055,
+ 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+ 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+ 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+ 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+ 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055, 0x055,
+ 0x055, 0x055, 0x055, 0x05A, 0x0CC, 0x090
+ };
+
+#endif /* defined(CONFIG_SMCTR) || defined(CONFIG_SMCTR_MODULE) */
* - David Hein at Texas Instruments
*
* Maintainer(s):
- * JS Jay Schulist jschlst@samba.anu.edu.au
+ * JS Jay Schulist jschlst@turbolinux.com
* CG Christoph Goos cgoos@syskonnect.de
* AF Adam Fritzler mid@auk.cx
*
pbus_set_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
{
struct pbus_set_ranges_data inner;
- struct pci_bus *child;
struct pci_dev *dev;
- struct list_node *ln;
+ struct list_head *ln;
inner.found_vga = 0;
inner.mem_start = inner.io_start = ~0UL;
void __init
pci_set_bus_ranges(void)
{
- struct list_node *ln;
+ struct list_head *ln;
for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next)
- pci_set_ranges(pci_bus_b(ln), NULL);
+ pbus_set_ranges(pci_bus_b(ln), NULL);
}
static void __init
#define PCDATA_CODE_TYPE 0x0014
#define PCDATA_INDICATOR 0x0015
+#ifndef CONFIG_PROC_FS
+#define pci_proc_attach_device(dev) do { } while (0)
+#define pci_proc_detach_device(dev) do { } while (0)
+#endif
+
typedef struct cb_config_t {
struct pci_dev dev;
} cb_config_t;
res->start = 0;
pci_assign_resource(dev, r);
}
- printk("Resource %d at %08lx-%08lx (%04lx)\n",
- r,
- res->start,
- res->end,
- res->flags);
}
list_add_tail(&dev->bus_list, &bus->devices);
list_add_tail(&dev->global_list, &pci_devices);
-#ifdef CONFIG_PROC_FS
pci_proc_attach_device(dev);
-#endif
-
pci_enable_device(dev);
}
int i;
if (c) {
+ int i;
+
+ s->cb_config = NULL;
for(i=0; i<s->functions; i++) {
struct pci_dev *dev = &c[i].dev;
+
list_del(&dev->bus_list);
list_del(&dev->global_list);
free_resources(dev);
-#ifdef CONFIG_PROC_FS
pci_proc_detach_device(dev);
-#endif
}
- kfree(s->cb_config);
- s->cb_config = NULL;
+ kfree(c);
printk(KERN_INFO "cs: cb_free(bus %d)\n", s->cap.cb_dev->subordinate->number);
}
}
s->state &= SOCKET_PRESENT|SOCKET_SETUP_PENDING;
init_socket(s);
s->irq.AssignedIRQ = s->irq.Config = 0;
- s->functions = 0;
s->lock_count = 0;
s->cis_used = 0;
if (s->fake_cis) {
cb_release_cis_mem(s);
cb_free(s);
#endif
+ s->functions = 0;
if (s->config) {
kfree(s->config);
s->config = NULL;
MIX_OBJS :=
ifeq ($(CONFIG_ISAPNP),y)
- LX_OBJS += isapnp.o
+ LX_OBJS += isapnp.o quirks.o
else
ifeq ($(CONFIG_ISAPNP),m)
- MX_OBJS += isapnp.o
+ MX_OBJS += isapnp.o quirks.o
endif
endif
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
+ * Changelog:
+ * 2000-01-01 Added ISAPnP quirks handling
+ * Peter Denison <peterd@pnd-pc.demon.co.uk>
*/
#include <linux/config.h>
isapnp_write_byte(idx+3, val);
}
-static void *isapnp_alloc(long size)
+void *isapnp_alloc(long size)
{
void *result;
int csn;
unsigned char header[9], checksum;
struct pci_bus *card;
+ struct pci_dev *dev;
isapnp_wait();
isapnp_key();
list_add_tail(&card->node, &isapnp_cards);
}
+ for (dev = isapnp_devices; dev ; dev = dev->next) {
+ isapnp_fixup_device(dev);
+ }
return 0;
}
*
*/
-static void *isapnp_alloc(long size);
+struct pci_bus *isapnp_cards;
+struct pci_dev *isapnp_devices;
struct isapnp_info_buffer {
char *buffer; /* pointer to begin of buffer */
--- /dev/null
+/*
+ * This file contains quirk handling code for ISAPnP devices
+ * Some devices do not report all their resources, and need to have extra
+ * resources added. This is most easily accomplished at initialisation time
+ * when building up the resource structure for the first time.
+ *
+ * Copyright (c) 2000 Peter Denison <peterd@pnd-pc.demon.co.uk>
+ *
+ * Heavily based on PCI quirks handling which is
+ *
+ * Copyright (c) 1999 Martin Mares <mj@suse.cz>
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/isapnp.h>
+
+static void __init quirk_awe32_resources(struct pci_dev *dev)
+{
+ struct isapnp_port *port, *port2, *port3;
+ struct isapnp_resources *res = dev->sysdata;
+
+ /*
+ * Unfortunately the isapnp_add_port_resource is too tightly bound
+ * into the PnP discovery sequence, and cannot be used. Link in the
+ * two extra ports (at offset 0x400 and 0x800 from the one given) by
+ * hand.
+ */
+ for ( ; res ; res = res->alt ) {
+ port2 = isapnp_alloc(sizeof(struct isapnp_port));
+ port3 = isapnp_alloc(sizeof(struct isapnp_port));
+ if (!port2 || !port3)
+ return;
+ port = res->port;
+ memcpy(port2, port, sizeof(struct isapnp_port));
+ memcpy(port3, port, sizeof(struct isapnp_port));
+ port->next = port2;
+ port2->next = port3;
+ port2->min += 0x400;
+ port2->max += 0x400;
+ port3->min += 0x800;
+ port3->max += 0x800;
+ }
+ printk(KERN_INFO "ISAPnP: AWE32 quirk - adding two ports\n");
+}
+
+
+/*
+ * ISAPnP Quirks
+ * Cards or devices that need some tweaking due to broken hardware
+ */
+
+static struct isapnp_fixup isapnp_fixups[] __initdata = {
+ { ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0021),
+ quirk_awe32_resources },
+ { 0 }
+};
+
+void isapnp_fixup_device(struct pci_dev *dev)
+{
+ int i = 0;
+
+ while (isapnp_fixups[i].vendor != 0) {
+ if ((isapnp_fixups[i].vendor == dev->vendor) &&
+ (isapnp_fixups[i].device == dev->device)) {
+ printk(KERN_DEBUG "PnP: Calling quirk for %s\n",
+ dev->slot_name);
+ isapnp_fixups[i].quirk_function(dev);
+ }
+ i++;
+ }
+}
+
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
+ nm256_audio.o ac97.o
obj-$(CONFIG_SOUND_CS4232) += uart401.o
obj-$(CONFIG_SOUND_GUS) += gus.o ad1848.o
obj-$(CONFIG_SOUND_MAD16) += mad16.o ad1848.o sb.o uart401.o
-obj-$(CONFIG_SOUND_VIA82CXXX) += via82cxxx.o sb.o uart401.o
+obj-$(CONFIG_SOUND_VIA82CXXX) += via82cxxx.o sb.o uart401.o ac97.o
obj-$(CONFIG_SOUND_MAUI) += maui.o mpu401.o
obj-$(CONFIG_SOUND_MPU401) += mpu401.o
obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
#include "ac97.h"
/* Flag for mono controls. */
return put_user(ret, (int *) arg);
}
+EXPORT_SYMBOL(ac97_init);
+EXPORT_SYMBOL(ac97_set_values);
+EXPORT_SYMBOL(ac97_set_mixer);
+EXPORT_SYMBOL(ac97_get_register);
+EXPORT_SYMBOL(ac97_put_register);
+EXPORT_SYMBOL(ac97_get_mixer_scaled);
+EXPORT_SYMBOL(ac97_mixer_ioctl);
+EXPORT_SYMBOL(ac97_reset);
\f
/*
* Local variables:
*/
#include <linux/config.h>
+#define __NO_VERSION__
#include <linux/pci.h>
#include <linux/module.h>
#ifdef CONFIG_APM
speed = 44100;
if (devc->opened & OPEN_READ && speed > 15000)
speed = 15000;
- devc->tconst = ((65536 - ((256000000 + s / 2) / s)) >> 8) & 0xff;
+ devc->tconst = (256 - ((1000000 + s / 2) / s)) & 0xff;
tmp = 256 - devc->tconst;
speed = ((1000000 + tmp / 2) / tmp) / devc->channels;
if (speed > 44100)
speed = 44100;
- devc->tconst = ((65536 - ((256000000 + s / 2) / s)) >> 8) & 0xff;
+ devc->tconst = (256 - ((1000000 + s / 2) / s)) & 0xff;
tmp = 256 - devc->tconst;
speed = ((1000000 + tmp / 2) / tmp) / devc->channels;
int support = 0; /* Set support to load this as a support module */
int sm_games = 0; /* Mixer - see sb_mixer.c */
int acer = 0; /* Do acer notebook init */
-#ifdef CONFIG_ISAPNP
-int isapnp = 1;
-#else
-int isapnp = 0;
-#endif
MODULE_PARM(io, "i");
MODULE_PARM(irq, "i");
MODULE_PARM(pas2, "i");
MODULE_PARM(sm_games, "i");
MODULE_PARM(esstype, "i");
-#ifdef CONFIG_ISAPNP
-MODULE_PARM(isapnp, "i");
-#endif
void *smw_free = NULL;
if (mad16 == 0 && trix == 0 && pas2 == 0 && support == 0)
{
#ifdef CONFIG_ISAPNP
- if (isapnp == 1 && sb_probe_isapnp(&config, &config_mpu)<0)
- {
- printk(KERN_ERR "sb_card: No ISAPnP cards found\n");
- return -EINVAL;
- }
- else
+ if (sb_probe_isapnp(&config, &config_mpu)<0)
{
#endif
if (io == -1 || dma == -1 || irq == -1)
config.dma = dma;
config.dma2 = dma16;
config.card_subtype = type;
+#ifdef CONFIG_MIDI
+ config_mpu.io_base = mpu_io;
+#endif
#ifdef CONFIG_ISAPNP
}
#endif
if(config.slots[0]==-1)
return -ENODEV;
#ifdef CONFIG_MIDI
- if (isapnp == 0)
- config_mpu.io_base = mpu_io;
if (probe_sbmpu(&config_mpu))
sbmpu = 1;
if (sbmpu)
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* History
+ * v0.04 Dec 31 1999 Ollie Lho
+ * Multiple Open, useing 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
#include "trident.h"
#include "ac97.h"
-/* --------------------------------------------------------------------- */
-
#undef DEBUG
-/* --------------------------------------------------------------------- */
#define DRIVER_VERSION "0.03"
-#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 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 TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */
#define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */
-
-#define NR_DSPS 8
+/* number of instances of opening /dev/dsp, can your CPU handle this ? */
+#define NR_DSPS 32
#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 {
} CHANNELCONTROL;
-/* --------------------------------------------------------------------- */
-
+/* "software" or virtual channel, an instance of opened /dev/dsp */
struct trident_state {
unsigned int magic;
- int channel;
struct trident_card *card; /* Card info */
+
/* wave stuff */
unsigned int rateadc, ratedac;
unsigned char fmt, enable;
+ /* single opne lock mechanism, should be removed */
struct semaphore open_sem;
- mode_t open_mode;
wait_queue_head_t open_wait;
- /* soundcore stuff */
- int dev_audio;
+ /* file mode */
+ mode_t open_mode;
+
+ /* virtual channel number */
+ int virt;
struct dmabuf {
void *rawbuf;
unsigned buforder;
unsigned numfrag;
unsigned fragshift;
- int chan[2]; /* Hardware channel */
+
+ /* hardware channel number */
+ int chan;
+
/* XXX zab - swptr only in here so that it can be referenced by
clear_advance, as far as I can tell :( */
unsigned hwptr, swptr;
int count;
unsigned error; /* over/underrun */
wait_queue_head_t wait;
+
/* redundant, but makes calculations easier */
unsigned fragsize;
unsigned dmasize;
unsigned ossfragshift;
int ossmaxfrags;
unsigned subdivision;
- u16 base; /* Offset for ptr */
} dma_dac, dma_adc;
-
+
u8 bDMAStart;
};
+/* hardware channels */
+struct trident_channel {
+ int chan; /* channel number */
+ u32 lba;
+ u32 eso;
+ u32 delta;
+ u16 attribute;
+
+};
+
struct trident_pcm_bank {
/* registers to control bank operations */
u32 start;
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,
so we use a single per card lock */
spinlock_t lock;
+ /* PCI device stuff */
struct pci_audio_info *pci_info;
struct pci_dev * pci_dev;
u16 pci_id;
- /* as most of this is static,
- perhaps it should be a pointer to a global struct */
+ /* soundcore stuff */
+ int dev_audio;
int dev_mixer;
- struct mixer_goo {
- 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];
- } mix;
-
- struct trident_state channels[NR_DSPS];
+
+ struct trident_mixer mix;
+ struct trident_state *channels[NR_DSPS];
/* hardware resources */
unsigned long iobase;
u32 irq;
+ /* hardware channel allocation bitmap */
u32 bitmap[2];
+
+ /* ugly stupid thing, remove ASAP */
CHANNELCONTROL ChRegs;
int ChanDwordCount;
};
static int trident_enable_end_interrupts(struct trident_card * trident)
{
- u32 GlobalControl;
+ u32 global_control;
- GlobalControl = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
+ global_control = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
switch (trident->pci_id)
{
case PCI_DEVICE_ID_SI_7018:
- GlobalControl |= (ENDLP_IE | BANK_B_EN);
+ global_control |= (ENDLP_IE | BANK_B_EN);
break;
case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
- GlobalControl |= ENDLP_IE;
+ global_control |= ENDLP_IE;
break;
default:
return FALSE;
}
- outl(GlobalControl, TRID_REG(trident, T4D_LFO_GC_CIR));
+ outl(global_control, TRID_REG(trident, T4D_LFO_GC_CIR));
#ifdef DEBUG
- printk("trident: Enable End Interrupts, globctl = 0x%08X\n", GlobalControl);
+ printk("trident: Enable End Interrupts, globctl = 0x%08X\n", global_control);
#endif
return (TRUE);
}
static int trident_enable_middle_interrupts(struct trident_card * trident)
{
- u32 GlobalControl;
+ u32 global_control;
- GlobalControl = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
+ global_control = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
switch (trident->pci_id)
{
case PCI_DEVICE_ID_SI_7018:
- GlobalControl |= (MIDLP_IE | BANK_B_EN);
+ global_control |= (MIDLP_IE | BANK_B_EN);
break;
case PCI_DEVICE_ID_TRIDENT_4DWAVE_DX:
case PCI_DEVICE_ID_TRIDENT_4DWAVE_NX:
default:
- GlobalControl |= MIDLP_IE;
+ global_control |= MIDLP_IE;
break;
}
- outl(GlobalControl, TRID_REG(trident, T4D_LFO_GC_CIR));
+ outl(global_control, TRID_REG(trident, T4D_LFO_GC_CIR));
#ifdef DEBUG
- printk("trident: Enable Middle Interrupts, globctl = 0x%08X\n", GlobalControl);
+ printk("trident: Enable Middle Interrupts, globctl = 0x%08X\n", global_control);
#endif
return (TRUE);
}
static int trident_disable_end_interrupts(struct trident_card * trident)
{
- u32 GlobalControl;
+ u32 global_control;
- GlobalControl = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
- GlobalControl &= ~ENDLP_IE;
- outl(GlobalControl, TRID_REG(trident, T4D_LFO_GC_CIR));
+ global_control = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
+ global_control &= ~ENDLP_IE;
+ outl(global_control, TRID_REG(trident, T4D_LFO_GC_CIR));
#ifdef DEBUG
- printk("trident: Disabled End Interrupts, globctl = 0x%08X\n", GlobalControl);
+ printk("trident: Disabled End Interrupts, globctl = 0x%08X\n", global_control);
#endif
return (TRUE);
}
static int trident_disable_middle_interrupts(struct trident_card * trident)
{
- u32 GlobalControl;
+ u32 global_control;
- GlobalControl = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
- GlobalControl &= ~MIDLP_IE;
- outl(GlobalControl, TRID_REG(trident, T4D_LFO_GC_CIR));
+ global_control = inl(TRID_REG(trident, T4D_LFO_GC_CIR));
+ global_control &= ~MIDLP_IE;
+ outl(global_control, TRID_REG(trident, T4D_LFO_GC_CIR));
#ifdef DEBUG
- printk("trident: Disabled Middle Interrupts, globctl = 0x%08X\n", GlobalControl);
+ printk("trident: Disabled Middle Interrupts, globctl = 0x%08X\n", global_control);
#endif
return (TRUE);
}
int idx;
if (trident->bitmap[BANK_B] == ~0UL) {
- /* not more free channels avaliable */
+ /* no more free channels avaliable */
printk(KERN_ERR "trident: no more channels available on Bank B.\n");
return -1;
}
/* 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) {
- /* not more free channels avaliable */
+ /* no more free channels avaliable */
printk(KERN_ERR "trident: no channels available on Bank A.\n");
return -1;
}
trident->ratedac = rate;
if (set)
- trident_load_hw_delta(trident->card, trident->dma_dac.chan[1],
+ trident_load_hw_delta(trident->card, trident->dma_dac.chan,
delta);
#ifdef DEBUG
printk("trident: called trident_set_dac_rate : rate = %d, "
#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_dac.chan[0],
+ trident_load_hw_delta(trident->card, trident->dma_adc.chan,
delta);
#endif
#ifdef DEBUG
#ifdef DEBUG
printk(" 0x%04x", val);
#endif
-
trident_ac97_set(card, mh->offset, val);
#ifdef DEBUG
return 0;
}
-/* this only fixes the output apu mode to be later set by start_dac and
- company. output apu modes are set in trident_rec_setup */
+/* 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;
- /* Set the chip ? */
}
/* the mode passed should be already shifted and masked */
ESO /= 2;
ESO = ESO - 1;
+ /* loop mode enable */
CTRL = 0x00000001;
if (mode & TRIDENT_FMT_16BIT) {
- CTRL |= 0x00000008; // 16-bit data
- CTRL |= 0x00000002; // signed data
+ /* 16-bits */
+ CTRL |= 0x00000008;
+ /* signed */
+ CTRL |= 0x00000002;
}
if (mode & TRIDENT_FMT_STEREO)
- CTRL |= 0x00000004; // stereo data
+ /* stereo */
+ CTRL |= 0x00000004;
/* FIXME: some difference between 4D and 7018 in FMC_RVOL_CVOL */
/* right vol: mute, ledt vol: mute */
EC = 0;
trident_write_voice_regs(trident->card,
- trident->dma_dac.chan[1],
+ trident->dma_dac.chan,
LBA,
0, /* cso */
ESO,
/* 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)
+static void trident_rec_setup(struct trident_state *trident, int mode, u32 rate,
+ void *buffer, int size)
{
unsigned int LBA;
unsigned int Delta;
EC = 0;
trident_write_voice_regs(card,
- trident->dma_adc.chan[0],
+ trident->dma_adc.chan,
LBA,
0, /* cso */
ESO,
if (!(trident->enable & ADC_RUNNING))
return 0;
#endif
- outb(trident->dma_dac.chan[1], TRID_REG(trident->card, T4D_LFO_GC_CIR));
+ outb(trident->dma_dac.chan, TRID_REG(trident->card, T4D_LFO_GC_CIR));
switch (trident->card->pci_id)
{
}
#ifdef DEBUG
- printk("trident: get_dmaa: chip reported esc = %d, cso = %d\n", cso, eso);
+ printk("trident: get_dmaa: chip reported channel: %d, cso = %d, eso = %d\n",
+ trident->dma_dac.chan, cso, eso);
#endif
- cso++;
/* ESO and CSO are in units of Samples, convert to byte offset */
if (cso > eso)
cso = eso;
u32 cso;
#if 0
/* FIXME: does this mean that FULL duplex is not supported ? */
- if (!(trident->enable&DAC_RUNNING))
+ if (!(trident->enable & DAC_RUNNING))
return 0;
#endif
- outb(trident->dma_adc.chan[0], TRID_REG(trident->card, T4D_LFO_GC_CIR));
+ outb(trident->dma_adc.chan, TRID_REG(trident->card, T4D_LFO_GC_CIR));
switch (trident->card->pci_id)
{
#ifdef DEBUG
printk("(trident) get_dmac: chip reported cso = %d\n", cso);
#endif
- cso++;
/* ESO and CSO are in units of Samples, convert to byte offset */
if (trident->fmt & TRIDENT_FMT_16BIT)
cso *= 2;
printk("(trident) stopping ADC\n");
#endif
s->enable &= ~ADC_RUNNING;
- trident_disable_voice_irq(trident, s->dma_adc.chan[0]);
+ 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[0]);
- trident_stop_voice(trident, s->dma_adc.chan[0]);
- ResetAinten(trident, s->dma_adc.chan[0]);
+ trident_disable_voice_irq(trident, s->dma_adc.chan);
+ trident_stop_voice(trident, s->dma_adc.chan);
+ ResetAinten(trident, s->dma_adc.chan);
}
extern inline void stop_adc(struct trident_state *s)
}
/* stop playback (lock held) */
-
-extern inline void __stop_dac(struct trident_state *s)
+extern inline void __stop_dac(struct trident_state *state)
{
- struct trident_card *trident = s->card;
-#ifdef DEBUG
- printk("(trident) stopping DAC\n");
-#endif
- //trident_stop_voice(trident, s->dma_dac.chan[0]);
- //trident_disable_voice_irq(trident, s->dma_dac.chan[0]);
- trident_stop_voice(trident, s->dma_dac.chan[1]);
- trident_disable_voice_irq(trident, s->dma_dac.chan[1]);
- s->enable &= ~DAC_RUNNING;
+ 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;
}
-extern inline void stop_dac(struct trident_state *s)
+extern inline void stop_dac(struct trident_state *state)
{
- struct trident_card *trident = s->card;
+ struct trident_card *trident = state->card;
unsigned long flags;
spin_lock_irqsave(&trident->lock, flags);
- __stop_dac(s);
+ __stop_dac(state);
spin_unlock_irqrestore(&trident->lock, flags);
}
-static void start_dac(struct trident_state *s)
+static void start_dac(struct trident_state *state)
{
unsigned long flags;
- struct trident_card *trident = s->card;
+ struct trident_card *trident = state->card;
- spin_lock_irqsave(&s->card->lock, flags);
- if ((s->dma_dac.mapped || s->dma_dac.count > 0) && s->dma_dac.ready)
- {
- s->enable |= DAC_RUNNING;
- trident_enable_voice_irq(trident, s->dma_dac.chan[1]);
- trident_start_voice(trident, s->dma_dac.chan[1]);
- //trident_start_voice(trident, s->dma_dac.chan[0]);
-#ifdef DEBUG
- printk("(trident) starting DAC\n");
-#endif
+ 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_unlock_irqrestore(&s->card->lock, flags);
+ spin_unlock_irqrestore(&state->card->lock, flags);
}
static void start_adc(struct trident_state *s)
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[0]);
+ 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[0]);
+ trident_start_voice(s->card, s->dma_adc.chan);
#ifdef DEBUG
printk("(trident) starting ADC\n");
#endif
}
#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT)
-#define DMABUF_MINORDER 2
+#define DMABUF_MINORDER 1
/* allocate DMA buffer, playback and recording buffer should be allocated seperately */
static int alloc_dmabuf(struct trident_state *state, unsigned rec)
/* 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|GFP_DMA, order)))
+ if ((rawbuf = (void *)__get_free_pages(GFP_KERNEL, order)))
break;
if (!rawbuf)
return -ENOMEM;
+#ifdef DEBUG
+ printk("trident: allocated %ld (%d) bytes at %p\n",
+ PAGE_SIZE << order, order, rawbuf);
+#endif
/* for 4DWave and 7018, there are only 30 (31) siginifcan bits for Loop Begin Address
(LBA) which limits the address space to 1 (2) GB, bad T^2 design */
/* set the ready flag for the dma buffer */
db->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);
+#endif
+
return 0;
}
-/* only called by trident_write */
extern __inline__ void clear_advance(struct trident_state *s)
{
unsigned char c = ((s->fmt >> TRIDENT_DAC_SHIFT) & TRIDENT_FMT_16BIT) ? 0 : 0x80;
/* 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;
+ 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;
}
/* update DAC pointer */
- if (s->dma_dac.ready)
- {
- /* this is so gross. */
- hwptr = (/*s->dma_dac.dmasize -*/ get_dmaa(s)) % s->dma_dac.dmasize;
- diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % s->dma_dac.dmasize;
-#ifdef DEBUG
- printk("(trident) updating dac: hwptr: %d diff: %d\n",hwptr,diff);
-#endif
+ 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)
- {
+ 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);
}
- else
- {
+ else {
s->dma_dac.count -= diff;
-#ifdef DEBUG
- printk("(trident) trident_update_ptr: diff: %d, count: %d\n", diff, s->dma_dac.count);
-#endif
- if (s->dma_dac.count <= 0)
- {
+ if (s->dma_dac.count <= 0) {
s->enable &= ~TRIDENT_ENABLE_PE;
/* Lock already held */
__stop_dac(s);
s->dma_dac.error++;
}
else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize &&
- !s->dma_dac.endcleared)
- {
+ !s->dma_dac.endcleared) {
clear_advance(s);
s->dma_dac.endcleared = 1;
}
if (event & ADDRESS_IRQ) {
/* Update the pointers for all channels we are running. */
- /* the index variable i is the main bug make the original driver crash,
- the code mix "software" channel with "hardware" channel */
+ /* FIXME: improve interrupt latency !!! */
for (i = 0; i < NR_DSPS; i++) {
- state = &card->channels[i];
+ state = card->channels[i];
if (trident_check_channel_interrupt(card, 63 - i)) {
trident_ack_channel_interrupt(card, 63 - i);
- if (state->dev_audio != -1)
+ if (state != NULL)
trident_update_ptr(state);
else {
/* Spurious ? */
struct trident_card *card = (struct trident_card *)file->private_data;
VALIDATE_CARD(card);
-
return mixer_ioctl(card, cmd, arg);
}
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;
or schedule_timeout is broken.
or something. who cares. - zach */
if (!schedule_timeout(tmo ? tmo : 1) && tmo)
- printk(KERN_ERR "trident: dma timed out?? %ld\n", jiffies);
+ 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;
}
stop_adc(state);
spin_lock_irqsave(&state->card->lock, flags);
- /*set_dmac(s, virt_to_bus(s->dma_adc.rawbuf),
- s->dma_adc.numfrag << s->dma_adc.fragshift); */
state->dma_adc.count = 0;
state->dma_adc.hwptr = 0;
state->dma_adc.swptr = 0;
int mode = (state->fmt >> TRIDENT_DAC_SHIFT) & TRIDENT_FMT_MASK;
#ifdef DEBUG
- printk("(trident) trident_write: count %d\n", count);
+ printk("trident: trident_write called, count = %d\n", count);
#endif
VALIDATE_STATE(state);
return ret;
}
if (!interruptible_sleep_on_timeout(&state->dma_dac.wait, HZ)) {
- printk(KERN_DEBUG
+ printk(KERN_ERR
"trident: write: chip lockup? "
"dmasz %u fragsz %u count %i "
"hwptr %u swptr %u\n",
state->dma_dac.swptr);
stop_dac(state);
spin_lock_irqsave(&state->card->lock, flags);
- /* set_dmaa(s, virt_to_bus(s->dma_dac.rawbuf),
- s->dma_dac.numfrag << s->dma_dac.fragshift); */
state->dma_dac.count = 0;
state->dma_dac.hwptr = 0;
state->dma_dac.swptr = 0;
poll_wait(file, &s->dma_dac.wait, wait);
if (file->f_mode & FMODE_READ)
poll_wait(file, &s->dma_adc.wait, wait);
+
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;
VALIDATE_STATE(s);
mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) ||
((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
+#ifdef DEBUG
+ printk("trident: trident_ioctl, command = %2d, arg = 0x%08x\n",_IOC_NR(cmd),
+ arg ? *(int *)arg : 0);
+#endif
switch (cmd)
{
static int trident_open(struct inode *inode, struct file *file)
{
+ int i = 0;
int minor = MINOR(inode->i_rdev);
struct trident_card *card = devs;
- struct trident_state *state = NULL, *sp;
- int i;
+ struct trident_state *state = NULL;
unsigned char fmtm = ~0, fmts = 0;
- /* Scan the cards and find the channel.
- We only do this at open time so it is ok */
+ /* find an avaiable virtual channel (instance of /dev/dsp) */
while (card != NULL) {
for (i = 0; i < NR_DSPS; i++) {
- sp = &card->channels[i];
- if (sp->dev_audio < 0)
- continue;
- if ((sp->dev_audio ^ minor) & ~0xf)
- continue;
- state = sp;
+ if (card->channels[i] == NULL) {
+ state = card->channels[i] = (struct trident_state *)
+ kmalloc(sizeof(struct trident_state), GFP_KERNEL);
+ if (state == NULL)
+ return -ENOMEM;
+ memset(state, 0, sizeof(struct trident_state));
+ goto found_virt;
+ }
}
card = card->next;
}
-
+ /* no more virtual channel avaiable */
if (!state)
return -ENODEV;
- VALIDATE_STATE(state);
+ 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;;
+ 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 (file->f_mode & FMODE_READ)
+ /* free previously allocated hardware channel */
+ trident_free_pcm_channel(card, state->dma_adc.chan);
+ return -ENODEV;
+ }
+
+ /* initialize the virtual channel */
+ state->virt = i;
+ state->card = card;
+ state->magic = TRIDENT_STATE_MAGIC;
+ init_waitqueue_head(&state->dma_adc.wait);
+ init_waitqueue_head(&state->dma_dac.wait);
+ init_MUTEX(&state->open_sem);
file->private_data = state;
down(&state->open_sem);
- while (state->open_mode & file->f_mode) {
- /* the channel has been open for the same mode before */
- if (file->f_flags & O_NONBLOCK) {
- /* Non-blocking mode, return immediately */
- up(&state->open_sem);
- return -EWOULDBLOCK;
- }
- up(&state->open_sem);
- /* blocking, wait for device to become free */
- interruptible_sleep_on(&state->open_wait);
- if (signal_pending(current))
- return -ERESTARTSYS;
- down(&state->open_sem);
- }
-
+ /* 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;
-
state->dma_adc.ossfragshift = 0;
state->dma_adc.ossmaxfrags = 0;
state->dma_adc.subdivision = 0;
trident_set_adc_rate(state, 8000, 0);
}
+
+ /* 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);
if ((minor & 0xf) == SND_DEV_DSP16)
if (file->f_mode & FMODE_WRITE)
drain_dac(state, file->f_flags & O_NONBLOCK);
- /* stop DMA state machine and free DMA buffers */
+ /* stop DMA state machine and free DMA buffers/channels */
down(&state->open_sem);
+
if (file->f_mode & FMODE_WRITE) {
stop_dac(state);
dealloc_dmabuf(&state->dma_dac);
+ trident_free_pcm_channel(state->card, state->dma_dac.chan);
}
if (file->f_mode & FMODE_READ) {
stop_adc(state);
dealloc_dmabuf(&state->dma_adc);
+ trident_free_pcm_channel(state->card, state->dma_adc.chan);
}
+
+ kfree(state->card->channels[state->virt]);
+ state->card->channels[state->virt] = NULL;
state->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
+
/* we're covered by the open_sem */
up(&state->open_sem);
- wake_up(&state->open_wait);
-
//FIXME put back in
//MOD_DEC_USE_COUNT;
return 0;
}
-
static /*const*/ struct file_operations trident_audio_fops = {
&trident_llseek,
&trident_read,
NULL, /* lock */
};
-#ifdef CONFIG_APM
-int trident_apm_callback(apm_event_t ae) {
- return 0;
-}
-#endif
-
-/* --------------------------------------------------------------------- */
-
+/* 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)
{
+ int i;
u16 w;
unsigned long iobase;
- int i;
struct trident_card *card;
- struct trident_state *trident;
- int num = 0;
- u32 ChanDwordCount;
-
+ u32 ChanDwordCount;
+
iobase = pcidev->resource[0].start;
-
- if(check_region(iobase, 256)) {
- printk(KERN_WARNING "trident: can't allocate I/O space at 0x%4.4lx\n",
+ if (check_region(iobase, 256)) {
+ printk(KERN_ERR "trident: can't allocate I/O space at 0x%4.4lx\n",
iobase);
return 0;
}
- /* this was tripping up some machines */
- if (pcidev->irq == 0) {
- printk(KERN_WARNING "trident: pci subsystem reports irq 0,"
- " this might not be correct.\n");
- }
-
- /* just to be sure */
- pci_set_master(pcidev);
-
+ /* just to be sure that IO space and bus master is on */
+ pci_set_master(pcidev);
pci_read_config_word(pcidev, PCI_COMMAND, &w);
- if((w&(PCI_COMMAND_IO|PCI_COMMAND_MASTER)) != (PCI_COMMAND_IO|PCI_COMMAND_MASTER))
- {
- printk(KERN_WARNING "trident: BIOS did not enable I/O access.\n");
- w|=PCI_COMMAND_IO|PCI_COMMAND_MASTER;
- pci_write_config_word(pcidev, PCI_COMMAND, w);
- }
-
- card = kmalloc(sizeof(struct trident_card), GFP_KERNEL);
+ w |= PCI_COMMAND_IO|PCI_COMMAND_MASTER;
+ pci_write_config_word(pcidev, PCI_COMMAND, w);
- if (card == NULL) {
- printk(KERN_WARNING "trident: out of memory\n");
+ if ((card = kmalloc(sizeof(struct trident_card), GFP_KERNEL)) == NULL) {
+ printk(KERN_ERR "trident: out of memory\n");
return 0;
}
-
memset(card, 0, sizeof(*card));
-#ifdef CONFIG_APM
- printk("trident: apm_reg_callback: %d\n",
- apm_register_callback(trident_apm_callback));
-#endif
-
card->iobase = iobase;
card->pci_info = pci_info;
card->pci_id = pci_info->device;
card->irq = pcidev->irq;
card->next = devs;
card->magic = TRIDENT_CARD_MAGIC;
+ 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[1] = T4D_AINT_B;
card->ChRegs.lpAChAinten[1] = T4D_AINTEN_B;
- outl(0x00, TRID_REG(card, T4D_MUSICVOL_WAVEVOL));
-
-
- spin_lock_init(&card->lock);
-
- for (i = 0; i < NR_DSPS; i++) {
- struct trident_state *s=&card->channels[i];
-
- s->card = card;
- init_waitqueue_head(&s->dma_adc.wait);
- init_waitqueue_head(&s->dma_dac.wait);
- init_waitqueue_head(&s->open_wait);
- init_MUTEX(&s->open_sem);
- s->magic = TRIDENT_STATE_MAGIC;
- s->channel = i;
-
- if(s->dma_adc.ready || s->dma_dac.ready || s->dma_adc.rawbuf)
- printk(KERN_ERR "trident: BOTCH!\n");
-
- /*
- * Now allocate the hardware resources
- */
-
- //s->dma_dac.chan[0] = AllocateChannelPCM(card);
- //s->dma_adc.chan[0] = AllocateChannelPCM(card);
- s->dma_dac.chan[1] = trident_alloc_pcm_channel(card);
- /* register devices */
- if ((s->dev_audio = register_sound_dsp(&trident_audio_fops, -1)) < 0)
- break;
- }
-
- num = i;
-
- /* clear the rest if we ran out of slots to register */
- for (;i < NR_DSPS; i++){
- struct trident_state *s=&card->channels[i];
- s->dev_audio = -1;
- }
-
- trident = &card->channels[0];
-
- /*
- * Ok card ready. Begin setup proper
- */
- printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n",
+ printk(KERN_INFO "trident: %s found at IO 0x%04lx, IRQ %d\n",
card->pci_info->name, card->iobase, card->irq);
+ /* claim our iospace and irq */
+ request_region(card->iobase, 256, card->pci_info->name);
+ if (request_irq(card->irq, &trident_interrupt, SA_SHIRQ, card->pci_info->name, card)) {
+ printk(KERN_ERR "trident: unable to allocate irq %d\n", card->irq);
+ release_region(card->iobase, 256);
+ kfree(card);
+ return 0;
+ }
- /* stake our claim on the iospace */
- request_region(iobase, 256, card->pci_info->name);
-
+ /* 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");
+ release_region(iobase, 256);
+ free_irq(card->irq, card);
+ 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");
- }
- else {
- int i;
- for (i = 0 ; i < SOUND_MIXER_NRDEVICES ; i++) {
+ 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))
}
}
- if (request_irq(card->irq, &trident_interrupt, SA_SHIRQ, card->pci_info->name, card)) {
- printk(KERN_ERR "trident: unable to allocate irq %d,\n", card->irq);
- unregister_sound_mixer(card->dev_mixer);
- for (i = 0; i < NR_DSPS; i++) {
- struct trident_state *s = &card->channels[i];
- if(s->dev_audio != -1)
- unregister_sound_dsp(s->dev_audio);
- }
- release_region(card->iobase, 256);
- kfree(card);
- return 0;
- }
-
+ /* Enable Address Engine Interrupts */
trident_enable_end_interrupts(card);
+ trident_enable_middle_interrupts(card);
+
return 1;
}
-
#ifdef MODULE
int init_module(void)
#else
return 0;
}
-/* --------------------------------------------------------------------- */
-
#ifdef MODULE
-
MODULE_AUTHOR("Alan Cox <alan@redhat.com>");
MODULE_DESCRIPTION("Trident 4DWave/SiS 7018 PCI Audio Driver");
+
#ifdef DEBUG
MODULE_PARM(debug,"i");
#endif
void cleanup_module(void)
{
-#ifdef CONFIG_APM
- apm_unregister_callback(trident_apm_callback);
-#endif
-
while (devs != NULL) {
- int i;
-
/* Kill interrupts, and SP/DIF */
trident_disable_end_interrupts(devs);
+ trident_enable_middle_interrupts(devs);
+
+ /* free hardware resources */
free_irq(devs->irq, devs);
- unregister_sound_mixer(devs->dev_mixer);
- for (i = 0; i < NR_DSPS; i++) {
- struct trident_state *trident = &devs->channels[i];
- if (trident->dev_audio != -1)
- unregister_sound_dsp(trident->dev_audio);
- }
release_region(devs->iobase, 256);
+
+ /* unregister audio devices */
+ unregister_sound_mixer(devs->dev_mixer);
+ unregister_sound_dsp(devs->dev_audio);
+
kfree(devs);
devs = devs->next;
}
}
-
#endif /* MODULE */
#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
+#define DX_AC97_BUSY_READ 0x8000
+#define NX_AC97_BUSY_READ 0x0800
#define AC97_REG_ADDR 0x000000ff
-#define DX_AC97_REG_ADDR 0x000000ff
-#define NX_AC97_REG_ADDR 0x000000ff
+
+enum serial_intf_ctrl_bits {
+ WARM_REST = 0x00000001, COLD_RESET = 0x00000002,
+ I2S_CLOCK = 0x00000004, PCM_SEC_AC97= 0x00000008,
+ AC97_DBL_RATE = 0x00000010, SPDIF_EN = 0x00000020,
+ I2S_OUTPUT_EN = 0x00000040, I2S_INPUT_EN = 0x00000080,
+ PCMIN = 0x00000100, LINE1IN = 0x00000200,
+ MICIN = 0x00000400, LINE2IN = 0x00000800,
+};
enum global_control_bits {
- CHANNLE_IDX = 0x0000003f, PB_RESET = 0x00000100,
+ CHANNLE_IDX = 0x0000003f, PB_RESET = 0x00000100,
PAUSE_ENG = 0x00000200,
OVERRUN_IE = 0x00000400, UNDERRUN_IE = 0x00000800,
- ENDLP_IE = 0x00001000, MIDLP_IE = 0x00002000,
+ ENDLP_IE = 0x00001000, MIDLP_IE = 0x00002000,
ETOG_IE = 0x00004000,
- EDROP_IE = 0x00008000, BANK_B_EN = 0x00010000
+ EDROP_IE = 0x00008000, BANK_B_EN = 0x00010000
};
enum miscint_bits {
/*
* Support for VIA 82Cxxx Audio Codecs
- * Copyright 1999 Jeff Garzik <jgarzik@pobox.com>
+ * Copyright 1999,2000 Jeff Garzik <jgarzik@mandrakesoft.com>
*
* Distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2.
* See the "COPYING" file distributed with this software for more info.
*
- ********************************************************************
- *
- * TODO:
- *
- * - Integrate AC'97 support, when AC'97 interface released
+ * Documentation for this driver available as
+ * linux/Documentation/sound/via82cxxx.txt.
*
+ * Since the mixer is called from the OSS glue the kernel lock is always held
+ * on our AC97 mixing
*/
+
+#define VIA_VERSION "1.1.2"
+
+
+
#include <linux/module.h>
+#include <linux/config.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/proc_fs.h>
#include <asm/io.h>
#include "sound_config.h"
#include "soundmodule.h"
#include "sb.h"
+#include "ac97.h"
#ifndef SOUND_LOCK
#define SOUND_LOCK do {} while (0)
#define SOUND_LOCK_END do {} while (0)
#endif
+#define VIA_DEBUG 0 /* define to 1 to enable debugging output and checks */
+#if VIA_DEBUG
+/* note: prints function name for you */
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+#define VIA_NDEBUG 0 /* define to 1 to disable lightweight runtime checks */
+#if VIA_NDEBUG
+#define assert(expr)
+#else
+#define assert(expr) \
+ if(!(expr)) { \
+ printk( "Assertion failed! %s,%s,%s,line=%d\n", \
+ #expr,__FILE__,__FUNCTION__,__LINE__); \
+ }
+#endif
+
+#define arraysize(x) (sizeof(x)/sizeof(*(x)))
+
#define MAX_CARDS 2
-#define PFX "via82cxxx: "
+#define LINE_SIZE 10
-#define VIA_VERSION "1.0.0"
#define VIA_CARD_NAME "VIA 82Cxxx Audio driver " VIA_VERSION
+#define VIA_MODULE_NAME "via82cxxx"
+#define PFX VIA_MODULE_NAME ": "
+
+#define VIA_COUNTER_LIMIT 100000
+/* 82C686 function 5 (audio codec) PCI configuration registers */
#define VIA_FUNC_ENABLE 0x42
#define VIA_PNP_CONTROL 0x43
+#define VIA_AC97_CTRL 0x80
+
+/* PCI configuration register bits and masks */
+#define VIA_CR40_AC97_READY 0x01
+#define VIA_CR40_AC97_LOW_POWER 0x02
+#define VIA_CR40_SECONDARY_READY 0x04
+
+#define VIA_CR41_ACLINK_ENABLE 0x80
#define VIA_CR42_SB_ENABLE 0x01
#define VIA_CR42_MIDI_ENABLE 0x02
#define VIA_CR42_FM_ENABLE 0x04
+#define VIA_CR42_GAME_ENABLE 0x08
+
+#define VIA_CR44_SECOND_CODEC_SUPPORT (1 << 6)
+#define VIA_CR44_AC_LINK_ACCESS (1 << 7)
+
+#define VIA_CR80_FIRST_CODEC 0
+#define VIA_CR80_SECOND_CODEC (1 << 30)
+#define VIA_CR80_FIRST_CODEC_VALID (1 << 25)
+#define VIA_CR80_SECOND_CODEC_VALID (1 << 27)
+#define VIA_CR80_BUSY (1 << 24)
+#define VIA_CR80_READ_MODE (1 << 23)
+#define VIA_CR80_WRITE_MODE 0
+#define VIA_CR80_REG_IDX(idx) (((idx) & 0x7E) << 16)
+
+struct via_info {
+ struct address_info sb_data;
+ struct address_info opl3_data;
+ struct pci_dev *pdev;
+ struct ac97_hwint ac97;
+ int mixer_oss_dev;
+ int have_ac97;
+};
+static struct via_info cards [MAX_CARDS];
+static unsigned num_cards = 0;
+
+
+static const struct {
+ int revision;
+ const char *rev_name;
+} via_chip_revs[] __initdata = {
+ { 0x10, "A" },
+ { 0x11, "B" },
+ { 0x12, "C" },
+ { 0x13, "D" },
+ { 0x14, "E" },
+ { 0x20, "H" },
+};
+
+static inline void via_ac97_write32 (struct pci_dev *pdev, int port, u32 data)
+{
+ struct resource *rsrc = &pdev->resource[0];
+ outw ((u16)data,rsrc->start+port);
+ outw ((u16)(data>>16),rsrc->start+port+2);
+}
+
+static inline u32 via_ac97_read32 (struct pci_dev *pdev, int port)
+{
+ struct resource *rsrc = &pdev->resource[0];
+ return
+ ((u32)inw (rsrc->start+port)) |
+ (((u32)inw (rsrc->start+port+2)) << 16);
+}
+
+/****************************************************************
+ *
+ * Intel Audio Codec '97 interface
+ *
+ *
+ */
+
+static inline void via_ac97_wait_idle (struct pci_dev *pdev)
+{
+ u32 tmp;
+ int counter = VIA_COUNTER_LIMIT;
+
+ DPRINTK ("ENTER\n");
+
+ assert (pdev != NULL);
+
+ do {
+ tmp = via_ac97_read32 (pdev,VIA_AC97_CTRL);
+ } while ((tmp & VIA_CR80_BUSY) && (counter-- > 0));
+
+ DPRINTK ("EXIT%s\n", counter > 0 ? "" : ", counter limit reached");
+}
+
+
+static int via_ac97_read_reg (struct ac97_hwint *dev, u8 reg)
+{
+ u32 data;
+ struct via_info *card;
+ struct pci_dev *pdev;
+
+ DPRINTK ("ENTER\n");
+
+ assert (dev != NULL);
+ assert (dev->driver_private != NULL);
+
+ card = (struct via_info *) dev->driver_private;
+ pdev = card->pdev;
+ assert (pdev != NULL);
+
+ via_ac97_wait_idle (pdev);
+ data = VIA_CR80_FIRST_CODEC | VIA_CR80_FIRST_CODEC_VALID |
+ VIA_CR80_READ_MODE | VIA_CR80_REG_IDX(reg);
+ via_ac97_write32 (pdev,VIA_AC97_CTRL,data);
+ via_ac97_wait_idle (pdev);
+ data = via_ac97_read32 (pdev,VIA_AC97_CTRL);
+
+#if 0
+ if (! (data & VIA_CR80_FIRST_CODEC_VALID)) {
+ DPRINTK ("EXIT, first codec not valid, returning -1\n");
+ return -1;
+ }
+#endif
+
+ DPRINTK ("EXIT, returning %d\n", data & 0xFFFF);
+ return data & 0xFFFF;
+}
+
+
+static int via_ac97_write_reg (struct ac97_hwint *dev, u8 reg, u16 value)
+{
+ u32 data;
+ struct via_info *card;
+ struct pci_dev *pdev;
+
+ DPRINTK ("ENTER\n");
+
+ assert (dev != NULL);
+ assert (dev->driver_private != NULL);
-#define via_probe_midi probe_uart401
-#define via_attach_midi attach_uart401
-#define via_unload_midi unload_uart401
+ card = (struct via_info *) dev->driver_private;
+ pdev = card->pdev;
+ assert (pdev != NULL);
-static struct address_info sb_data[MAX_CARDS];
-static struct address_info opl3_data[MAX_CARDS];
-static unsigned cards = 0;
+ via_ac97_wait_idle (pdev);
+ data = VIA_CR80_FIRST_CODEC | VIA_CR80_FIRST_CODEC_VALID |
+ VIA_CR80_WRITE_MODE | VIA_CR80_REG_IDX(reg) | value;
+ via_ac97_write32 (pdev,VIA_AC97_CTRL,data);
+#if 0
+ if (! (data & VIA_CR80_FIRST_CODEC_VALID)) {
+ DPRINTK ("EXIT, first codec invalid, returning -1\n");
+ return -1;
+ }
+#endif
+
+ DPRINTK ("EXIT, returning 0\n");
+ return 0;
+}
+
+
+static int via_ac97_reset (struct ac97_hwint *dev)
+{
+ struct via_info *card;
+ struct pci_dev *pdev;
+
+ DPRINTK ("ENTER\n");
+
+ assert (dev != NULL);
+ assert (dev->driver_private != NULL);
+
+ card = (struct via_info *) dev->driver_private;
+ pdev = card->pdev;
+ assert (pdev != NULL);
+
+ pci_write_config_word (pdev, PCI_COMMAND, PCI_COMMAND_IO);
+
+ DPRINTK ("EXIT, returning 0\n");
+ return 0;
+}
+
+
+static struct via_info *via_ac97_find_card_for_mixer (int dev)
+{
+ int x;
+
+ DPRINTK ("ENTER\n");
+
+ for (x = 0; x < num_cards; x++)
+ if (cards[x].mixer_oss_dev == dev) {
+ DPRINTK ("EXIT, returning %p\n", cards + x);
+ return cards + x;
+ }
+
+ DPRINTK ("EXIT, returning 0\n");
+ return NULL;
+}
+
+
+static int
+via_ac97_default_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
+{
+ int rc;
+ struct via_info *card = via_ac97_find_card_for_mixer (dev);
+
+ DPRINTK ("ENTER\n");
+
+ if (card != NULL) {
+ rc = ac97_mixer_ioctl (&card->ac97, cmd, arg);
+ DPRINTK ("EXIT, returning %d\n", rc);
+ return rc;
+ }
+
+ DPRINTK ("EXIT, returning -ENODEV\n");
+ return -ENODEV;
+
+}
+
+static struct mixer_operations via_ac97_mixer_operations =
+{
+ "VIA82Cxxx",
+ "via82cxxxAC97Mixer",
+ via_ac97_default_mixer_ioctl
+};
+
+static int __init via_attach_ac97 (struct via_info *card)
+{
+ int mixer;
+ struct ac97_hwint *mdev;
+
+ DPRINTK ("ENTER\n");
+
+ assert (card != NULL);
+
+ mdev = &card->ac97;
+
+ memset (mdev, 0, sizeof (*mdev));
+ mdev->reset_device = via_ac97_reset;
+ mdev->read_reg = via_ac97_read_reg;
+ mdev->write_reg = via_ac97_write_reg;
+ mdev->driver_private = (void *) card;
+
+ if (ac97_init (mdev)) {
+ printk (KERN_ERR PFX "Unable to init AC97\n");
+ DPRINTK ("EXIT, returning -1\n");
+ return -1;
+ }
+ mixer = sound_alloc_mixerdev ();
+ if (mixer < 0 || num_mixers >= MAX_MIXER_DEV) {
+ printk (KERN_ERR PFX "Unable to alloc mixerdev\n");
+ DPRINTK ("EXIT, returning -1\n");
+ return -1;
+ }
+ mixer_devs[mixer] = &via_ac97_mixer_operations;
+ card->mixer_oss_dev = mixer;
+
+ /* Some reasonable default values. */
+ ac97_set_mixer (mdev, SOUND_MIXER_VOLUME, (85 << 8) | 85);
+ ac97_set_mixer (mdev, SOUND_MIXER_SPEAKER, 100);
+ ac97_set_mixer (mdev, SOUND_MIXER_PCM, (65 << 8) | 65);
+ ac97_set_mixer (mdev, SOUND_MIXER_CD, (65 << 8) | 65);
+
+ printk (KERN_INFO PFX "Initialized AC97 mixer\n");
+
+ card->have_ac97 = mixer;
+
+ DPRINTK ("EXIT, returning 0\n");
+ return 0;
+}
+
+
+static void via_unload_ac97 (struct via_info *card)
+{
+ DPRINTK ("ENTER\n");
+
+ assert (card != NULL);
+
+ if (card->have_ac97 >= 0)
+ sound_unload_mixerdev (card->have_ac97);
+
+ DPRINTK ("EXIT\n");
+}
+
+
+#ifdef CONFIG_PROC_FS
+
+/****************************************************************
+ *
+ * /proc/driver/via82cxxx/info
+ *
+ *
+ */
+
+static int via_info_read_proc (char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+#define YN(val,bit) (((val) & (bit)) ? "yes" : "no")
+
+ int len = 0, i;
+ u8 r40, r41, r42, r44;
+
+ DPRINTK ("ENTER\n");
+
+ len += sprintf (page+len, VIA_CARD_NAME "\n\n");
+
+ for (i = 0; i < num_cards; i++) {
+ pci_read_config_byte (cards[i].pdev, 0x40, &r40);
+ pci_read_config_byte (cards[i].pdev, 0x42, &r41);
+ pci_read_config_byte (cards[i].pdev, 0x42, &r42);
+ pci_read_config_byte (cards[i].pdev, 0x44, &r44);
+
+ len += sprintf (page+len,
+ "40 AC97 Codec Ready: %s\n"
+ " AC97 Codec Low-power: %s\n"
+ " Secondary Codec Ready: %s\n"
+
+ "41 AC-Link Interface Enable: %s\n"
+
+ "42 Game port enabled: %s\n"
+ " SoundBlaster enabled: %s\n"
+ " FM enabled: %s\n"
+ " MIDI enabled: %s\n"
+
+ "44 AC-Link Interface Access: %s\n"
+ " Secondary Codec Support: %s\n"
+
+ "\n",
+
+ YN (r40, VIA_CR40_AC97_READY),
+ YN (r40, VIA_CR40_AC97_LOW_POWER),
+ YN (r40, VIA_CR40_SECONDARY_READY),
+
+ YN (r41, VIA_CR41_ACLINK_ENABLE),
+
+ YN (r42, VIA_CR42_GAME_ENABLE),
+ YN (r42, VIA_CR42_SB_ENABLE),
+ YN (r42, VIA_CR42_FM_ENABLE),
+ YN (r42, VIA_CR42_MIDI_ENABLE),
+
+ YN (r44, VIA_CR44_AC_LINK_ACCESS),
+ YN (r44, VIA_CR44_SECOND_CODEC_SUPPORT)
+
+ );
+ }
+
+ DPRINTK("EXIT, returning %d\n", len);
+ return len;
+
+#undef YN
+}
+
+
+/****************************************************************
+ *
+ * /proc/driver/via82cxxx
+ *
+ *
+ */
+
+static int __init via_init_proc (void)
+{
+ DPRINTK ("ENTER\n");
+
+ proc_mkdir ("driver/via_audio", 0);
+ create_proc_read_entry ("driver/via_audio/info", 0, 0, via_info_read_proc, NULL);
+
+ DPRINTK("EXIT\n");
+ return 0;
+}
+
+
+
+static void __exit via_cleanup_proc (void)
+{
+ DPRINTK ("ENTER\n");
+ remove_proc_entry ("driver/via_audio/info", NULL);
+ remove_proc_entry ("driver/via_audio", NULL);
+ DPRINTK("EXIT\n");
+}
+
+
+#else
+
+static inline int via_init_proc (void) { return 0; }
+static inline void via_cleanup_proc (void) {}
+
+#endif /* CONFIG_PROC_FS */
+
+
+/****************************************************************
+ *
+ * Legacy SoundBlaster Pro, FM support via OSS
+ *
+ *
+ */
static void __init via_attach_sb(struct address_info *hw_config)
{
+ DPRINTK ("ENTER\n");
+
if(!sb_dsp_init(hw_config))
hw_config->slots[0] = -1;
+
+ DPRINTK("EXIT\n");
}
static int __init via_probe_sb(struct address_info *hw_config)
{
+ DPRINTK ("ENTER\n");
+
if (check_region(hw_config->io_base, 16))
{
printk(KERN_DEBUG PFX "SBPro port 0x%x is already in use\n",
hw_config->io_base);
return 0;
}
+ DPRINTK("EXIT after sb_dsp_detect\n");
return sb_dsp_detect(hw_config, 0, 0);
}
-static void __exit via_unload_sb(struct address_info *hw_config, int unload_mpu)
+static void __exit via_unload_sb(struct address_info *hw_config)
{
- if(hw_config->slots[0]!=-1)
- sb_dsp_unload(hw_config, unload_mpu);
+ DPRINTK ("ENTER\n");
+
+ if(hw_config->slots[0] != -1)
+ sb_dsp_unload(hw_config, 1);
+
+ DPRINTK("EXIT\n");
}
+static const struct {
+ int sb_irq,
+ sb_dma,
+ midi_base,
+ sb_io_base;
+} via_pnp_data[] __initdata = {
+ { 5, 0, 0x300, 0x220 },
+ { 7, 1, 0x310, 0x240 },
+ { 9, 2, 0x320, 0x260 },
+ { 10,3, 0x330, 0x280 },
+};
+
+
+/****************************************************************
+ *
+ * Chip setup and kernel registration
+ *
+ *
+ */
+
static int __init via82cxxx_install (struct pci_dev *pcidev)
{
- int sb_io_base = 0;
- int sb_irq = 0;
- int sb_dma = 0;
- int midi_base = 0;
+ int sb_io_base;
+ int sb_irq;
+ int sb_dma;
+ int midi_base, rc;
u8 tmp8;
+ struct via_info *card = &cards[num_cards];
- memset (&sb_data[cards], 0, sizeof (struct address_info));
- memset (&opl3_data[cards], 0, sizeof (struct address_info));
+ DPRINTK ("ENTER\n");
- sb_data[cards].name = opl3_data[cards].name = VIA_CARD_NAME;
- opl3_data[cards].irq = -1;
+ card->pdev = pcidev;
+ card->have_ac97 = -1;
+
+ /* turn off legacy features, if not already */
+ pci_read_config_byte (pcidev, VIA_FUNC_ENABLE, &tmp8);
+ tmp8 &= ~(VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
+ VIA_CR42_FM_ENABLE);
+ pci_write_config_byte (pcidev, VIA_FUNC_ENABLE, tmp8);
- /* turn on features, if not already */
+ /*
+ * try to init AC97 mixer device
+ */
+ rc = via_attach_ac97 (card);
+ if (rc) {
+ printk (KERN_WARNING PFX
+ "AC97 init failed, SB legacy mode only\n");
+ }
+
+ /* turn on legacy features */
pci_read_config_byte (pcidev, VIA_FUNC_ENABLE, &tmp8);
tmp8 |= VIA_CR42_SB_ENABLE | VIA_CR42_MIDI_ENABLE |
VIA_CR42_FM_ENABLE;
pci_read_config_byte (pcidev, VIA_PNP_CONTROL, &tmp8);
pci_write_config_byte (pcidev, VIA_PNP_CONTROL, tmp8);
- switch ((tmp8 >> 6) & 0x03) {
- case 0: sb_irq = 5; break;
- case 1: sb_irq = 7; break;
- case 2: sb_irq = 9; break;
- case 3: sb_irq = 10; break;
- default: /* do nothing */ break;
- }
- switch ((tmp8 >> 4) & 0x03) {
- case 0: sb_dma = 0; break;
- case 1: sb_dma = 1; break;
- case 2: sb_dma = 2; break;
- case 3: sb_dma = 3; break;
- default: /* do nothing */ break;
- }
- switch ((tmp8 >> 2) & 0x03) {
- case 0: midi_base = 0x300; break;
- case 1: midi_base = 0x310; break;
- case 2: midi_base = 0x320; break;
- case 3: midi_base = 0x330; break;
- default: /* do nothing */ break;
- }
- switch (tmp8 & 0x03) {
- case 0: sb_io_base = 0x220; break;
- case 1: sb_io_base = 0x240; break;
- case 2: sb_io_base = 0x260; break;
- case 3: sb_io_base = 0x280; break;
- default: /* do nothing */ break;
- }
+ sb_irq = via_pnp_data[((tmp8 >> 6) & 0x03)].sb_irq;
+ sb_dma = via_pnp_data[((tmp8 >> 4) & 0x03)].sb_dma;
+ midi_base = via_pnp_data[((tmp8 >> 2) & 0x03)].midi_base;
+ sb_io_base = via_pnp_data[(tmp8 & 0x03)].sb_io_base;
udelay(100);
"MIDI: 0x%X, SB: 0x%X / %d IRQ / %d DMA\n",
midi_base, sb_io_base, sb_irq, sb_dma);
- sb_data[cards].card_subtype = MDL_SBPRO;
- sb_data[cards].io_base = sb_io_base;
- sb_data[cards].irq = sb_irq;
- sb_data[cards].dma = sb_dma;
-
- opl3_data[cards].io_base = midi_base;
+ card->sb_data.name = VIA_CARD_NAME;
+ card->sb_data.card_subtype = MDL_SBPRO;
+ card->sb_data.io_base = sb_io_base;
+ card->sb_data.irq = sb_irq;
+ card->sb_data.dma = sb_dma;
/* register legacy SoundBlaster Pro */
- if (!via_probe_sb (&sb_data[cards])) {
+ if (!via_probe_sb (&card->sb_data)) {
printk (KERN_ERR PFX
"SB probe @ 0x%X failed, aborting\n",
sb_io_base);
+ DPRINTK ("EXIT, returning -1\n");
return -1;
}
- via_attach_sb (&sb_data[cards]);
+ via_attach_sb (&card->sb_data);
+ card->opl3_data.name = card->sb_data.name;
+ card->opl3_data.io_base = midi_base;
+ card->opl3_data.irq = -1;
+
/* register legacy MIDI */
- if (!via_probe_midi (&opl3_data[cards])) {
- printk (KERN_ERR PFX
- "MIDI probe @ 0x%X failed, aborting\n",
+ if (!probe_uart401 (&card->opl3_data)) {
+ printk (KERN_WARNING PFX
+ "MIDI probe @ 0x%X failed, continuing\n",
midi_base);
- via_unload_sb (&sb_data[cards], 0);
- return -1;
+ card->opl3_data.io_base = 0;
+ } else {
+ attach_uart401 (&card->opl3_data);
}
- via_attach_midi (&opl3_data[cards]);
- cards++;
+ num_cards++;
+ DPRINTK ("EXIT, returning 0\n");
return 0;
}
/*
* This loop walks the PCI configuration database and finds where
* the sound cards are.
+ *
+ * Note - only a single PCI scan occurs, eliminating possibility
+ * of multiple audio chips
+ *
*/
static int __init probe_via82cxxx (void)
{
struct pci_dev *pcidev = NULL;
- while ((pcidev = pci_find_device (PCI_VENDOR_ID_VIA,
- PCI_DEVICE_ID_VIA_82C686_5,
- pcidev)) != NULL) {
+ DPRINTK ("ENTER\n");
- if (via82cxxx_install (pcidev) != 0) {
- printk (KERN_ERR PFX "audio init failed\n");
- return -1;
- }
+ pcidev = pci_find_device (PCI_VENDOR_ID_VIA,
+ PCI_DEVICE_ID_VIA_82C686_5, NULL);
- if (cards == MAX_CARDS) {
- printk (KERN_DEBUG PFX "maximum number of cards reached\n");
- break;
- }
+ if (!pcidev || via82cxxx_install (pcidev) != 0) {
+ printk (KERN_ERR PFX "audio init failed\n");
+ DPRINTK ("EXIT, returning -1\n");
+ return -1;
}
+ DPRINTK ("EXIT, returning 0\n");
return 0;
}
static int __init init_via82cxxx_module(void)
{
+ u8 tmp;
+ int i;
+ const char *rev = "unknown!";
+
+ memset (cards, 0, sizeof (cards));
+
+ DPRINTK ("ENTER\n");
+
if (!pci_present ()) {
printk (KERN_DEBUG PFX "PCI not present, exiting\n");
+ DPRINTK ("EXIT, returning -ENODEV\n");
return -ENODEV;
}
if (probe_via82cxxx() != 0) {
printk(KERN_ERR PFX "probe failed, aborting\n");
/* XXX unload cards registered so far, if any */
+ DPRINTK ("EXIT, returning -ENODEV\n");
return -ENODEV;
}
- if (cards == 0) {
- printk(KERN_DEBUG PFX "No chips found, aborting\n");
- return -ENODEV;
- }
-
+ pci_read_config_byte (cards[0].pdev, PCI_REVISION_ID, &tmp);
+ for (i = 0; i < arraysize(via_chip_revs); i++)
+ if (via_chip_revs[i].revision == tmp) {
+ rev = via_chip_revs[i].rev_name;
+ break;
+ }
printk (KERN_INFO PFX VIA_CARD_NAME " loaded\n");
+ printk (KERN_INFO PFX "Chip rev %s. Features: SBPro compat%s%s\n",
+ rev,
+ cards[0].opl3_data.io_base == 0 ? "" : ", MPU-401 MIDI",
+ cards[0].have_ac97 == -1 ? "" : ", AC97 mixer");
+ if (via_init_proc () != 0) {
+ printk (KERN_WARNING PFX
+ "Unable to init experimental /proc, ignoring\n");
+ }
+
/*
* Binds us to the sound subsystem
*/
SOUND_LOCK;
+ DPRINTK ("EXIT, returning 0\n");
return 0;
}
static void __exit cleanup_via82cxxx_module(void)
{
- int i;
+ DPRINTK("ENTER\n");
+
+ if (cards[0].opl3_data.io_base)
+ unload_uart401 (&cards[0].opl3_data);
+
+ via_unload_sb (&cards[0].sb_data);
- for (i = 0; i < cards; i++)
- via_unload_sb (&sb_data[i], 1);
+ via_unload_ac97 (&cards[0]);
+ via_cleanup_proc ();
+
/*
* Final clean up with the sound layer
*/
SOUND_LOCK_END;
+
+ DPRINTK("EXIT\n");
}
module_init(init_via82cxxx_module);
fi
dep_tristate ' Joystick support' CONFIG_INPUT_JOYDEV $CONFIG_USB_HID
dep_tristate ' Event interface support' CONFIG_INPUT_EVDEV $CONFIG_USB_HID
- bool ' USB HID debug output' CONFIG_USB_HID_DEBUG
- if [ "$CONFIG_USB_HID_DEBUG" != "n" ]; then
- bool ' USB HID lots of debug output' CONFIG_USB_HID_DEBUG_LOTS
- fi
fi
dep_tristate ' USB Printer support' CONFIG_USB_PRINTER $CONFIG_USB
dep_tristate ' USB Scanner support' CONFIG_USB_SCANNER $CONFIG_USB
#include <linux/module.h>
#include <linux/config.h>
-#include "usb.h"
+#undef DEBUG
-#ifdef CONFIG_USB_ACM_DEBUG
-#define acm_debug(fmt,arg...) printk(KERN_DEBUG "acm: " fmt "\n" , ##arg)
-#else
-#define acm_debug(fmt,arg...) do {} while(0)
-#endif
+#include "usb.h"
/*
* Major and minor numbers.
static void acm_set_control(unsigned int status, struct acm *acm)
{
if (usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), 0x22, 0x22, status, 0, NULL, 0, HZ) < 0)
- acm_debug("acm_set_control() failed");
+ dbg("acm_set_control() failed");
- acm_debug("output control lines: dtr%c rts%c",
+ dbg("output control lines: dtr%c rts%c",
acm->ctrlout & ACM_CTRL_DTR ? '+' : '-', acm->ctrlout & ACM_CTRL_RTS ? '+' : '-');
}
static void acm_set_coding(struct acm_coding *coding, struct acm *acm)
{
if (usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), 0x30, 0x22, 0, 0, coding, sizeof(struct acm_coding), HZ) < 0)
- acm_debug("acm_set_coding() failed");
+ dbg("acm_set_coding() failed");
}
static void acm_send_break(int ms, struct acm *acm)
{
if (usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), 0x30, 0x33, ms, 0, NULL, 0, HZ) < 0)
- acm_debug("acm_send_break() failed");
+ dbg("acm_send_break() failed");
}
#endif
unsigned char *data = (unsigned char *)(dr + 1);
if (urb->status < 0) {
- acm_debug("nonzero ctrl irq status received: %d", urb->status);
+ dbg("nonzero ctrl irq status received: %d", urb->status);
return;
}
case 0x20: /* Set serial line state */
if ((dr->index != 1) || (dr->length != 2)) {
- acm_debug("unknown set serial line request: index %d len %d", dr->index, dr->length);
+ dbg("unknown set serial line request: index %d len %d", dr->index, dr->length);
return;
}
acm->ctrlin = data[0] | (((unsigned int) data[1]) << 8);
- acm_debug("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
+ dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c",
acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', acm->ctrlin & ACM_CTRL_DSR ? '+' : '-',
acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', acm->ctrlin & ACM_CTRL_RI ? '+' : '-',
acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-',
return;
default:
- acm_debug("unknown control event received: request %d index %d len %d data0 %d data1 %d",
+ dbg("unknown control event received: request %d index %d len %d data0 %d data1 %d",
dr->request, dr->index, dr->length, data[0], data[1]);
return;
}
int i;
if (urb->status) {
- acm_debug("nonzero read bulk status received: %d", urb->status);
+ dbg("nonzero read bulk status received: %d", urb->status);
return;
}
tty_flip_buffer_push(tty);
if (usb_submit_urb(urb))
- acm_debug("failed resubmitting read urb");
+ dbg("failed resubmitting read urb");
return;
}
struct tty_struct *tty = acm->tty;
if (urb->status) {
- acm_debug("nonzero write bulk status received: %d", urb->status);
+ dbg("nonzero write bulk status received: %d", urb->status);
return;
}
if (acm->used++) return 0;
if (usb_submit_urb(&acm->ctrlurb))
- acm_debug("usb_submit_urb(ctrl irq) failed");
+ dbg("usb_submit_urb(ctrl irq) failed");
if (usb_submit_urb(&acm->readurb))
- acm_debug("usb_submit_urb(read bulk) failed");
+ dbg("usb_submit_urb(read bulk) failed");
acm_set_control(acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS, acm);
acm->writeurb.transfer_buffer_length = count;
if (usb_submit_urb(&acm->writeurb))
- acm_debug("usb_submit_urb(write bulk) failed");
+ dbg("usb_submit_urb(write bulk) failed");
return count;
}
static void acm_tty_set_termios(struct tty_struct *tty, struct termios *old)
{
- acm_debug("set_termios called, but not there yet");
+ dbg("set_termios called, but not there yet");
return;
}
for (minor = 0; minor < ACM_TTY_MINORS &&
(acm_table[minor].present || acm_table[minor].used); minor++);
if (acm_table[minor].present || acm_table[minor].used) {
- acm_debug("no more free acm devices");
+ dbg("no more free acm devices");
return NULL;
}
acm = acm_table + minor;
for (i = 0; i < dev->descriptor.bNumConfigurations; i++) {
- acm_debug("probing config %d", i);
+ dbg("probing config %d", i);
acm->cfg = dev->config + i;
ifcom = acm->cfg->interface[0].altsetting + 0;
struct acm *acm = ptr;
if (!acm->present) {
- acm_debug("disconnect on nonexisting interface");
+ dbg("disconnect on nonexisting interface");
return;
}
#include <asm/atomic.h>
#include <linux/delay.h>
+#undef DEBUG
+#undef DEBUG_ALL
+
#include "usb.h"
#include "dabusb.h"
#ifdef DEBUG
static void dump_urb (purb_t purb)
{
- printk ("urb :%p\n", purb);
- printk ("next :%p\n", purb->next);
- printk ("dev :%p\n", purb->dev);
- printk ("pipe :%08X\n", purb->pipe);
- printk ("status :%d\n", purb->status);
- printk ("transfer_flags :%08X\n", purb->transfer_flags);
- printk ("transfer_buffer :%p\n", purb->transfer_buffer);
- printk ("transfer_buffer_length:%d\n", purb->transfer_buffer_length);
- printk ("actual_length :%d\n", purb->actual_length);
- printk ("setup_packet :%p\n", purb->setup_packet);
- printk ("start_frame :%d\n", purb->start_frame);
- printk ("number_of_packets :%d\n", purb->number_of_packets);
- printk ("interval :%d\n", purb->interval);
- printk ("error_count :%d\n", purb->error_count);
- printk ("context :%p\n", purb->context);
- printk ("complete :%p\n", purb->complete);
+ dbg("urb :%p", purb);
+ dbg("next :%p", purb->next);
+ dbg("dev :%p", purb->dev);
+ dbg("pipe :%08X", purb->pipe);
+ dbg("status :%d", purb->status);
+ dbg("transfer_flags :%08X", purb->transfer_flags);
+ dbg("transfer_buffer :%p", purb->transfer_buffer);
+ dbg("transfer_buffer_length:%d", purb->transfer_buffer_length);
+ dbg("actual_length :%d", purb->actual_length);
+ dbg("setup_packet :%p", purb->setup_packet);
+ dbg("start_frame :%d", purb->start_frame);
+ dbg("number_of_packets :%d", purb->number_of_packets);
+ dbg("interval :%d", purb->interval);
+ dbg("error_count :%d", purb->error_count);
+ dbg("context :%p", purb->context);
+ dbg("complete :%p", purb->complete);
}
#endif
/*-------------------------------------------------------------------*/
struct list_head *p;
pbuff_t b;
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "dabusb_cancel_queue\n");
-#endif
+ dbg("dabusb_cancel_queue");
spin_lock_irqsave (&s->lock, flags);
for (p = q->next; p != q; p = p->next) {
struct list_head *p;
pbuff_t b;
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "dabusb_free_queue\n");
-#endif
+ dbg("dabusb_free_queue");
for (p = q->next; p != q;) {
b = list_entry (p, buff_t, buff_list);
#ifdef DEBUG
/*-------------------------------------------------------------------*/
static int dabusb_free_buffers (pdabusb_t s)
{
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "dabusb_free_buffers\n");
-#endif
+ dbg("dabusb_free_buffers");
dabusb_free_queue (&s->free_buff_list);
dabusb_free_queue (&s->rec_buff_list);
s->got_mem = 0;
void *buf = purb->transfer_buffer;
#ifdef DEBUG_ALL
- printk(KERN_DEBUG MODSTR"dabusb_iso_complete\n");
+ dbg("dabusb_iso_complete");
#endif
if (purb->status != USB_ST_URB_KILLED) {
unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE);
dst += len;
}
else
- printk (KERN_ERR MODSTR "dabusb_iso_complete: invalid len %d\n", len);
+ err("dabusb_iso_complete: invalid len %d", len);
}
if (dst != purb->actual_length)
- printk (KERN_ERR MODSTR "dst!=purb->actual_length:%d!=%d\n", dst, purb->actual_length);
+ err("dst!=purb->actual_length:%d!=%d", dst, purb->actual_length);
}
if (atomic_dec_and_test (&s->pending_io) && !s->remove_pending && s->state != _stopped) {
s->overruns++;
- printk (KERN_ERR MODSTR "overrun (%d)\n", s->overruns);
+ err("overrun (%d)", s->overruns);
}
wake_up (&s->wait);
}
int i;
int len = sizeof (urb_t) + packets * sizeof (iso_packet_descriptor_t);
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "dabusb_alloc_buffers len:%d pipesize:%d packets:%d transfer_buffer_len:%d\n",
+ dbg("dabusb_alloc_buffers len:%d pipesize:%d packets:%d transfer_buffer_len:%d",
len, pipesize, packets, transfer_buffer_length);
-#endif
while (buffers < (s->total_buffer_size << 10)) {
b = (pbuff_t) kmalloc (sizeof (buff_t), GFP_KERNEL);
if (!b) {
- printk (KERN_ERR MODSTR "kmalloc(sizeof(buff_t))==NULL\n");
+ err("kmalloc(sizeof(buff_t))==NULL");
goto err;
}
memset (b, sizeof (buff_t), 0);
b->s = s;
b->purb = (purb_t) kmalloc (len, GFP_KERNEL);
if (!b->purb) {
- printk (KERN_ERR MODSTR "kmalloc(sizeof(urb_t)+packets*sizeof(iso_packet_descriptor_t))==NULL\n");
+ err("kmalloc(sizeof(urb_t)+packets*sizeof(iso_packet_descriptor_t))==NULL");
kfree (b);
goto err;
}
if (!b->purb->transfer_buffer) {
kfree (b->purb);
kfree (b);
- printk (KERN_ERR MODSTR "kmalloc(%d)==NULL\n", transfer_buffer_length);
+ err("kmalloc(%d)==NULL", transfer_buffer_length);
goto err;
}
/*-------------------------------------------------------------------*/
static int dabusb_reset_pipe (struct usb_device *usbdev, unsigned int ep)
{
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "dabusb_reset_pipe\n");
-#endif
+ dbg("dabusb_reset_pipe");
if ((ep & ~0x80) >= 16)
return -EINVAL;
ret = usb_submit_urb (purb);
if (ret < 0) {
- printk (KERN_DEBUG MODSTR "dabusb_bulk: usb_submit_urb returned %d\n", ret);
+ dbg("dabusb_bulk: usb_submit_urb returned %d", ret);
return -EINVAL;
}
interruptible_sleep_on_timeout (&context.wait, HZ);
if (purb->status == USB_ST_URB_PENDING) {
- printk (KERN_ERR MODSTR "dabusb_usb_submit_urb: %p timed out\n", purb);
+ err("dabusb_usb_submit_urb: %p timed out", purb);
usb_unlink_urb (purb);
dabusb_reset_pipe(purb->dev, purb->pipe);
return -ETIMEDOUT;
pbulk_completion_context_t context = purb->context;
#ifdef DEBUG_ALL
- printk(KERN_DEBUG MODSTR"dabusb_bulk_complete\n");
+ dbg("dabusb_bulk_complete");
dump_urb(purb);
#endif
wake_up (&context->wait);
unsigned int pipe;
#ifdef DEBUG_ALL
- printk(KERN_DEBUG MODSTR"dabusb_bulk\n");
+ dbg("dabusb_bulk");
#endif
if (!pb->pipe)
unsigned char *transfer_buffer;
if (!setup) {
- printk (KERN_ERR MODSTR "dabusb_writemem: kmalloc(8) failed.\n");
+ err("dabusb_writemem: kmalloc(8) failed.");
return -ENOMEM;
}
transfer_buffer = kmalloc (len, GFP_KERNEL);
if (!transfer_buffer) {
- printk (KERN_ERR MODSTR "dabusb_writemem: kmalloc(%d) failed.\n", len);
+ err("dabusb_writemem: kmalloc(%d) failed.", len);
kfree (setup);
return -ENOMEM;
}
/* --------------------------------------------------------------------- */
static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit)
{
-#ifdef DEBUG
- printk("dabusb_8051_reset: %d\n",reset_bit);
-#endif
+ dbg("dabusb_8051_reset: %d",reset_bit);
return dabusb_writemem (s, CPUCS_REG, &reset_bit, 1);
}
/* --------------------------------------------------------------------- */
int ret;
PINTEL_HEX_RECORD ptr = firmware;
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "Enter dabusb_loadmem (internal)\n");
-#endif
+ dbg("Enter dabusb_loadmem (internal)");
+
ret = dabusb_8051_reset (s, 1);
while (ptr->Type == 0) {
#ifdef DEBUG_ALL
- printk(KERN_ERR MODSTR"dabusb_writemem: %04X %p %d)\n", ptr->Address, ptr->Data, ptr->Length);
+ err("dabusb_writemem: %04X %p %d)", ptr->Address, ptr->Data, ptr->Length);
#endif
ret = dabusb_writemem (s, ptr->Address, ptr->Data, ptr->Length);
if (ret < 0) {
- printk (KERN_ERR MODSTR "dabusb_writemem failed (%04X %p %d)\n", ptr->Address, ptr->Data, ptr->Length);
+ err("dabusb_writemem failed (%04X %p %d)", ptr->Address, ptr->Data, ptr->Length);
break;
}
ptr++;
}
ret = dabusb_8051_reset (s, 0);
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "dabusb_loadmem: exit\n");
-#endif
+ dbg("dabusb_loadmem: exit");
return ret;
}
/* --------------------------------------------------------------------- */
b->data[2] = 0;
b->data[3] = 0;
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "dabusb_fpga_clear\n");
-#endif
+ dbg("dabusb_fpga_clear");
return dabusb_bulk (s, b);
}
/* --------------------------------------------------------------------- */
b->data[2] = 0;
b->data[3] = 0;
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "dabusb_fpga_init\n");
-#endif
+ dbg("dabusb_fpga_init");
return dabusb_bulk (s, b);
}
/* --------------------------------------------------------------------- */
int ret;
unsigned char *buf = bitstream;
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "Enter dabusb_fpga_download (internal)\n");
-#endif
+ dbg("Enter dabusb_fpga_download (internal)");
if (!b) {
- printk (KERN_ERR MODSTR "kmalloc(sizeof(bulk_transfer_t))==NULL\n");
+ err("kmalloc(sizeof(bulk_transfer_t))==NULL");
return -ENOMEM;
}
ret = dabusb_fpga_clear (s, b);
mdelay (10);
blen = buf[73] + (buf[72] << 8);
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "Bitstream len: %i\n", blen);
-#endif
+ dbg("Bitstream len: %i", blen);
b->data[0] = 0x2b;
b->data[1] = 0;
b->data[2] = 0;
memcpy (b->data + 4, buf + 74 + n, 60);
ret = dabusb_bulk (s, b);
if (ret < 0) {
- printk (KERN_ERR MODSTR "dabusb_bulk failed.\n");
+ err("dabusb_bulk failed.");
break;
}
mdelay (1);
ret = dabusb_fpga_init (s, b);
kfree (b);
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "exit dabusb_fpga_download\n");
-#endif
+ dbg("exit dabusb_fpga_download");
return ret;
}
static int dabusb_stop (pdabusb_t s)
{
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "dabusb_stop\n");
-#endif
+ dbg("dabusb_stop");
s->state = _stopped;
dabusb_cancel_queue (s, &s->rec_buff_list);
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "pending_io: %d\n", s->pending_io.counter);
-#endif
+ dbg("pending_io: %d", s->pending_io.counter);
s->pending_io.counter = 0;
return 0;
static int dabusb_startrek (pdabusb_t s)
{
if (!s->got_mem && s->state != _started) {
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "dabusb_startrek\n");
-#endif
+ dbg("dabusb_startrek");
if (dabusb_alloc_buffers (s) < 0)
return -ENOMEM;
while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) {
#ifdef DEBUG_ALL
- printk("submitting: end:%p s->rec_buff_list:%p\n", s->rec_buff_list.prev, &s->rec_buff_list);
+ dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list);
#endif
end = list_entry (s->rec_buff_list.prev, buff_t, buff_list);
ret = usb_submit_urb (end->purb);
if (ret) {
- printk (KERN_ERR MODSTR "usb_submit_urb returned:%d\n", ret);
+ err("usb_submit_urb returned:%d", ret);
if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
- printk (KERN_ERR MODSTR "startrek: dabusb_add_buf_tail failed");
+ err("startrek: dabusb_add_buf_tail failed");
}
else
atomic_inc (&s->pending_io);
}
#ifdef DEBUG_ALL
- printk(KERN_DEBUG MODSTR"pending_io: %d\n",s->pending_io.counter);
+ dbg("pending_io: %d",s->pending_io.counter);
#endif
}
return 0;
purb_t purb = NULL;
#ifdef DEBUG_ALL
- printk(KERN_DEBUG MODSTR"dabusb_read\n");
+ dbg("dabusb_read");
#endif
if (*ppos)
while (count > 0) {
dabusb_startrek (s);
if (list_empty (&s->rec_buff_list)) {
- printk (KERN_ERR MODSTR "error: rec_buf_list is empty\n");
+ err("error: rec_buf_list is empty");
goto err;
}
b = list_entry (s->rec_buff_list.next, buff_t, buff_list);
goto err;
}
if (list_empty (&s->rec_buff_list)) {
- printk (KERN_ERR MODSTR "error: still no buffer available.\n");
+ err("error: still no buffer available.");
goto err;
}
s->readptr = 0;
cnt = count;
#ifdef DEBUG_ALL
- printk("copy_to_user:%p %p %d\n",buf, purb->transfer_buffer + s->readptr, cnt);
+ dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt);
#endif
if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) {
- printk (KERN_ERR MODSTR "read: copy_to_user failed\n");
+ err("read: copy_to_user failed");
if (!ret)
ret = -EFAULT;
goto err;
if (s->readptr == purb->actual_length) {
// finished, take next buffer
if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list))
- printk (KERN_ERR MODSTR "read: dabusb_add_buf_tail failed");
+ err("read: dabusb_add_buf_tail failed");
s->readptr = 0;
}
}
MOD_INC_USE_COUNT;
s = &dabusb[devnum - DABUSB_MINOR];
- printk (KERN_DEBUG MODSTR "dabusb_open\n");
+ dbg("dabusb_open");
down (&s->mutex);
while (!s->usbdev || s->opened) {
up (&s->mutex);
if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) {
- printk (KERN_ERR "dabusb: set_interface failed\n");
+ err("dabusb: set_interface failed");
MOD_DEC_USE_COUNT;
return -EINVAL;
}
{
pdabusb_t s = (pdabusb_t) file->private_data;
- printk (KERN_DEBUG MODSTR "dabusb_release\n");
+ dbg("dabusb_release");
down (&s->mutex);
dabusb_stop (s);
if (!s->remove_pending) {
if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0)
- printk (KERN_ERR "dabusb: set_interface failed\n");
+ err("dabusb: set_interface failed");
}
else
wake_up (&s->remove_ok);
int version = DABUSB_VERSION;
DECLARE_WAITQUEUE (wait, current);
-// printk(KERN_DEBUG MODSTR"dabusb_ioctl\n");
+// dbg("dabusb_ioctl");
if (s->remove_pending)
return -EIO;
int devnum;
pdabusb_t s;
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d\n",
+ dbg("dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d",
usbdev->descriptor.idVendor, usbdev->descriptor.idProduct, ifnum);
-#endif
/* the 1234:5678 is just a self assigned test ID */
if ((usbdev->descriptor.idVendor != 0x0547 || usbdev->descriptor.idProduct != 0x2131) &&
s->usbdev = usbdev;
if (usb_set_configuration (usbdev, usbdev->config[0].bConfigurationValue) < 0) {
- printk (KERN_ERR MODSTR "set_configuration failed\n");
+ err("set_configuration failed");
goto reject;
}
if (usbdev->descriptor.idProduct == 0x2131)
dabusb_fpga_download (s, NULL);
if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) {
- printk (KERN_ERR MODSTR "set_interface failed\n");
+ err("set_interface failed");
goto reject;
}
}
- printk (KERN_DEBUG MODSTR "bound to interface: %d\n", ifnum);
+ dbg("bound to interface: %d", ifnum);
up (&s->mutex);
MOD_INC_USE_COUNT;
return s;
{
pdabusb_t s = (pdabusb_t) ptr;
- printk (KERN_DEBUG MODSTR "dabusb_disconnect\n");
+ dbg("dabusb_disconnect");
s->remove_pending = 1;
wake_up (&s->wait);
/* register misc device */
usb_register (&dabusb_driver);
-#ifdef DEBUG
- printk (KERN_INFO "dabusb_init: driver registered\n");
-#endif
+ dbg("dabusb_init: driver registered");
return 0;
}
void __exit dabusb_cleanup (void)
{
-#ifdef DEBUG
- printk (KERN_DEBUG MODSTR "dabusb_cleanup\n");
-#endif
+ dbg("dabusb_cleanup");
usb_deregister (&dabusb_driver);
}
#ifdef __KERNEL__
-#ifdef MODSTR
-#undef MODSTR
-#endif
-#define MODSTR "dabusb: "
-
typedef enum { _stopped=0, _started } driver_state_t;
-
typedef struct
{
struct semaphore mutex;
BYTE Data[MAX_INTEL_HEX_RECORD_LENGTH];
} INTEL_HEX_RECORD, *PINTEL_HEX_RECORD;
-#endif
\ No newline at end of file
+#endif
#include <linux/malloc.h>
#include <linux/module.h>
-#include "usb.h"
-
-
-// #define CAMERA_DEBUG
+#undef DEBUG
+#include "usb.h"
/* XXX need to get registered minor number, cdev 10/MINOR */
/* XXX or: cdev USB_MAJOR(180)/USB_CAMERA_MINOR */
usb_rcvbulkpipe (camera->dev, camera->inEP),
camera->buf, len, &count, HZ*10);
-#ifdef CAMERA_DEBUG
- printk ("camera.r (%d) - 0x%x %ld\n", len, result, count);
-#endif
+ dbg("read (%d) - 0x%x %ld", len, result, count);
+
if (!result) {
if (copy_to_user (buf, camera->buf, count))
return -EFAULT;
if (result != USB_ST_TIMEOUT)
break;
interruptible_sleep_on_timeout (&camera->wait, RETRY_TIMEOUT);
-#ifdef CAMERA_DEBUG
- printk ("camera.r (%d) - retry\n", len);
-#endif
+
+ dbg("read (%d) - retry", len);
}
camera->isActive = 0;
return -EIO;
result = usb_bulk_msg (camera->dev,
usb_sndbulkpipe (camera->dev, camera->outEP),
obuf, thistime, &count, HZ*10);
-#ifdef CAMERA_DEBUG
+
if (result)
- printk ("camera.w USB err - %x\n", result);
-#endif
+ dbg("write USB err - %x", result);
+
if (count) {
obuf += count;
thistime -= count;
}
done:
camera->isActive = 0;
-#ifdef CAMERA_DEBUG
- printk ("camera.w %d\n", bytes_written);
-#endif
+
+ dbg("write %d", bytes_written);
+
return bytes_written;
}
camera->isOpen = 0;
return -ENOMEM;
}
-#ifdef CAMERA_DEBUG
- printk ("camera.open\n");
-#endif
+
+ dbg("open");
/* Keep driver from being unloaded while it's in use */
MOD_INC_USE_COUNT;
kfree (camera->buf);
camera->isOpen = 0;
MOD_DEC_USE_COUNT;
-#ifdef CAMERA_DEBUG
- printk ("camera.close\n");
-#endif
+
+ dbg("close");
return 0;
}
/* these have one config, one interface */
if (dev->descriptor.bNumConfigurations != 1
|| dev->config[0].bNumInterfaces != 1) {
- printk (KERN_INFO "Bogus camera config info\n");
+ dbg("Bogus camera config info");
return NULL;
}
|| interface->bInterfaceProtocol != 0
|| interface->bNumEndpoints != 2
) {
- printk (KERN_INFO "Bogus camera interface info\n");
+ dbg("Bogus camera interface info");
return NULL;
}
/* can only show one camera at a time through /dev ... */
if (!camera->dev) {
camera->dev = dev;
- printk(KERN_INFO "USB Camera is connected\n");
+ info("USB Camera is connected");
} else {
- printk(KERN_INFO "Ignoring additional USB Camera\n");
+ info("Ignoring additional USB Camera");
return NULL;
}
|| endpoint [0].bmAttributes != USB_ENDPOINT_XFER_BULK
|| endpoint [1].bmAttributes != USB_ENDPOINT_XFER_BULK
) {
- printk (KERN_INFO "Bogus camera endpoints\n");
+ dbg("Bogus camera endpoints");
camera->dev = NULL;
return NULL;
}
if (usb_set_configuration (dev, dev->config[0].bConfigurationValue)) {
- printk (KERN_INFO "Failed usb_set_configuration: camera\n");
+ err("Failed usb_set_configuration");
camera->dev = NULL;
return NULL;
}
camera->info = NULL;
camera->dev = NULL;
- printk (KERN_INFO "USB Camera disconnected\n");
+ info("USB Camera disconnected");
}
static /* const */ struct usb_driver camera_driver = {
#include <linux/list.h>
#include <linux/malloc.h>
#include <linux/smp_lock.h>
-//#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
+#define DEBUG
+
#include "usb.h"
#include "hub.h"
USB_DT_HUB << 8, 0, data, size, HZ);
}
+#if 0
static int usb_clear_hub_feature(struct usb_device *dev, int feature)
{
return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_CLEAR_FEATURE, USB_RT_HUB, feature, 0 , NULL, 0, HZ);
}
+#endif
static int usb_clear_port_feature(struct usb_device *dev, int port, int feature)
{
descriptor = (struct usb_hub_descriptor *)bitmap;
hub->nports = dev->maxchild = descriptor->bNbrPorts;
- printk(KERN_INFO "hub: %d port%s detected\n", hub->nports,
- (hub->nports == 1) ? "" : "s");
+ info("%d port%s detected", hub->nports, (hub->nports == 1) ? "" : "s");
switch (descriptor->wHubCharacteristics & HUB_CHAR_LPSM) {
case 0x00:
- printk(KERN_INFO "hub: ganged power switching\n");
+ dbg("ganged power switching");
break;
case 0x01:
- printk(KERN_INFO "hub: individual port power switching\n");
+ dbg("individual port power switching");
break;
case 0x02:
case 0x03:
- printk(KERN_INFO "hub: unknown reserved power switching mode\n");
+ dbg("unknown reserved power switching mode");
break;
}
if (descriptor->wHubCharacteristics & HUB_CHAR_COMPOUND)
- printk(KERN_INFO "hub: part of a compound device\n");
+ dbg("part of a compound device");
else
- printk(KERN_INFO "hub: standalone hub\n");
+ dbg("standalone hub");
switch (descriptor->wHubCharacteristics & HUB_CHAR_OCPM) {
case 0x00:
- printk(KERN_INFO "hub: global over-current protection\n");
+ dbg("global over-current protection");
break;
case 0x08:
- printk(KERN_INFO "hub: individual port over-current protection\n");
+ dbg("individual port over-current protection");
break;
case 0x10:
case 0x18:
- printk(KERN_INFO "hub: no over-current protection\n");
+ dbg("no over-current protection");
break;
}
- printk(KERN_INFO "hub: power on to power good time: %dms\n",
- descriptor->bPwrOn2PwrGood * 2);
-
- printk(KERN_INFO "hub: hub controller current requirement: %dmA\n",
- descriptor->bHubContrCurrent);
+ dbg("power on to power good time: %dms", descriptor->bPwrOn2PwrGood * 2);
+ dbg("hub controller current requirement: %dmA", descriptor->bHubContrCurrent);
for (i = 0; i < dev->maxchild; i++)
- printk(KERN_INFO "hub: port %d is%s removable\n", i + 1,
+ dbg("port %d is%s removable", i + 1,
bitmap[7 + ((i + 1)/8)] & (1 << ((i + 1) % 8))
? " not" : "");
return -1;
hubsts = (struct usb_hub_status *)buffer;
- printk(KERN_INFO "hub: local power source is %s\n",
+ dbg("local power source is %s",
(le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_LOCAL_POWER) ? "lost (inactive)" : "good");
- printk(KERN_INFO "hub: %sover-current condition exists\n",
+ dbg("%sover-current condition exists",
(le16_to_cpu(hubsts->wHubStatus) & HUB_STATUS_OVERCURRENT) ? "" : "no ");
/* Enable power to the ports */
- printk(KERN_INFO "hub: enabling power on all ports\n");
+ dbg("enabling power on all ports");
for (i = 0; i < hub->nports; i++)
usb_set_port_feature(dev, i + 1, USB_PORT_FEAT_POWER);
return 0;
return NULL;
/* We found a hub */
- printk(KERN_INFO "USB hub found\n");
+ info("USB hub found");
if ((hub = kmalloc(sizeof(*hub), GFP_KERNEL)) == NULL) {
- printk(KERN_ERR "couldn't kmalloc hub struct\n");
+ err("couldn't kmalloc hub struct");
return NULL;
}
hub_irq, endpoint->bInterval,
hub, &hub->irq_handle);
if (ret) {
- printk (KERN_WARNING "hub: usb_request_irq failed (%d)\n", ret);
+ err("usb_request_irq failed (%d)", ret);
/* free hub, but first clean up its list. */
spin_lock_irqsave(&hub_event_lock, flags);
wait_ms(100);
/* Check status */
if (usb_get_port_status(hub, port + 1, &portsts)<0) {
- printk(KERN_ERR "get_port_status failed\n");
+ err("get_port_status failed");
return;
}
portstatus = le16_to_cpu(portsts.wPortStatus);
portchange = le16_to_cpu(portsts.wPortChange);
- printk("hub.c: portstatus %x, change %x, %s\n",portstatus,portchange,
- (portstatus&(1<<USB_PORT_FEAT_LOWSPEED)?"Low Speed":"High Speed"));
+ dbg("portstatus %x, change %x, %s", portstatus, portchange,
+ portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed");
/* If it's not in CONNECT and ENABLE state, we're done */
if ((!(portstatus & USB_PORT_STAT_CONNECTION)) &&
(!(portstatus & USB_PORT_STAT_ENABLE))) {
wait_ms(200);
if (usb_get_port_status(hub, port + 1, &portsts)<0) {
- printk(KERN_ERR "get_port_status failed\n");
+ err("get_port_status failed");
return;
}
portstatus = le16_to_cpu(portsts.wPortStatus);
portchange = le16_to_cpu(portsts.wPortChange);
- printk("hub.c: portstatus %x, change %x, %s\n",portstatus,portchange,
- (portstatus&(1<<USB_PORT_FEAT_LOWSPEED)?"Low Speed":"High Speed"));
+ dbg("portstatus %x, change %x, %s", portstatus ,portchange,
+ portstatus&(1<<USB_PORT_FEAT_LOWSPEED) ? "Low Speed" : "High Speed");
if ((portstatus&(1<<USB_PORT_FEAT_ENABLE)))
break;
}
if (tries==MAX_TRIES) {
- printk("hub.c: Can not enable port %i after %i retries, disabling port\n",port+1,MAX_TRIES);
+ err("can not enable port %i after %i retries, disabling port", port+1, MAX_TRIES);
return;
}
/* Allocate a new device struct for it */
usb = usb_alloc_dev(hub, hub->bus);
if (!usb) {
- printk(KERN_ERR "couldn't allocate usb_device\n");
+ err("couldn't allocate usb_device");
return;
}
/* Run it through the hoops (find a driver, etc) */
if (usb_new_device(usb)) {
/* Woops, disable the port */
- printk(KERN_DEBUG "hub: disabling port %d\n",
- port + 1);
+ dbg("hub: disabling port %d", port + 1);
usb_clear_port_feature(hub, port + 1, USB_PORT_FEAT_ENABLE);
}
}
unsigned short portstatus, portchange;
if (usb_get_port_status(dev, i + 1, &portsts) < 0) {
- printk(KERN_ERR "get_port_status failed\n");
+ err("get_port_status failed");
continue;
}
portchange = le16_to_cpu(portsts.wPortChange);
if (portchange & USB_PORT_STAT_C_CONNECTION) {
- printk(KERN_INFO "hub: port %d connection change\n",
- i + 1);
+ dbg("port %d connection change", i + 1);
- usb_clear_port_feature(dev, i + 1,
- USB_PORT_FEAT_C_CONNECTION);
+ usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_CONNECTION);
usb_hub_port_connect_change(dev, i);
}
if (portchange & USB_PORT_STAT_C_ENABLE) {
- printk(KERN_INFO "hub: port %d enable change\n",
- i + 1);
- usb_clear_port_feature(dev, i + 1,
- USB_PORT_FEAT_C_ENABLE);
+ dbg("port %d enable change", i + 1);
+ usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_ENABLE);
}
if (portchange & USB_PORT_STAT_C_SUSPEND)
- printk(KERN_INFO "hub: port %d suspend change\n",
- i + 1);
+ dbg("port %d suspend change", i + 1);
if (portchange & USB_PORT_STAT_C_OVERCURRENT)
- printk(KERN_INFO "hub: port %d over-current change\n",
- i + 1);
+ dbg("port %d over-current change", i + 1);
if (portchange & USB_PORT_STAT_C_RESET) {
- printk(KERN_INFO "hub: port %d reset change\n",
- i + 1);
- usb_clear_port_feature(dev, i + 1,
- USB_PORT_FEAT_C_RESET);
+ dbg("port %d reset change", i + 1);
+ usb_clear_port_feature(dev, i + 1, USB_PORT_FEAT_C_RESET);
}
} /* end for i */
} /* end while (1) */
MOD_DEC_USE_COUNT;
*/
- printk("usb_hub_thread exiting\n");
+ dbg("usb_hub_thread exiting");
khubd_running = 0;
return 0;
}
if (!count)
- printk(KERN_ERR "hub: giving up on killing khubd\n");
+ err("giving up on killing khubd");
}
/*
c = buffer[i];
-#ifdef MOUSEDEV_DEBUG
- printk(KERN_DEBUG "mousedev: received char %#x\n", c);
-#endif
-
if (c == mousedev_genius_seq[list->genseq]) {
if (++list->genseq == MOUSEDEV_GENIUS_LEN) {
list->genseq = 0;
#include <linux/malloc.h>
#include <linux/delay.h>
-#include "usb.h"
-
-// #define SCN_DBG /* Enable to print results of read/write_scanner() calls */
-// #define RD_DATA_DUMP /* Enable to dump data - limited to 24 bytes */
-// #define WR_DATA_DUMP
+#undef DEBUG /* Enable to print results of read/write_scanner() calls */
+#undef RD_DATA_DUMP /* Enable to dump data - limited to 24 bytes */
+#undef WR_DATA_DUMP
-#ifdef SCN_DBG
-#define SCN_DEBUG(X) X
-#else
-#define SCN_DEBUG(X)
-#endif
+#include "usb.h"
#define IBUF_SIZE 32768
#define OBUF_SIZE 4096
}
result = usb_bulk_msg(hps->hpscan_dev,usb_sndbulkpipe(hps->hpscan_dev, hps->oep), obuf, copy_size, &partial, 30*HZ);
- SCN_DEBUG(printk(KERN_DEBUG "write stats: result:%d copy_size:%lu partial:%lu\n", (int)result, copy_size, partial);)
+ dbg("write stats: result:%d copy_size:%lu partial:%lu", (int)result, copy_size, partial);
if (result == USB_ST_TIMEOUT) { /* NAK -- shouldn't happen */
- printk(KERN_WARNING "write_scanner: NAK recieved.\n");
+ warn("write_scanner: NAK recieved.");
ret = -ETIME;
break;
} else if (result < 0) { /* We should not get any I/O errors */
- printk(KERN_WARNING "write_scanner: funky result: %d. Please notify the maintainer.\n", result);
+ warn("write_scanner: funky result: %d. Please notify the maintainer.", result);
ret = -EIO;
break;
}
if (partial) {
unsigned char cnt, cnt_max;
cnt_max = (partial > 24) ? 24 : partial;
- printk(KERN_DEBUG "dump: ");
+ printk(KERN_DEBUG __FILE__ ": dump: ");
for (cnt=0; cnt < cnt_max; cnt++) {
printk("%X ", obuf[cnt]);
}
this_read = (count > IBUF_SIZE) ? IBUF_SIZE : count;
result = usb_bulk_msg(hps->hpscan_dev, usb_rcvbulkpipe(hps->hpscan_dev, hps->iep), ibuf, this_read, &partial, 60*HZ);
- SCN_DEBUG(printk(KERN_DEBUG "read stats: result:%d this_read:%u partial:%lu\n", (int)result, this_read, partial);)
+ dbg("read stats: result:%d this_read:%u partial:%lu", (int)result, this_read, partial);
if (result == USB_ST_TIMEOUT) { /* NAK -- shouldn't happen */
- printk(KERN_WARNING "read_scanner: NAK received\n");
+ warn("read_scanner: NAK received");
ret = -ETIME;
break;
} else if ((result < 0) && (result != USB_ST_DATAUNDERRUN)) {
- printk(KERN_WARNING "read_scanner: funky result: %d. Please notify the maintainer.\n", (int)result);
+ warn("read_scanner: funky result: %d. Please notify the maintainer.", (int)result);
ret = -EIO;
break;
}
if (partial) {
unsigned char cnt, cnt_max;
cnt_max = (partial > 24) ? 24 : partial;
- printk(KERN_DEBUG "dump: ");
+ printk(KERN_DEBUG __FILE__ ": dump: ");
for (cnt=0; cnt < cnt_max; cnt++) {
printk("%X ", ibuf[cnt]);
}
hps->present = 0;
- if (vendor != 0 || product != 0) {
- printk(KERN_INFO "USB Scanner Vendor:Product - %x:%x\n", vendor, product);
- }
+ if (vendor != 0 || product != 0)
+ info("USB Scanner Vendor:Product - %x:%x\n", vendor, product);
/* There doesn't seem to be an imaging class defined in the USB
* Spec. (yet). If there is, HP isn't following it and it doesn't
if (dev->descriptor.bNumConfigurations != 1 ||
dev->config[0].bNumInterfaces != 1) {
- printk(KERN_INFO "probe_scanner: only simple configurations supported\n");
+ dbg("probe_scanner: only simple configurations supported");
return NULL;
}
if (endpoint[0].bmAttributes != USB_ENDPOINT_XFER_BULK
|| endpoint [1].bmAttributes != USB_ENDPOINT_XFER_BULK) {
- printk(KERN_INFO "probe_scanner: invalid bulk endpoints\n");
+ dbg("probe_scanner: invalid bulk endpoints");
return NULL;
}
if (usb_set_configuration(dev, dev->config[0].bConfigurationValue)) {
- printk (KERN_INFO "probe_scanner: failed usb_set_configuration\n");
+ dbg("probe_scanner: failed usb_set_configuration");
hps->hpscan_dev = NULL;
return NULL;
}
}
ident = usb_string(dev, dev->descriptor.iProduct); /* usb_string allocates memory using kmalloc() so kfree() needs to be called afterwards when the pointer is no longer needed. */
- printk(KERN_INFO "USB Scanner (%s) found at address %d\n", ident, dev->devnum);
+ info("USB Scanner (%s) found at address %d", ident, dev->devnum);
kfree(ident);
- SCN_DEBUG(printk(KERN_DEBUG "probe_scanner: using bulk endpoints - In: %x Out: %x\n", hps->iep, hps->oep);)
+ dbg("probe_scanner: using bulk endpoints - In: %x Out: %x", hps->iep, hps->oep);
hps->present = 1;
hps->hpscan_dev = dev;
if (usb_register(&scanner_driver) < 0)
return -1;
- printk(KERN_INFO "USB Scanner support registered.\n");
+ info("USB Scanner support registered.");
return 0;
}
/*
* $Id: uhci-debug.c,v 1.12 1999/12/13 15:24:42 fliegl Exp $
*/
+
#include <linux/version.h>
#include <linux/kernel.h>
#include <asm/io.h>
+#define DEBUG
+
#include "usb.h"
#include "uhci.h"
-#define DEBUG
-#ifdef DEBUG
-#define dbg printk
-#else
-#define dbg nix
-static void nix (const char *format,...)
-{
-}
-#endif
void dump_urb (purb_t purb)
{
- printk ("urb :%p\n", purb);
- printk ("next :%p\n", purb->next);
- printk ("dev :%p\n", purb->dev);
- printk ("pipe :%08X\n", purb->pipe);
- printk ("status :%d\n", purb->status);
- printk ("transfer_flags :%08X\n", purb->transfer_flags);
- printk ("transfer_buffer :%p\n", purb->transfer_buffer);
- printk ("transfer_buffer_length:%d\n", purb->transfer_buffer_length);
- printk ("actual_length :%d\n", purb->actual_length);
- printk ("setup_packet :%p\n", purb->setup_packet);
- printk ("start_frame :%d\n", purb->start_frame);
- printk ("number_of_packets :%d\n", purb->number_of_packets);
- printk ("interval :%d\n", purb->interval);
- printk ("error_count :%d\n", purb->error_count);
- printk ("context :%p\n", purb->context);
- printk ("complete :%p\n", purb->complete);
+ dbg("urb :%p", purb);
+ dbg("next :%p", purb->next);
+ dbg("dev :%p", purb->dev);
+ dbg("pipe :%08X", purb->pipe);
+ dbg("status :%d", purb->status);
+ dbg("transfer_flags :%08X", purb->transfer_flags);
+ dbg("transfer_buffer :%p", purb->transfer_buffer);
+ dbg("transfer_buffer_length:%d", purb->transfer_buffer_length);
+ dbg("actual_length :%d", purb->actual_length);
+ dbg("setup_packet :%p", purb->setup_packet);
+ dbg("start_frame :%d", purb->start_frame);
+ dbg("number_of_packets :%d", purb->number_of_packets);
+ dbg("interval :%d", purb->interval);
+ dbg("error_count :%d", purb->error_count);
+ dbg("context :%p", purb->context);
+ dbg("complete :%p", purb->complete);
}
void beep (long freq)
void uhci_show_qh (puhci_desc_t qh)
{
if (qh->type != QH_TYPE) {
- dbg (KERN_DEBUG MODSTR "qh has not QH_TYPE\n");
+ dbg("qh has not QH_TYPE");
return;
}
- dbg (KERN_DEBUG MODSTR "uhci_show_qh %p (%08lX):\n", qh, virt_to_bus (qh));
+ dbg("uhci_show_qh %p (%08lX):", qh, virt_to_bus (qh));
if (qh->hw.qh.head & UHCI_PTR_TERM)
- dbg (KERN_DEBUG MODSTR "Head Terminate\n");
+ dbg("Head Terminate");
else {
if (qh->hw.qh.head & UHCI_PTR_QH)
- dbg (KERN_DEBUG MODSTR "Head points to QH\n");
+ dbg("Head points to QH");
else
- dbg (KERN_DEBUG MODSTR "Head points to TD\n");
+ dbg("Head points to TD");
- dbg (KERN_DEBUG MODSTR "head: %08X\n", qh->hw.qh.head & ~UHCI_PTR_BITS);
+ dbg("head: %08X", qh->hw.qh.head & ~UHCI_PTR_BITS);
}
if (qh->hw.qh.element & UHCI_PTR_TERM)
- dbg (KERN_DEBUG MODSTR "Element Terminate\n");
+ dbg("Element Terminate");
else {
if (qh->hw.qh.element & UHCI_PTR_QH)
- dbg (KERN_DEBUG MODSTR "Element points to QH\n");
+ dbg("Element points to QH");
else
- dbg (KERN_DEBUG MODSTR "Element points to TD\n");
- dbg (KERN_DEBUG MODSTR "element: %08X\n", qh->hw.qh.element & ~UHCI_PTR_BITS);
+ dbg("Element points to TD");
+ dbg("element: %08X", qh->hw.qh.element & ~UHCI_PTR_BITS);
}
}
void uhci_show_td (puhci_desc_t td)
{
char *spid;
- dbg (KERN_DEBUG MODSTR "uhci_show_td %p (%08lX) ", td, virt_to_bus (td));
switch (td->hw.td.info & 0xff) {
case USB_PID_SETUP:
break;
}
- dbg ("MaxLen=%02x DT%d EndPt=%x Dev=%x, PID=%x(%s) (buf=%08x)\n",
+ dbg("uhci_show_td %p (%08lX) MaxLen=%02x DT%d EndPt=%x Dev=%x, PID=%x(%s) (buf=%08x)",
+ td,
+ virt_to_bus(td),
td->hw.td.info >> 21,
((td->hw.td.info >> 19) & 1),
(td->hw.td.info >> 15) & 15,
spid,
td->hw.td.buffer);
- dbg (KERN_DEBUG MODSTR "Len=%02x e%d %s%s%s%s%s%s%s%s%s%s\n",
+ dbg("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_CRCTIMEO) ? "CRC/Timeo " : "",
(td->hw.td.status & TD_CTRL_BITSTUFF) ? "BitStuff " : ""
);
-#if 1
+
if (td->hw.td.link & UHCI_PTR_TERM)
- dbg (KERN_DEBUG MODSTR "Link Terminate\n");
+ dbg("Link Terminate");
else {
if (td->hw.td.link & UHCI_PTR_QH)
- dbg (KERN_DEBUG MODSTR "%s, link points to QH @ %08x\n",
+ dbg("%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
- dbg (KERN_DEBUG MODSTR "%s, link points to TD @ %08x \n",
+ dbg("%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_td_queue (puhci_desc_t td)
{
- dbg (KERN_DEBUG MODSTR "uhci_show_td_queue %p (%08lX):\n", td, virt_to_bus (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)
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 (KERN_DEBUG MODSTR "td points to itself!\n");
+ dbg("td points to itself!");
break;
}
// schedule();
void uhci_show_queue (puhci_desc_t qh)
{
- dbg (KERN_DEBUG MODSTR "uhci_show_queue %p:\n", qh);
+ dbg("uhci_show_queue %p:", qh);
while (1) {
uhci_show_qh (qh);
if (qh->hw.qh.element & UHCI_PTR_QH)
- dbg (KERN_DEBUG MODSTR "Warning: qh->element points to qh!\n");
+ 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 != bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS))
qh = bus_to_virt (qh->hw.qh.head & ~UHCI_PTR_BITS);
else {
- dbg (KERN_DEBUG MODSTR "qh points to itself!\n");
+ 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\n",
+ dbg(" stat%d = %04x %s%s%s%s%s%s%s%s",
port,
status,
(status & USBPORTSC_SUSP) ? "PortSuspend " : "",
portsc1 = inw (io_addr + 16);
portsc2 = inw (io_addr + 18);
- dbg (" usbcmd = %04x %s%s%s%s%s%s%s%s\n",
+ dbg(" usbcmd = %04x %s%s%s%s%s%s%s%s",
usbcmd,
(usbcmd & USBCMD_MAXP) ? "Maxp64 " : "Maxp32 ",
(usbcmd & USBCMD_CF) ? "CF " : "",
(usbcmd & USBCMD_HCRESET) ? "HCRESET " : "",
(usbcmd & USBCMD_RS) ? "RS " : "");
- dbg (" usbstat = %04x %s%s%s%s%s%s\n",
+ dbg(" usbstat = %04x %s%s%s%s%s%s",
usbstat,
(usbstat & USBSTS_HCH) ? "HCHalted " : "",
(usbstat & USBSTS_HCPE) ? "HostControllerProcessError " : "",
(usbstat & USBSTS_ERROR) ? "USBError " : "",
(usbstat & USBSTS_USBINT) ? "USBINT " : "");
- dbg (" usbint = %04x\n", usbint);
- dbg (" usbfrnum = (%d)%03x\n", (usbfrnum >> 10) & 1,
+ dbg(" usbint = %04x", usbint);
+ dbg(" usbfrnum = (%d)%03x", (usbfrnum >> 10) & 1,
0xfff & (4 * (unsigned int) usbfrnum));
- dbg (" flbaseadd = %08x\n", flbaseadd);
- dbg (" sof = %02x\n", sof);
+ dbg(" flbaseadd = %08x", flbaseadd);
+ dbg(" sof = %02x", sof);
uhci_show_sc (1, portsc1);
uhci_show_sc (2, portsc2);
}
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/system.h>
-//#include <asm/spinlock.h>
+
+#undef DEBUG
#include "usb.h"
#include "uhci.h"
#include "uhci-debug.h"
-//#define DEBUG
-#ifdef DEBUG
-#define dbg(format, args...) printk(format, ## args)
-#else
-#define dbg(format, args...)
-#endif
-
-#define _static static
-
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)
#define __init
#define __exit
static puhci_t devs = NULL;
/*-------------------------------------------------------------------*/
-_static void queue_urb (puhci_t s, struct list_head *p, int do_lock)
+static void queue_urb (puhci_t s, struct list_head *p, int do_lock)
{
unsigned long flags=0;
}
/*-------------------------------------------------------------------*/
-_static void dequeue_urb (puhci_t s, struct list_head *p, int do_lock)
+static void dequeue_urb (puhci_t s, struct list_head *p, int do_lock)
{
unsigned long flags=0;
}
/*-------------------------------------------------------------------*/
-_static int alloc_td (puhci_desc_t * new, int flags)
+static int alloc_td (puhci_desc_t * new, int flags)
{
#ifdef _UHCI_SLAB
*new= kmem_cache_alloc(uhci_desc_kmem, in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL);
}
/*-------------------------------------------------------------------*/
/* insert td at last position in td-list of qh (vertical) */
-_static int insert_td (puhci_t s, puhci_desc_t qh, puhci_desc_t new, int flags)
+static int insert_td (puhci_t s, puhci_desc_t qh, puhci_desc_t new, int flags)
{
uhci_desc_t *prev;
unsigned long xxx;
}
/*-------------------------------------------------------------------*/
/* insert new_td after td (horizontal) */
-_static int insert_td_horizontal (puhci_t s, puhci_desc_t td, puhci_desc_t new, int flags)
+static int insert_td_horizontal (puhci_t s, puhci_desc_t td, puhci_desc_t new, int flags)
{
uhci_desc_t *next;
unsigned long xxx;
return 0;
}
/*-------------------------------------------------------------------*/
-_static int unlink_td (puhci_t s, puhci_desc_t element)
+static int unlink_td (puhci_t s, puhci_desc_t element)
{
uhci_desc_t *next, *prev;
int dir = 0;
return 0;
}
/*-------------------------------------------------------------------*/
-_static int delete_desc (puhci_desc_t element)
+static int delete_desc (puhci_desc_t element)
{
#ifdef _UHCI_SLAB
kmem_cache_free(uhci_desc_kmem, element);
}
/*-------------------------------------------------------------------*/
// Allocates qh element
-_static int alloc_qh (puhci_desc_t * new)
+static int alloc_qh (puhci_desc_t * new)
{
#ifdef _UHCI_SLAB
*new= kmem_cache_alloc(uhci_desc_kmem, in_interrupt ()? SLAB_ATOMIC : SLAB_KERNEL);
INIT_LIST_HEAD (&(*new)->horizontal);
INIT_LIST_HEAD (&(*new)->vertical);
- dbg (KERN_DEBUG MODSTR "Allocated qh @ %p\n", *new);
+ dbg("Allocated qh @ %p", *new);
return 0;
}
/*-------------------------------------------------------------------*/
// inserts new qh before/after the qh at pos
// flags: 0: insert before pos, 1: insert after pos (for low speed transfers)
-_static int insert_qh (puhci_t s, puhci_desc_t pos, puhci_desc_t new, int flags)
+static int insert_qh (puhci_t s, puhci_desc_t pos, puhci_desc_t new, int flags)
{
puhci_desc_t old;
unsigned long xxx;
return 0;
}
/*-------------------------------------------------------------------*/
-_static int unlink_qh (puhci_t s, puhci_desc_t element)
+static int unlink_qh (puhci_t s, puhci_desc_t element)
{
puhci_desc_t next, prev;
unsigned long xxx;
return 0;
}
/*-------------------------------------------------------------------*/
-_static int delete_qh (puhci_t s, puhci_desc_t qh)
+static int delete_qh (puhci_t s, puhci_desc_t qh)
{
puhci_desc_t td;
struct list_head *p;
}
/*-------------------------------------------------------------------*/
// Removes ALL qhs in chain (paranoia!)
-_static void cleanup_skel (puhci_t s)
+static void cleanup_skel (puhci_t s)
{
unsigned int n;
puhci_desc_t td;
- printk (KERN_DEBUG MODSTR "Cleanup_skel\n");
+ dbg("cleanup_skel");
for (n = 0; n < 8; n++) {
td = s->int_chain[n];
/*-------------------------------------------------------------------*/
// allocates framelist and qh-skeletons
// only HW-links provide continous linking, SW-links stay in their domain (ISO/INT)
-_static int init_skel (puhci_t s)
+static int init_skel (puhci_t s)
{
int n, ret;
puhci_desc_t qh, td;
- dbg (KERN_DEBUG MODSTR "init_skel\n");
+ dbg("init_skel");
s->framelist = (__u32 *) get_free_page (GFP_KERNEL);
memset (s->framelist, 0, 4096);
- dbg (KERN_DEBUG MODSTR "allocating iso desc pointer list\n");
+ dbg("allocating iso desc pointer list");
s->iso_td = (puhci_desc_t *) kmalloc (1024 * sizeof (puhci_desc_t), GFP_KERNEL);
if (!s->iso_td)
s->bulk_chain = NULL;
s->chain_end = NULL;
- dbg (KERN_DEBUG MODSTR "allocating iso descs\n");
+ dbg("allocating iso descs");
for (n = 0; n < 1024; n++) {
// allocate skeleton iso/irq-tds
ret = alloc_td (&td, 0);
s->framelist[n] = ((__u32) virt_to_bus (td));
}
- dbg (KERN_DEBUG MODSTR "allocating qh: chain_end\n");
+ dbg("allocating qh: chain_end");
ret = alloc_qh (&qh);
if (ret)
s->chain_end = qh;
- dbg (KERN_DEBUG MODSTR "allocating qh: bulk_chain\n");
+ dbg("allocating qh: bulk_chain");
ret = alloc_qh (&qh);
if (ret)
insert_qh (s, s->chain_end, qh, 0);
s->bulk_chain = qh;
- dbg (KERN_DEBUG MODSTR "allocating qh: control_chain\n");
+ dbg("allocating qh: control_chain");
ret = alloc_qh (&qh);
if (ret)
for (n = 0; n < 8; n++)
s->int_chain[n] = 0;
- dbg (KERN_DEBUG MODSTR "Allocating skeleton INT-TDs\n");
+ dbg("allocating skeleton INT-TDs");
for (n = 0; n < 8; n++) {
puhci_desc_t td;
}
}
- dbg (KERN_DEBUG MODSTR "Linking skeleton INT-TDs\n");
+ dbg("linking skeleton INT-TDs");
for (n = 0; n < 1024; n++) {
// link all iso-tds to the interrupt chains
int m, o;
- //dbg("framelist[%i]=%x\n",n,s->framelist[n]);
+ //dbg("framelist[%i]=%x",n,s->framelist[n]);
for (o = 1, m = 2; m <= 128; o++, m += m) {
// n&(m-1) = n%m
if ((n & (m - 1)) == ((m - 1) / 2)) {
}
//uhci_show_queue(s->control_chain);
- dbg (KERN_DEBUG MODSTR "init_skel exit\n");
+ dbg("init_skel exit");
return 0; // OK
init_skel_cleanup:
}
/*-------------------------------------------------------------------*/
-_static void fill_td (puhci_desc_t td, int status, int info, __u32 buffer)
+static void fill_td (puhci_desc_t td, int status, int info, __u32 buffer)
{
td->hw.td.status = status;
td->hw.td.info = info;
// LOW LEVEL STUFF
// assembles QHs und TDs for control, bulk and iso
/*-------------------------------------------------------------------*/
-_static int uhci_submit_control_urb (purb_t purb)
+static int uhci_submit_control_urb (purb_t purb)
{
puhci_desc_t qh, td;
puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
unsigned long len, bytesrequested;
char *data;
- dbg (KERN_DEBUG MODSTR "uhci_submit_control start\n");
+ dbg("uhci_submit_control start");
alloc_qh (&qh); // alloc qh for this request
if (!qh)
insert_td (s, qh, td, 0); // queue 'setup stage'-td in qh
#if 0
- printk ("SETUP to pipe %x: %x %x %x %x %x %x %x %x\n", purb->pipe,
+ dbg("SETUP to pipe %x: %x %x %x %x %x %x %x %x", purb->pipe,
purb->setup_packet[0], purb->setup_packet[1], purb->setup_packet[2], purb->setup_packet[3],
purb->setup_packet[4], purb->setup_packet[5], purb->setup_packet[6], purb->setup_packet[7]);
//uhci_show_td(td);
insert_qh (s, s->bulk_chain, qh, 0); // insert before bulk chain
//uhci_show_queue(s->control_chain);
- dbg (KERN_DEBUG MODSTR "uhci_submit_control end\n");
+ dbg("uhci_submit_control end");
return 0;
}
/*-------------------------------------------------------------------*/
-_static int uhci_submit_bulk_urb (purb_t purb)
+static int uhci_submit_bulk_urb (purb_t purb)
{
puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
purb_priv_t purb_priv = purb->hcpriv;
/* Build the TDs for the bulk request */
len = purb->transfer_buffer_length;
data = purb->transfer_buffer;
- dbg (KERN_DEBUG MODSTR "uhci_submit_bulk_urb: pipe %x, len %d\n", pipe, len);
+ dbg("uhci_submit_bulk_urb: pipe %x, len %d", pipe, len);
while (len > 0) {
int pktsze = len;
if (!len)
td->hw.td.status |= TD_CTRL_IOC; // last one generates INT
- //dbg("insert td %p, len %i\n",td,pktsze);
+ //dbg("insert td %p, len %i",td,pktsze);
insert_td (s, qh, td, UHCI_PTR_DEPTH);
insert_qh (s, s->chain_end, qh, 0); // insert before end marker
//uhci_show_queue(s->bulk_chain);
- dbg (KERN_DEBUG MODSTR "uhci_submit_bulk_urb: exit\n");
+ dbg("uhci_submit_bulk_urb: exit");
return 0;
}
/*-------------------------------------------------------------------*/
// unlinks an urb by dequeuing its qh, waits some frames and forgets it
// Problem: unlinking in interrupt requires waiting for one frame (udelay)
// to allow the whole structures to be safely removed
-_static int uhci_unlink_urb (purb_t purb)
+static int uhci_unlink_urb (purb_t purb)
{
puhci_t s;
puhci_desc_t qh;
spin_lock_irqsave (&s->unlink_urb_lock, flags); // do not allow interrupts
}
- //dbg("unlink_urb called %p\n",purb);
+ //dbg("unlink_urb called %p",purb);
if (purb->status == USB_ST_URB_PENDING) {
// URB probably still in work
purb_priv = purb->hcpriv;
kfree (purb->hcpriv);
#endif
if (purb->complete) {
- dbg (KERN_DEBUG MODSTR "unlink_urb: calling completion\n");
+ dbg("unlink_urb: calling completion");
purb->complete ((struct urb *) purb);
usb_dec_dev_use (purb->dev);
}
// In case of ASAP iso transfer, search the URB-list for already queued URBs
// for this EP and calculate the earliest start frame for the new
// URB (easy seamless URB continuation!)
-_static int find_iso_limits (purb_t purb, unsigned int *start, unsigned int *end)
+static int find_iso_limits (purb_t purb, unsigned int *start, unsigned int *end)
{
purb_t u, last_urb = NULL;
puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
/*-------------------------------------------------------------------*/
// adjust start_frame according to scheduling constraints (ASAP etc)
-_static void jnx_show_desc (puhci_desc_t d)
+static void jnx_show_desc (puhci_desc_t d)
{
switch (d->type) {
case TD_TYPE:
- printk (KERN_DEBUG MODSTR "td @ 0x%08lx: link 0x%08x status 0x%08x info 0x%08x buffer 0x%08x\n",
+ dbg("td @ 0x%08lx: link 0x%08x status 0x%08x info 0x%08x buffer 0x%08x",
(unsigned long) d, d->hw.td.link, d->hw.td.status, d->hw.td.info, d->hw.td.buffer);
if (!(d->hw.td.link & UHCI_PTR_TERM))
jnx_show_desc ((puhci_desc_t) bus_to_virt (d->hw.td.link & ~UHCI_PTR_BITS));
break;
case QH_TYPE:
- printk (KERN_DEBUG MODSTR "qh @ 0x%08lx: head 0x%08x element 0x%08x\n",
+ dbg("qh @ 0x%08lx: head 0x%08x element 0x%08x",
(unsigned long) d, d->hw.qh.head, d->hw.qh.element);
if (!(d->hw.qh.element & UHCI_PTR_TERM))
jnx_show_desc ((puhci_desc_t) bus_to_virt (d->hw.qh.element & ~UHCI_PTR_BITS));
break;
default:
- printk (KERN_DEBUG MODSTR "desc @ 0x%08lx: invalid type %u\n",
- (unsigned long) d, d->type);
+ dbg("desc @ 0x%08lx: invalid type %u", (unsigned long) d, d->type);
}
}
/*-------------------------------------------------------------------*/
-_static int iso_find_start (purb_t purb)
+static int iso_find_start (purb_t purb)
{
puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
unsigned int now;
purb->start_frame = stop_limit; //seamless linkage
if (((now - purb->start_frame) & 1023) <= (unsigned) purb->number_of_packets) {
- printk (KERN_DEBUG MODSTR "iso_find_start: warning, ASAP gap, should not happen\n");
- printk (KERN_DEBUG MODSTR "iso_find_start: now %u start_frame %u number_of_packets %u pipe 0x%08x\n",
+ dbg("iso_find_start: warning, ASAP gap, should not happen");
+ dbg("iso_find_start: now %u start_frame %u number_of_packets %u pipe 0x%08x",
now, purb->start_frame, purb->number_of_packets, purb->pipe);
{
puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
u = list_entry (p, urb_t, urb_list);
if (purb->dev != u->dev)
continue;
- printk (KERN_DEBUG MODSTR "urb: pipe 0x%08x status %d start_frame %u number_of_packets %u\n",
+ dbg("urb: pipe 0x%08x status %d start_frame %u number_of_packets %u",
u->pipe, u->status, u->start_frame, u->number_of_packets);
if (!usb_pipeisoc (u->pipe))
continue;
else {
purb->start_frame &= 1023;
if (((now - purb->start_frame) & 1023) < (unsigned) purb->number_of_packets) {
- printk (KERN_DEBUG MODSTR "iso_find_start: now between start_frame and end\n");
+ dbg("iso_find_start: now between start_frame and end");
return -EAGAIN;
}
}
return 0;
if (((purb->start_frame - start_limit) & 1023) < queued_size ||
((purb->start_frame + purb->number_of_packets - 1 - start_limit) & 1023) < queued_size) {
- printk (KERN_DEBUG MODSTR "iso_find_start: start_frame %u number_of_packets %u start_limit %u stop_limit %u\n",
+ dbg("iso_find_start: start_frame %u number_of_packets %u start_limit %u stop_limit %u",
purb->start_frame, purb->number_of_packets, start_limit, stop_limit);
return -EAGAIN;
}
// ASAP-flag set implicitely
// if period==0, the the transfer is only done once (usb_scsi need this...)
-_static int uhci_submit_int_urb (purb_t purb)
+static int uhci_submit_int_urb (purb_t purb)
{
puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
purb_priv_t purb_priv = purb->hcpriv;
int info;
unsigned int pipe = purb->pipe;
- //printk("SUBMIT INT\n");
+ //dbg("SUBMIT INT");
if (purb->interval < 0 || purb->interval >= 256)
return -EINVAL;
}
nint--;
}
- dbg(KERN_INFO "Rounded interval to %i, chain %i\n", purb->interval, nint);
+ dbg("Rounded interval to %i, chain %i", purb->interval, nint);
now = UHCI_GET_CURRENT_FRAME (s) & 1023;
purb->start_frame = now; // remember start frame, just in case...
return 0;
}
/*-------------------------------------------------------------------*/
-_static int uhci_submit_iso_urb (purb_t purb)
+static int uhci_submit_iso_urb (purb_t purb)
{
puhci_t s = (puhci_t) purb->dev->bus->hcpriv;
purb_priv_t purb_priv = purb->hcpriv;
// First try to get all TDs
for (n = 0; n < purb->number_of_packets; n++) {
- dbg (KERN_DEBUG MODSTR "n:%d purb->iso_frame_desc[n].length:%d\n", n, purb->iso_frame_desc[n].length);
+ dbg("n:%d purb->iso_frame_desc[n].length:%d", n, purb->iso_frame_desc[n].length);
if (!purb->iso_frame_desc[n].length) {
// allows ISO striping by setting length to zero in iso_descriptor
tdm[n] = 0;
}
kfree (tdm);
- dbg ("ISO-INT# %i, start %i, now %i\n", purb->number_of_packets, purb->start_frame, UHCI_GET_CURRENT_FRAME (s) & 1023);
+ dbg("ISO-INT# %i, start %i, now %i", purb->number_of_packets, purb->start_frame, UHCI_GET_CURRENT_FRAME (s) & 1023);
ret = 0;
err:
}
/*-------------------------------------------------------------------*/
-_static int search_dev_ep (puhci_t s, purb_t purb)
+static int search_dev_ep (puhci_t s, purb_t purb)
{
unsigned long flags;
struct list_head *p = s->urb_list.next;
purb_t tmp;
- dbg (KERN_DEBUG MODSTR "search_dev_ep:\n");
+ dbg("search_dev_ep:");
spin_lock_irqsave (&s->urb_list_lock, flags);
for (; p != &s->urb_list; p = p->next) {
tmp = list_entry (p, urb_t, urb_list);
- dbg (KERN_DEBUG MODSTR "urb: %p\n", tmp);
+ dbg("urb: %p", tmp);
// we can accept this urb if it is not queued at this time
// or if non-iso transfer requests should be scheduled for the same device and pipe
if ((usb_pipetype (purb->pipe) != PIPE_ISOCHRONOUS &&
return 0;
}
/*-------------------------------------------------------------------*/
-_static int uhci_submit_urb (purb_t purb)
+static int uhci_submit_urb (purb_t purb)
{
puhci_t s;
purb_priv_t purb_priv;
return -ENODEV;
s = (puhci_t) purb->dev->bus->hcpriv;
- //printk( MODSTR"submit_urb: %p type %d\n",purb,usb_pipetype(purb->pipe));
+ //dbg("submit_urb: %p type %d",purb,usb_pipetype(purb->pipe));
if (usb_pipedevice (purb->pipe) == s->rh.devnum)
return rh_submit_urb (purb); /* virtual root hub */
purb->hcpriv = purb_priv;
INIT_LIST_HEAD (&purb_priv->desc_list);
purb_priv->short_control_packet=0;
- dbg (KERN_DEBUG MODSTR "submit_urb: scheduling %p\n", purb);
+ dbg("submit_urb: scheduling %p", purb);
switch (usb_pipetype (purb->pipe)) {
case PIPE_ISOCHRONOUS:
ret = -EINVAL;
}
- dbg (KERN_DEBUG MODSTR "submit_urb: scheduled with ret: %d\n", ret);
+ dbg("submit_urb: scheduled with ret: %d", ret);
if (ret != USB_ST_NOERROR) {
usb_dec_dev_use (purb->dev);
purb->status = USB_ST_URB_PENDING;
queue_urb (s, &purb->urb_list,1);
- dbg (KERN_DEBUG MODSTR "submit_urb: exit\n");
+ dbg("submit_urb: exit");
return 0;
}
Virtual Root Hub
-------------------------------------------------------------------*/
-_static __u8 root_hub_dev_des[] =
+static __u8 root_hub_dev_des[] =
{
0x12, /* __u8 bLength; */
0x01, /* __u8 bDescriptorType; Device */
/* Configuration descriptor */
-_static __u8 root_hub_config_des[] =
+static __u8 root_hub_config_des[] =
{
0x09, /* __u8 bLength; */
0x02, /* __u8 bDescriptorType; Configuration */
};
-_static __u8 root_hub_hub_des[] =
+static __u8 root_hub_hub_des[] =
{
0x09, /* __u8 bLength; */
0x29, /* __u8 bDescriptorType; Hub-descriptor */
/*-------------------------------------------------------------------------*/
/* prepare Interrupt pipe transaction data; HUB INTERRUPT ENDPOINT */
-_static int rh_send_irq (purb_t purb)
+static int rh_send_irq (purb_t purb)
{
int len = 1;
purb->status = USB_ST_NOERROR;
if ((data > 0) && (uhci->rh.send != 0)) {
- dbg (KERN_DEBUG MODSTR "Root-Hub INT complete: port1: %x port2: %x data: %x\n",
+ dbg("Root-Hub INT complete: port1: %x port2: %x data: %x",
inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2), data);
purb->complete (purb);
/*-------------------------------------------------------------------------*/
/* Virtual Root Hub INTs are polled by this timer every "intervall" ms */
-_static int rh_init_int_timer (purb_t purb);
+static int rh_init_int_timer (purb_t purb);
-_static void rh_int_timer_do (unsigned long ptr)
+static void rh_int_timer_do (unsigned long ptr)
{
int len;
/*-------------------------------------------------------------------------*/
/* Root Hub INTs are polled by this timer */
-_static int rh_init_int_timer (purb_t purb)
+static int rh_init_int_timer (purb_t purb)
{
puhci_t uhci = purb->dev->bus->hcpriv;
*************************/
-_static int rh_submit_urb (purb_t purb)
+static int rh_submit_urb (purb_t purb)
{
struct usb_device *usb_dev = purb->dev;
puhci_t uhci = usb_dev->bus->hcpriv;
__u16 wLength;
if (usb_pipetype (pipe) == PIPE_INTERRUPT) {
- dbg (KERN_DEBUG MODSTR "Root-Hub submit IRQ: every %d ms\n", purb->interval);
+ dbg("Root-Hub submit IRQ: every %d ms", purb->interval);
uhci->rh.urb = purb;
uhci->rh.send = 1;
uhci->rh.interval = purb->interval;
for (i = 0; i < 8; i++)
uhci->rh.c_p_r[i] = 0;
- dbg(KERN_DEBUG MODSTR "Root-Hub: adr: %2x cmd(%1x): %04x %04x %04x %04x\n",
+ dbg("Root-Hub: adr: %2x cmd(%1x): %04x %04x %04x %04x",
uhci->rh.devnum, 8, bmRType_bReq, wValue, wIndex, wLength);
switch (bmRType_bReq) {
}
- printk (KERN_DEBUG MODSTR "Root-Hub stat port1: %x port2: %x \n",
+ dbg("Root-Hub stat port1: %x port2: %x",
inw (io_addr + USBPORTSC1), inw (io_addr + USBPORTSC2));
purb->actual_length = len;
}
/*-------------------------------------------------------------------------*/
-_static int rh_unlink_urb (purb_t purb)
+static int rh_unlink_urb (purb_t purb)
{
puhci_t uhci = purb->dev->bus->hcpriv;
- dbg (KERN_DEBUG MODSTR "Root-Hub unlink IRQ\n");
+ dbg("Root-Hub unlink IRQ");
uhci->rh.send = 0;
del_timer (&uhci->rh.rh_int_timer);
return 0;
* <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)
+static int uhci_map_status (int status, int dir_out)
{
if (!status)
return USB_ST_NOERROR;
/*
* Only the USB core should call uhci_alloc_dev and uhci_free_dev
*/
-_static int uhci_alloc_dev (struct usb_device *usb_dev)
+static int uhci_alloc_dev (struct usb_device *usb_dev)
{
return 0;
}
-_static int uhci_free_dev (struct usb_device *usb_dev)
+static int uhci_free_dev (struct usb_device *usb_dev)
{
return 0;
}
*
* returns the current frame number for a USB bus/controller.
*/
-_static int uhci_get_current_frame_number (struct usb_device *usb_dev)
+static int uhci_get_current_frame_number (struct usb_device *usb_dev)
{
return UHCI_GET_CURRENT_FRAME ((puhci_t) usb_dev->bus->hcpriv);
}
* when the transfered length fits exactly in maxsze-packets. A bit
* more intelligence is needed to detect this and finish without error.
*/
-_static int process_transfer (puhci_t s, purb_t purb)
+static int process_transfer (puhci_t s, purb_t purb)
{
int ret = USB_ST_NOERROR;
purb_priv_t purb_priv = purb->hcpriv;
int actual_length;
int status = USB_ST_NOERROR;
- dbg (KERN_DEBUG MODSTR "process_transfer: urb contains bulk/control request\n");
+ dbg("process_transfer: urb contains bulk/control request");
/* if the status phase has been retriggered and the
if ( (actual_length < maxlength)) {
if (purb->transfer_flags & USB_DISABLE_SPD) {
ret = USB_ST_SHORT_PACKET; // treat as real error
- printk (KERN_DEBUG MODSTR "process_transfer: SPD!!\n");
+ dbg("process_transfer: SPD!!");
break; // exit after this TD because SP was detected
}
if (uhci_packetid(last_desc->hw.td.info) == USB_PID_OUT) {
uhci_show_td (last_desc);
qh->hw.qh.element = virt_to_bus (last_desc); // re-trigger status stage
- printk("uhci: short packet during control transfer, retrigger status stage @ %p\n",last_desc);
+ info("short packet during control transfer, retrigger status stage @ %p",last_desc);
purb_priv->short_control_packet=1;
return 0;
}
}
data_toggle = uhci_toggle (desc->hw.td.info);
- //printk(KERN_DEBUG MODSTR"process_transfer: len:%d status:%x mapped:%x toggle:%d\n", actual_length, desc->hw.td.status,status, data_toggle);
+ //dbg("process_transfer: len:%d status:%x mapped:%x toggle:%d", actual_length, desc->hw.td.status,status, data_toggle);
}
usb_settoggle (purb->dev, usb_pipeendpoint (purb->pipe), usb_pipeout (purb->pipe), !data_toggle);
purb->status = status;
- dbg(KERN_DEBUG MODSTR"process_transfer: urb %p, wanted len %d, len %d status %x err %d\n",
+ dbg("process_transfer: urb %p, wanted len %d, len %d status %x err %d",
purb,purb->transfer_buffer_length,purb->actual_length, purb->status, purb->error_count);
- //dbg(KERN_DEBUG MODSTR"process_transfer: exit\n");
+ //dbg("process_transfer: exit");
return ret;
}
-_static int process_interrupt (puhci_t s, purb_t purb)
+static int process_interrupt (puhci_t s, purb_t purb)
{
int i, ret = USB_ST_URB_PENDING;
purb_priv_t purb_priv = purb->hcpriv;
int actual_length;
int status = USB_ST_NOERROR;
- //printk(KERN_DEBUG MODSTR"urb contains interrupt request\n");
+ //dbg("urb contains interrupt request");
for (i = 0; p != &purb_priv->desc_list; p = p->next, i++) // Maybe we allow more than one TD later ;-)
{
if (desc->hw.td.status & TD_CTRL_ACTIVE) {
// do not process active TDs
- //printk("TD ACT Status @%p %08x\n",desc,desc->hw.td.status);
+ //dbg("TD ACT Status @%p %08x",desc,desc->hw.td.status);
break;
}
if (purb->complete && status != USB_ST_TIMEOUT) {
// for last td, no user completion is needed
- dbg (KERN_DEBUG MODSTR "process_interrupt: calling completion\n");
+ dbg("process_interrupt: calling completion");
purb->status = status;
purb->complete ((struct urb *) purb);
purb->status = USB_ST_URB_PENDING;
}
-_static int process_iso (puhci_t s, purb_t purb)
+static int process_iso (puhci_t s, purb_t purb)
{
int i;
int ret = USB_ST_NOERROR;
struct list_head *p = purb_priv->desc_list.next;
puhci_desc_t desc = list_entry (purb_priv->desc_list.prev, uhci_desc_t, desc_list);
- dbg ( /*KERN_DEBUG */ MODSTR "urb contains iso request\n");
+ dbg("urb contains iso request");
if (desc->hw.td.status & TD_CTRL_ACTIVE)
return USB_ST_PARTIAL_ERROR; // last TD not finished
//uhci_show_td(desc);
if (desc->hw.td.status & TD_CTRL_ACTIVE) {
// means we have completed the last TD, but not the TDs before
- printk (KERN_DEBUG MODSTR "TD still active (%x)- grrr. paranoia!\n", desc->hw.td.status);
+ dbg("TD still active (%x)- grrr. paranoia!", desc->hw.td.status);
ret = USB_ST_PARTIAL_ERROR;
purb->iso_frame_desc[i].status = ret;
unlink_td (s, desc);
unlink_td (s, desc);
if (purb->number_of_packets <= i) {
- dbg (KERN_DEBUG MODSTR "purb->number_of_packets (%d)<=(%d)\n", purb->number_of_packets, i);
+ dbg("purb->number_of_packets (%d)<=(%d)", purb->number_of_packets, i);
ret = USB_ST_URB_INVALID_ERROR;
goto err;
}
if (purb->iso_frame_desc[i].offset + purb->transfer_buffer != bus_to_virt (desc->hw.td.buffer)) {
// Hm, something really weird is going on
- dbg (KERN_DEBUG MODSTR "Pointer Paranoia: %p!=%p\n", purb->iso_frame_desc[i].offset + purb->transfer_buffer, bus_to_virt (desc->hw.td.buffer));
+ dbg("Pointer Paranoia: %p!=%p", purb->iso_frame_desc[i].offset + purb->transfer_buffer, bus_to_virt (desc->hw.td.buffer));
ret = USB_ST_URB_INVALID_ERROR;
purb->iso_frame_desc[i].status = ret;
goto err;
purb->error_count++;
purb->status = purb->iso_frame_desc[i].status;
}
- dbg (KERN_DEBUG MODSTR "process_iso: len:%d status:%x\n",
+ dbg("process_iso: len:%d status:%x",
purb->iso_frame_desc[i].length, purb->iso_frame_desc[i].status);
delete_desc (desc);
list_del (p);
}
- dbg ( /*KERN_DEBUG */ MODSTR "process_iso: exit %i (%d)\n", i, ret);
+ dbg("process_iso: exit %i (%d)", i, ret);
return ret;
}
-_static int process_urb (puhci_t s, struct list_head *p)
+static int process_urb (puhci_t s, struct list_head *p)
{
int ret = USB_ST_NOERROR;
purb_t purb;
spin_lock(&s->urb_list_lock);
purb=list_entry (p, urb_t, urb_list);
- dbg ( /*KERN_DEBUG */ MODSTR "found queued urb: %p\n", purb);
+ dbg("found queued urb: %p", purb);
switch (usb_pipetype (purb->pipe)) {
case PIPE_CONTROL:
if (purb->status != USB_ST_URB_PENDING) {
int proceed = 0;
- dbg ( /*KERN_DEBUG */ MODSTR "dequeued urb: %p\n", purb);
+ dbg("dequeued urb: %p", purb);
dequeue_urb (s, p, 1);
#ifdef _UHCI_SLAB
// In case you need the current URB status for your completion handler
if (purb->complete && (!proceed || (purb->transfer_flags & USB_URB_EARLY_COMPLETE))) {
- dbg (KERN_DEBUG MODSTR "process_transfer: calling early completion\n");
+ dbg("process_transfer: calling early completion");
purb->complete ((struct urb *) purb);
if (!proceed && is_ring && (purb->status != USB_ST_URB_KILLED))
uhci_submit_urb (purb);
while (tmp != NULL && tmp != purb->next); // submit until we reach NULL or our own pointer or submit fails
if (purb->complete && !(purb->transfer_flags & USB_URB_EARLY_COMPLETE)) {
- dbg ( /*KERN_DEBUG */ MODSTR "process_transfer: calling completion\n");
+ dbg("process_transfer: calling completion");
purb->complete ((struct urb *) purb);
}
}
return ret;
}
-_static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs)
+static void uhci_interrupt (int irq, void *__uhci, struct pt_regs *regs)
{
puhci_t s = __uhci;
unsigned int io_addr = s->io_addr;
* Read the interrupt status, and write it back to clear the
* interrupt cause
*/
- dbg ("interrupt\n");
+ dbg("interrupt");
status = inw (io_addr + USBSTS);
if (!status) /* shared interrupt, not mine */
return;
if (status != 1) {
- printk (KERN_DEBUG MODSTR "interrupt, status %x\n", status);
+ dbg("interrupt, status %x", status);
//uhci_show_status (s);
}
//beep(1000);
#ifdef __alpha
mb (); // ?
#endif
- dbg ("done\n");
+ dbg("done");
}
-_static void reset_hc (puhci_t s)
+static void reset_hc (puhci_t s)
{
unsigned int io_addr = s->io_addr;
wait_ms (10);
}
-_static void start_hc (puhci_t s)
+static void start_hc (puhci_t s)
{
unsigned int io_addr = s->io_addr;
int timeout = 1000;
while (inw (io_addr + USBCMD) & USBCMD_HCRESET) {
if (!--timeout) {
- printk (KERN_ERR MODSTR "USBCMD_HCRESET timed out!\n");
+ err("USBCMD_HCRESET timed out!");
break;
}
}
s->apm_state = 1;
}
-_static void __exit uhci_cleanup_dev(puhci_t s)
+static void __exit uhci_cleanup_dev(puhci_t s)
{
struct usb_device *root_hub = s->bus->root_hub;
if (root_hub)
}
-_static int __init uhci_start_usb (puhci_t s)
+static int __init uhci_start_usb (puhci_t s)
{ /* start it up */
/* connect the virtual root hub */
struct usb_device *usb_dev;
return 0;
}
-_static int __init alloc_uhci (int irq, unsigned int io_addr, unsigned int io_size)
+static int __init alloc_uhci (int irq, unsigned int io_addr, unsigned int io_size)
{
puhci_t s;
struct usb_bus *bus;
unsigned int portstatus;
portstatus = inw (io_addr + 0x10 + (s->maxports * 2));
- printk ("port %i, adr %x status %x\n", s->maxports,
+ dbg("port %i, adr %x status %x", s->maxports,
io_addr + 0x10 + (s->maxports * 2), portstatus);
if (!(portstatus & 0x0080))
break;
}
- dbg (KERN_DEBUG MODSTR "Detected %d ports\n", s->maxports);
+ dbg("Detected %d ports", s->maxports);
/* This is experimental so anything less than 2 or greater than 8 is */
/* something weird and we'll ignore it */
if (s->maxports < 2 || s->maxports > 8) {
- dbg (KERN_DEBUG "Port count misdetected, forcing to 2 ports\n");
+ dbg("Port count misdetected, forcing to 2 ports");
s->maxports = 2;
}
start_hc (s);
if (request_irq (irq, uhci_interrupt, SA_SHIRQ, MODNAME, s)) {
- printk(MODSTR KERN_ERR"request_irq %d failed!\n",irq);
+ err("request_irq %d failed!",irq);
usb_free_bus (bus);
reset_hc (s);
release_region (s->io_addr, s->io_size);
return 0;
}
-_static int __init start_uhci (struct pci_dev *dev)
+static int __init start_uhci (struct pci_dev *dev)
{
int i;
}
#ifdef CONFIG_APM
-_static int handle_apm_event (apm_event_t event)
+static int handle_apm_event (apm_event_t event)
{
static int down = 0;
puhci_t s = devs;
- printk ("handle_apm_event(%d)\n", event);
+ dbg("handle_apm_event(%d)", event);
switch (event) {
case APM_SYS_SUSPEND:
case APM_USER_SUSPEND:
if (down) {
- dbg (KERN_DEBUG MODSTR "received extra suspend event\n");
+ dbg("received extra suspend event");
break;
}
while (s) {
case APM_NORMAL_RESUME:
case APM_CRITICAL_RESUME:
if (!down) {
- dbg (KERN_DEBUG MODSTR "received bogus resume event\n");
+ dbg("received bogus resume event");
break;
}
down = 0;
uhci_desc_kmem = kmem_cache_create(slabname, sizeof(uhci_desc_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
if(!uhci_desc_kmem) {
- printk(KERN_ERR MODSTR"kmem_cache_create for uhci_desc failed (out of memory)\n");
+ err("kmem_cache_create for uhci_desc failed (out of memory)");
return -ENOMEM;
}
urb_priv_kmem = kmem_cache_create(slabname, sizeof(urb_priv_t), 0, SLAB_HWCACHE_ALIGN, NULL, NULL);
if(!urb_priv_kmem) {
- printk(KERN_ERR MODSTR"kmem_cache_create for urb_priv_t failed (out of memory)\n");
+ err("kmem_cache_create for urb_priv_t failed (out of memory)");
return -ENOMEM;
}
#endif
- printk (KERN_INFO MODSTR VERSTR "\n");
+ info(VERSTR);
for (;;) {
dev = pci_find_class (PCI_CLASS_SERIAL_USB << 8, dev);
#endif
if(!dev->irq)
{
- printk(KERN_ERR MODSTR"Found UHCI device with no IRQ assigned. Check BIOS settings!\n");
+ err("Found UHCI device with no IRQ assigned. Check BIOS settings!");
continue;
}
$Id: uhci.h,v 1.30 1999/12/15 17:57:25 fliegl Exp $
*/
#define MODNAME "usb-uhci"
-#define MODSTR MODNAME": "
#define VERSTR "version v0.9 time " __TIME__ " " __DATE__
/* Command register */
*/
#include <linux/version.h>
#include <linux/kernel.h>
+
+#define DEBUG
+
#include "usb.h"
static void usb_show_endpoint(struct usb_endpoint_descriptor *endpoint)
#include <linux/module.h>
#include <linux/spinlock.h>
-#include "usb.h"
-
-/*#define SERIAL_DEBUG 1*/
-
-#ifdef SERIAL_DEBUG
- #define debug_info(format,arg...) printk(KERN_DEBUG "USB Serial: " format "\n" , ##arg)
-#else
- #define debug_info(format,arg...) do {} while (0)
-#endif
-
+#undef DEBUG
+#include "usb.h"
/* Module information */
MODULE_AUTHOR("Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux-usb/");
unsigned char *data = urb->transfer_buffer;
int i;
- debug_info("serial_read_irq");
+ dbg("serial_read_irq");
if (urb->status) {
- debug_info("nonzero read bulk status received: %d", urb->status);
+ dbg("nonzero read bulk status received: %d", urb->status);
return;
}
-#ifdef SERIAL_DEBUG
- if (urb->actual_length) {
- debug_info("%d %s\n", urb->actual_length, data);
- }
-#endif
+ if (urb->actual_length)
+ dbg("%d %s", urb->actual_length, data);
if (urb->actual_length) {
for (i = 0; i < urb->actual_length ; ++i) {
/* Continue trying to always read */
if (usb_submit_urb(urb))
- debug_info("failed resubmitting read urb");
+ dbg("failed resubmitting read urb");
return;
}
struct usb_serial_state *serial = (struct usb_serial_state *) urb->context;
struct tty_struct *tty = serial->tty;
- debug_info("serial_write_irq");
+ dbg("serial_write_irq");
if (urb->status) {
- debug_info("nonzero write bulk status received: %d", urb->status);
+ dbg("nonzero write bulk status received: %d", urb->status);
return;
}
{
struct usb_serial_state *serial;
- debug_info("serial_open");
+ dbg("serial_open");
/* assign a serial object to the tty pointer */
serial = &serial_state_table [MINOR(tty->device)-tty->driver.minor_start];
/* do some sanity checking that we really have a device present */
if (!serial) {
- debug_info("serial == NULL!");
+ dbg("serial == NULL!");
return (-ENODEV);
}
if (!serial->type) {
- debug_info("serial->type == NULL!");
+ dbg("serial->type == NULL!");
return (-ENODEV);
}
static void serial_close(struct tty_struct *tty, struct file * filp)
{
struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- debug_info("serial_close");
+ dbg("serial_close");
/* do some sanity checking that we really have a device present */
if (!serial) {
- debug_info("serial == NULL!");
+ dbg("serial == NULL!");
return;
}
if (!serial->type) {
- debug_info("serial->type == NULL!");
+ dbg("serial->type == NULL!");
return;
}
if (!serial->present) {
- debug_info("no device registered");
+ dbg("no device registered");
return;
}
if (!serial->active) {
- debug_info ("device already open");
+ dbg ("device already open");
return;
}
{
struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- debug_info("serial_write");
+ dbg("serial_write");
/* do some sanity checking that we really have a device present */
if (!serial) {
- debug_info("serial == NULL!");
+ dbg("serial == NULL!");
return (-ENODEV);
}
if (!serial->type) {
- debug_info("serial->type == NULL!");
+ dbg("serial->type == NULL!");
return (-ENODEV);
}
if (!serial->present) {
- debug_info("device not registered");
+ dbg("device not registered");
return (-EINVAL);
}
if (!serial->active) {
- debug_info ("device not opened");
+ dbg ("device not opened");
return (-EINVAL);
}
{
struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data;
- debug_info("serial_put_char");
+ dbg("serial_put_char");
/* do some sanity checking that we really have a device present */
if (!serial) {
- debug_info("serial == NULL!");
+ dbg("serial == NULL!");
return;
}
if (!serial->type) {
- debug_info("serial->type == NULL!");
+ dbg("serial->type == NULL!");
return;
}
if (!serial->present) {
- debug_info("no device registered");
+ dbg("no device registered");
return;
}
if (!serial->active) {
- debug_info ("device not open");
+ dbg ("device not open");
return;
}
{
struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data;
- debug_info("serial_write_room");
+ dbg("serial_write_room");
/* do some sanity checking that we really have a device present */
if (!serial) {
- debug_info("serial == NULL!");
+ dbg("serial == NULL!");
return (-ENODEV);
}
if (!serial->type) {
- debug_info("serial->type == NULL!");
+ dbg("serial->type == NULL!");
return (-ENODEV);
}
if (!serial->present) {
- debug_info("no device registered");
+ dbg("no device registered");
return (-EINVAL);
}
if (!serial->active) {
- debug_info ("device not open");
+ dbg ("device not open");
return (-EINVAL);
}
{
struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data;
- debug_info("serial_chars_in_buffer");
+ dbg("serial_chars_in_buffer");
/* do some sanity checking that we really have a device present */
if (!serial) {
- debug_info("serial == NULL!");
+ dbg("serial == NULL!");
return (-ENODEV);
}
if (!serial->type) {
- debug_info("serial->type == NULL!");
+ dbg("serial->type == NULL!");
return (-ENODEV);
}
if (!serial->present) {
- debug_info("no device registered");
+ dbg("no device registered");
return (-EINVAL);
}
if (!serial->active) {
- debug_info ("device not open");
+ dbg ("device not open");
return (-EINVAL);
}
{
struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- debug_info("serial_throttle");
+ dbg("serial_throttle");
/* do some sanity checking that we really have a device present */
if (!serial) {
- debug_info("serial == NULL!");
+ dbg("serial == NULL!");
return;
}
if (!serial->type) {
- debug_info("serial->type == NULL!");
+ dbg("serial->type == NULL!");
return;
}
if (!serial->present) {
- debug_info("no device registered");
+ dbg("no device registered");
return;
}
if (!serial->active) {
- debug_info ("device not open");
+ dbg ("device not open");
return;
}
{
struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- debug_info("serial_unthrottle");
+ dbg("serial_unthrottle");
/* do some sanity checking that we really have a device present */
if (!serial) {
- debug_info("serial == NULL!");
+ dbg("serial == NULL!");
return;
}
if (!serial->type) {
- debug_info("serial->type == NULL!");
+ dbg("serial->type == NULL!");
return;
}
if (!serial->present) {
- debug_info("no device registered");
+ dbg("no device registered");
return;
}
if (!serial->active) {
- debug_info ("device not open");
+ dbg ("device not open");
return;
}
{
struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- debug_info("etek_serial_open");
+ dbg("etek_serial_open");
if (!serial->present) {
- debug_info("no device registered");
+ dbg("no device registered");
return -EINVAL;
}
if (serial->active) {
- debug_info ("device already open");
+ dbg ("device already open");
return -EINVAL;
}
serial->active = 1;
/*Start reading from the device*/
if (usb_submit_urb(&serial->read_urb))
- debug_info("usb_submit_urb(read bulk) failed");
+ dbg("usb_submit_urb(read bulk) failed");
/* Need to do device specific setup here (control lines, baud rate, etc.) */
/* FIXME!!! */
static void etek_serial_close(struct tty_struct *tty, struct file * filp)
{
struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- debug_info("etek_serial_close");
+ dbg("etek_serial_close");
/* Need to change the control lines here */
/* FIXME */
{
struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- debug_info("whiteheat_serial_open");
+ dbg("whiteheat_serial_open");
if (!serial->present) {
- debug_info("no device registered");
+ dbg("no device registered");
return -EINVAL;
}
if (serial->active) {
- debug_info ("device already open");
+ dbg ("device already open");
return -EINVAL;
}
serial->active = 1;
/*Start reading from the device*/
if (usb_submit_urb(&serial->read_urb))
- debug_info("usb_submit_urb(read bulk) failed");
+ dbg("usb_submit_urb(read bulk) failed");
/* Need to do device specific setup here (control lines, baud rate, etc.) */
/* FIXME!!! */
static void whiteheat_serial_close(struct tty_struct *tty, struct file * filp)
{
struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- debug_info("whiteheat_serial_close");
+ dbg("whiteheat_serial_close");
/* Need to change the control lines here */
/* FIXME */
static void whiteheat_throttle (struct tty_struct * tty)
{
- debug_info("whiteheat_throttle");
+ dbg("whiteheat_throttle");
/* Change the control signals */
/* FIXME!!! */
static void whiteheat_unthrottle (struct tty_struct * tty)
{
- debug_info("whiteheat_unthrottle");
+ dbg("whiteheat_unthrottle");
/* Change the control signals */
/* FIXME!!! */
static int visor_serial_open (struct tty_struct *tty, struct file *filp)
{
struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- debug_info("visor_serial_open");
+ dbg("visor_serial_open");
if (!serial->present) {
- debug_info("no device registered");
+ dbg("no device registered");
return -EINVAL;
}
if (serial->active) {
- debug_info ("device already open");
+ dbg ("device already open");
return -EINVAL;
}
/*Start reading from the device*/
if (usb_submit_urb(&serial->read_urb))
- debug_info("usb_submit_urb(read bulk) failed");
+ dbg("usb_submit_urb(read bulk) failed");
return (0);
}
{
struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- debug_info("USB: visor_serial_close");
+ dbg("USB: visor_serial_close");
/* shutdown our bulk reads and writes */
usb_unlink_urb (&serial->write_urb);
{
/* struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; */
- debug_info("visor_throttle");
+ dbg("visor_throttle");
/* Change the control signals */
/* FIXME!!! */
{
/* struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data; */
- debug_info("visor_unthrottle");
+ dbg("visor_unthrottle");
/* Change the control signals */
/* FIXME!!! */
{
struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- debug_info("generic_serial_open");
+ dbg("generic_serial_open");
if (!serial->present) {
- debug_info("no device registered");
+ dbg("no device registered");
return -EINVAL;
}
if (serial->active) {
- debug_info ("device already open");
+ dbg ("device already open");
return -EINVAL;
}
serial->active = 1;
if (serial->num_bulk_in) {
/*Start reading from the device*/
if (usb_submit_urb(&serial->read_urb))
- debug_info("usb_submit_urb(read bulk) failed");
+ dbg("usb_submit_urb(read bulk) failed");
}
return (0);
static void generic_serial_close(struct tty_struct *tty, struct file * filp)
{
struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- debug_info("generic_serial_close");
+ dbg("generic_serial_close");
/* shutdown any bulk reads that might be going on */
if (serial->num_bulk_out) {
{
struct usb_serial_state *serial = (struct usb_serial_state *) tty->driver_data;
- debug_info("generic_serial_write");
+ dbg("generic_serial_write");
if (count == 0) {
- debug_info("write request of 0 bytes");
+ dbg("write request of 0 bytes");
return (0);
}
/* only do something if we have a bulk out endpoint */
if (serial->num_bulk_out) {
if (serial->write_urb.status == -EINPROGRESS) {
- debug_info ("already writing");
+ dbg ("already writing");
return (0);
}
serial->write_urb.transfer_buffer_length = count;
if (usb_submit_urb(&serial->write_urb))
- debug_info("usb_submit_urb(write bulk) failed");
+ dbg("usb_submit_urb(write bulk) failed");
return (count);
}
{
struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data;
- debug_info("generic_serial_put_char");
+ dbg("generic_serial_put_char");
/* if we have a bulk out endpoint, then shove a character out it */
if (serial->num_bulk_out) {
serial->write_urb.transfer_buffer_length = 1;
if (usb_submit_urb(&serial->write_urb))
- debug_info("usb_submit_urb(write bulk) failed");
+ dbg("usb_submit_urb(write bulk) failed");
}
struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data;
int room;
- debug_info("generic_write_room");
+ dbg("generic_write_room");
if (serial->num_bulk_out) {
if (serial->write_urb.status == -EINPROGRESS)
room = 0;
else
room = serial->bulk_out_size[0];
- debug_info("generic_write_room returns %d", room);
+ dbg("generic_write_room returns %d", room);
return (room);
}
{
struct usb_serial_state *serial = (struct usb_serial_state *)tty->driver_data;
- debug_info("generic_chars_in_buffer");
+ dbg("generic_chars_in_buffer");
if (serial->num_bulk_out) {
if (serial->write_urb.status == -EINPROGRESS) {
device_num = 0;
while (usb_serial_devices[device_num] != NULL) {
type = usb_serial_devices[device_num];
- debug_info ("Looking at %s Vendor id=%.4x Product id=%.4x", type->name, *(type->idVendor), *(type->idProduct));
+ dbg ("Looking at %s Vendor id=%.4x Product id=%.4x", type->name, *(type->idVendor), *(type->idProduct));
/* look at the device descriptor */
if ((dev->descriptor.idVendor == *(type->idVendor)) &&
(dev->descriptor.idProduct == *(type->idProduct))) {
- debug_info("descriptor matches...looking at the endpoints");
+ dbg("descriptor matches...looking at the endpoints");
/* descriptor matches, let's try to find the endpoints needed */
interrupt_pipe = bulk_in_pipe = bulk_out_pipe = HAS_NOT;
if ((endpoint->bEndpointAddress & 0x80) &&
((endpoint->bmAttributes & 3) == 0x02)) {
/* we found a bulk in endpoint */
- debug_info("found bulk in");
+ dbg("found bulk in");
bulk_in_pipe = HAS;
bulk_in_endpoint[num_bulk_in] = endpoint;
++num_bulk_in;
if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
((endpoint->bmAttributes & 3) == 0x02)) {
/* we found a bulk out endpoint */
- debug_info("found bulk out");
+ dbg("found bulk out");
bulk_out_pipe = HAS;
bulk_out_endpoint[num_bulk_out] = endpoint;
++num_bulk_out;
if ((endpoint->bEndpointAddress & 0x80) &&
((endpoint->bmAttributes & 3) == 0x03)) {
/* we found a interrupt in endpoint */
- debug_info("found interrupt in");
+ dbg("found interrupt in");
interrupt_pipe = HAS;
interrupt_in_endpoint[num_interrupt_in] = endpoint;
++num_interrupt_in;
(bulk_in_pipe & type->needs_bulk_in) &&
(bulk_out_pipe & type->needs_bulk_out)) {
/* found all that we need */
- printk (KERN_INFO "USB Serial: %s converter detected.\n", type->name);
+ info("%s converter detected", type->name);
if (0>(serial_num = Get_Free_Serial())) {
- debug_info("Too many devices connected");
+ dbg("Too many devices connected");
return NULL;
}
serial->bulk_in_pipe[i] = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint[i]);
serial->bulk_in_buffer[i] = kmalloc (serial->bulk_in_size[i], GFP_KERNEL);
if (!serial->bulk_in_buffer[i]) {
- printk("USB Serial: Couldn't allocate bulk_in_buffer\n");
+ err("Couldn't allocate bulk_in_buffer");
goto probe_error;
}
}
serial->bulk_out_pipe[i] = usb_rcvbulkpipe (dev, serial->bulk_out_endpoint[i]);
serial->bulk_out_buffer[i] = kmalloc (serial->bulk_out_size[i], GFP_KERNEL);
if (!serial->bulk_out_buffer[i]) {
- printk("USB Serial: Couldn't allocate bulk_out_buffer\n");
+ err("Couldn't allocate bulk_out_buffer");
goto probe_error;
}
}
/* serial->interrupt_in_pipe = usb_rcvbulkpipe (dev, serial->bulk_in_endpoint); */
serial->interrupt_in_buffer[i] = kmalloc (serial->bulk_in_size[i], GFP_KERNEL);
if (!serial->interrupt_in_buffer[i]) {
- printk("USB Serial: Couldn't allocate interrupt_in_buffer\n");
+ err("Couldn't allocate interrupt_in_buffer");
goto probe_error;
}
}
/* set up our interrupt to be the time for the bulk in read */
ret = usb_request_irq (dev, serial->bulk_in_pipe, usb_serial_irq, serial->bulk_in_interval, serial, &serial->irq_handle);
if (ret) {
- printk(KERN_INFO "USB Serial: failed usb_request_irq (0x%x)\n", ret);
+ info("failed usb_request_irq (0x%x)", ret);
goto probe_error;
}
#endif
serial->present = 1;
MOD_INC_USE_COUNT;
- printk(KERN_INFO "USB Serial: %s converter now attached to ttyUSB%d\n", type->name, serial_num);
+ info("%s converter now attached to ttyUSB%d", type->name, serial_num);
return serial;
} else {
- printk(KERN_INFO "USB Serial: descriptors matched, but endpoints did not\n");
+ info("descriptors matched, but endpoints did not");
}
}
if (serial) {
if (!serial->present) {
/* something strange is going on */
- debug_info("disconnect but not present?");
+ dbg("disconnect but not present?");
return;
}
serial->present = 0;
serial->active = 0;
- printk (KERN_INFO "USB Serial: %s converter now disconnected from ttyUSB%d\n", serial->type->name, serial->number);
+ info("%s converter now disconnected from ttyUSB%d", serial->type->name, serial->number);
} else {
- printk (KERN_INFO "USB Serial: device disconnected.\n");
+ info("device disconnected");
}
MOD_DEC_USE_COUNT;
serial_tty_driver.init_termios = tty_std_termios;
serial_tty_driver.init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
if (tty_register_driver (&serial_tty_driver)) {
- printk( "USB Serial: failed to register tty driver\n" );
+ err("failed to register tty driver");
return -EPERM;
}
return -1;
}
- printk(KERN_INFO "USB Serial: support registered.\n");
+ info("support registered");
return 0;
}
* $Id: usb.c,v 1.39 1999/12/27 15:17:47 acher Exp $
*/
-#define USB_DEBUG 1
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/malloc.h>
#include <linux/interrupt.h> /* for in_interrupt() */
-#include "usb.h"
-
-#define MODSTR "usbcore: "
+#define DEBUG
-#ifdef USB_DEBUG
- #define dbg(format, arg...) printk(format, ## arg)
-#else
- #define dbg(format, arg...)
-#endif
+#include "usb.h"
/*
* Prototypes for the device driver probing/loading functions
new_alloc = old_alloc + bustime;
/* what new total allocated bus time would be */
- PRINTD ("usb-bandwidth-alloc: was: %u, new: %u, "
+ dbg("usb-bandwidth-alloc: was: %u, new: %u, "
"bustime = %ld us, Pipe allowed: %s",
old_alloc, new_alloc, bustime,
(new_alloc <= FRAME_TIME_MAX_USECS_ALLOC) ?
if (!iface || !driver)
return;
- printk(KERN_DEBUG "usbcore: %s driver claimed interface %p\n", driver->name, iface);
+ dbg("%s driver claimed interface %p", driver->name, iface);
iface->driver = driver;
iface->private_data = priv;
}
if (rejected)
- printk(KERN_DEBUG "usbcore: unhandled interfaces on device.\n");
+ dbg("unhandled interfaces on device");
+
+#ifdef DEBUG
+ usb_show_device(dev);
+#endif
}
/*
in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
if (!urb)
{
- printk(KERN_ERR MODSTR"alloc_urb: kmalloc failed\n");
+ err("alloc_urb: kmalloc failed");
return 0;
}
memset(urb,0,sizeof(urb_t));
wake_up(awd->wakeup);
#if 0
else
- dbg(KERN_DEBUG MODSTR "(blocking_completion): waitqueue empty!\n");
+ dbg("(blocking_completion): waitqueue empty!");
// even occurs if urb was unlinked by timeout...
#endif
}
if (!status) {
// timeout
- printk(KERN_DEBUG MODSTR"usb_control/bulk_msg: timeout\n");
+ dbg("usb_control/bulk_msg: timeout");
usb_unlink_urb(urb); // remove urb safely
status=-ETIMEDOUT;
}
dr.value = cpu_to_le16p(&value);
dr.index = cpu_to_le16p(&index);
dr.length = cpu_to_le16p(&size);
- //dbg(KERN_DEBUG MODSTR"usb_control_msg\n");
+ //dbg("usb_control_msg");
return usb_internal_control_msg(dev, pipe, &dr, data, size, timeout);
}
int usb_terminate_bulk(struct usb_device *dev, void *first)
{
urb_t *urb=(urb_t*)first;
- dbg(KERN_DEBUG MODSTR"usb_terminate_bulk: urb:%p\n",urb);
+ dbg("usb_terminate_bulk: urb:%p",urb);
if (!urb) // none found? there is nothing to remove!
return -ENODEV;
{
dev->bus->bandwidth_allocated -= bw_alloc;
dev->bus->bandwidth_int_reqs--;
- PRINTD ("bw_alloc reduced to %d for %d requesters",
+ dbg("bw_alloc reduced to %d for %d requesters",
dev->bus->bandwidth_allocated,
dev->bus->bandwidth_int_reqs +
dev->bus->bandwidth_isoc_reqs);
if (!ret) {
dev->bus->bandwidth_allocated += bustime;
dev->bus->bandwidth_int_reqs++;
- PRINTD ("bw_alloc bumped to %d for %d requesters",
+ dbg("bw_alloc bumped to %d for %d requesters",
dev->bus->bandwidth_allocated,
dev->bus->bandwidth_int_reqs +
dev->bus->bandwidth_isoc_reqs);
struct usb_descriptor_header *header;
memcpy(config, buffer, USB_DT_INTERFACE_SIZE);
- usb_show_config_descriptor(config);
le16_to_cpus(&config->wTotalLength);
size = config->wTotalLength;
#include <linux/ioctl.h>
#include <linux/version.h>
-
/* USB constants */
/*
void usb_show_device(struct usb_device *);
void usb_show_string(struct usb_device *dev, char *id, int index);
-#ifdef USB_DEBUG
-#define PRINTD(format, args...) printk(KERN_DEBUG "usb: " format "\n" , ## args);
-#else /* NOT DEBUGGING */
-#define PRINTD(fmt, arg...) do {} while (0)
-#endif /* USB_DEBUG */
-/* A simple way to change one line from DEBUG to NOT DEBUG: */
-#define XPRINTD(fmt, arg...) do {} while (0)
+#ifdef DEBUG
+#define dbg(format, arg...) printk(KERN_DEBUG __FILE__ ": " format "\n", ## arg)
+#else
+#define dbg(format, arg...)
+#endif
+#define err(format, arg...) printk(KERN_ERR __FILE__ ": " format "\n", ## arg)
+#define info(format, arg...) printk(KERN_INFO __FILE__ ": " format "\n", ## arg)
+#define warn(format, arg...) printk(KERN_WARNING __FILE__ ": " format "\n", ## arg)
+
/*
* procfs stuff
if (usb_kbd_keycode[kbd->old[i]])
input_report_key(&kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
else
- printk(KERN_DEBUG "usbkbd.c: Unknown key (scancode %#x) released.\n", kbd->old[i]);
+ info("Unknown key (scancode %#x) released.", kbd->old[i]);
}
if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
if (usb_kbd_keycode[kbd->new[i]])
input_report_key(&kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
else
- printk(KERN_DEBUG "usbkbd.c: Unknown key (scancode %#x) pressed.\n", kbd->new[i]);
+ info("Unknown key (scancode %#x) pressed.", kbd->new[i]);
}
}
-/* $Id: atyfb.c,v 1.134 1999/12/23 21:32:09 geert Exp $
+/* $Id: atyfb.c,v 1.136 2000/01/06 23:53:29 davem Exp $
* linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
*
* Copyright (C) 1997-1998 Geert Uytterhoeven
u16 tmp;
#endif
- while ((pdev = pci_find_device(PCI_VENDOR_ID_ATY, PCI_ANY_ID, pdev))) {
+ while ((pdev = pci_find_device(PCI_VENDOR_ID_ATI, PCI_ANY_ID, pdev))) {
if ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
struct resource *rp;
#ifdef CONFIG_FB_CLGEN
{ "clgen", clgenfb_init, clgenfb_setup },
#endif
+#ifdef CONFIG_FB_SBUS
+ { "sbus", sbusfb_init, sbusfb_setup },
+#endif
#ifdef CONFIG_FB_ATY
{ "atyfb", atyfb_init, atyfb_setup },
#endif
*/
{ "offb", offb_init, offb_setup },
#endif
-#ifdef CONFIG_FB_SBUS
- { "sbus", sbusfb_init, sbusfb_setup },
-#endif
#ifdef CONFIG_FB_ATY128
{ "aty128fb", aty128fb_init, aty128fb_setup },
#endif
u_int16_t sid;
pci_read_config_byte(pdev, PCI_REVISION_ID, &rev);
- svid = dev->subsystem_vendor;
- sid = dev->subsystem_device;
+ svid = pdev->subsystem_vendor;
+ sid = pdev->subsystem_device;
for (b = dev_list; b->vendor; b++) {
if ((b->vendor != pdev->vendor) || (b->device != pdev->device) || (b->rev < rev)) continue;
if (b->svid)
int offset;
unsigned long blocknr;
struct kiobuf * iobuf = NULL;
- unsigned long page;
struct page * map;
struct buffer_head *tmp, *bh[KIO_MAX_SECTORS];
for (pageind = 0; pageind < iobuf->nr_pages; pageind++) {
map = iobuf->maplist[pageind];
- if (map && PageHighMem(map)) {
- err = -EIO;
- goto error;
- }
- page = page_address(map);
while (length > 0) {
blocknr = b[bufind++];
* ...
* 6 - base-level: try to shrink a bit.
*/
-int shrink_dcache_memory(int priority, unsigned int gfp_mask)
+int shrink_dcache_memory(int priority, unsigned int gfp_mask, zone_t * zone)
{
if (gfp_mask & __GFP_IO) {
int count = 0;
#define MAX(a,b) (((a)>(b))?(a):(b))
static long long ext2_file_lseek(struct file *, long long, int);
-#if BITS_PER_LONG < 64
static int ext2_open_file (struct inode *, struct file *);
-#endif
#define EXT2_MAX_SIZE(bits) \
(((EXT2_NDIR_BLOCKS + (1LL << (bits - 2)) + \
return 0;
}
-#if BITS_PER_LONG < 64
/*
* Called when an inode is about to be open.
* We use this to disallow opening RW large files on 32bit systems if
- * the caller didn't specify O_LARGEFILE.
+ * the caller didn't specify O_LARGEFILE. On 64bit systems we force
+ * on this flag in sys_open.
*/
static int ext2_open_file (struct inode * inode, struct file * filp)
{
return -EFBIG;
return 0;
}
-#endif
/*
* We have mostly NULL's here: the current defaults are ok for
NULL, /* poll - default */
ext2_ioctl, /* ioctl */
generic_file_mmap, /* mmap */
-#if BITS_PER_LONG == 64
- NULL, /* no special open is needed */
-#else
ext2_open_file,
-#endif
NULL, /* flush */
ext2_release_file, /* release */
ext2_sync_file, /* fsync */
dispose_list(freeable);
}
-int shrink_icache_memory(int priority, int gfp_mask)
+int shrink_icache_memory(int priority, int gfp_mask, zone_t *zone)
{
if (gfp_mask & __GFP_IO)
{
char * tmp;
int fd, error;
+#if BITS_PER_LONG != 32
+ flags |= O_LARGEFILE;
+#endif
tmp = getname(filename);
fd = PTR_ERR(tmp);
if (!IS_ERR(tmp)) {
static loff_t udf_file_llseek(struct file *, loff_t, int);
static ssize_t udf_file_read_adinicb (struct file *, char *, size_t, loff_t *);
static ssize_t udf_file_write (struct file *, const char *, size_t, loff_t *);
-#if BITS_PER_LONG < 64
static int udf_open_file(struct inode *, struct file *);
-#endif
static int udf_release_file(struct inode *, struct file *);
static struct file_operations udf_file_operations = {
udf_file_llseek, /* llseek */
generic_file_read, /* read */
udf_file_write, /* write */
- NULL, /* readdir */
- NULL, /* poll */
- udf_ioctl, /* ioctl */
+ NULL, /* readdir */
+ NULL, /* poll */
+ udf_ioctl, /* ioctl */
generic_file_mmap, /* mmap */
-#if BITS_PER_LONG == 64
- NULL, /* open */
-#else
udf_open_file, /* open */
-#endif
- NULL, /* flush */
+ NULL, /* flush */
udf_release_file, /* release */
udf_sync_file, /* fsync */
- NULL, /* fasync */
- NULL, /* check_media_change */
- NULL, /* revalidate */
- NULL /* lock */
+ NULL, /* fasync */
+ NULL, /* check_media_change */
+ NULL, /* revalidate */
+ NULL /* lock */
};
struct inode_operations udf_file_inode_operations = {
return 0;
}
-#if BITS_PER_LONG < 64
/*
* udf_open_file
*
*
* DESCRIPTION
* Use this to disallow opening RW large files on 32 bit systems.
+ * On 64 bit systems we force on O_LARGEFILE in sys_open.
*
* HISTORY
*
return -EFBIG;
return 0;
}
-#endif
#define O_DIRECT 040000 /* direct disk access - should check with OSF/1 */
#define O_DIRECTORY 0100000 /* must be a directory */
#define O_NOFOLLOW 0200000 /* don't follow links */
+#define O_LARGEFILE 0400000 /* will be set by the kernel on every open */
#define F_DUPFD 0 /* dup */
#define F_GETFD 1 /* get f_flags */
return csum_partial_copy_generic ( src, dst, len, sum, err_ptr, NULL);
}
-#if 0
-
-/* Not used at the moment. It is difficult to imagine for what purpose
- it can be used :-) Please, do not forget to verify_area before it --ANK
- */
-
-/*
- * This combination is currently not used, but possible:
- */
-
-extern __inline__
-unsigned int csum_partial_copy_to_user ( const char *src, char *dst,
- int len, int sum, int *err_ptr)
-{
- return csum_partial_copy_generic ( src, dst, len, sum, NULL, err_ptr);
-}
-#endif
-
/*
* These are the old (and unsafe) way of doing checksums, a warning message will be
* printed if they are used and an exeption occurs.
-/* $Id: checksum.h,v 1.29 1999/03/21 05:22:07 davem Exp $ */
+/* $Id: checksum.h,v 1.30 2000/01/05 21:27:39 davem Exp $ */
#ifndef __SPARC_CHECKSUM_H
#define __SPARC_CHECKSUM_H
*
* it's best to have buff aligned on a 32-bit boundary
*/
-extern unsigned int csum_partial(unsigned char * buff, int len, unsigned int sum);
+extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
/* the same as csum_partial, but copies from fs:src while it
* checksums
-/* $Id: unistd.h,v 1.59 1999/12/21 14:09:43 jj Exp $ */
+/* $Id: unistd.h,v 1.60 2000/01/05 07:37:50 jj Exp $ */
#ifndef _SPARC_UNISTD_H
#define _SPARC_UNISTD_H
type name(void) \
{ \
long __res; \
-__asm__ __volatile__ ("or %%g0, %0, %%g1\n\t" \
- "t 0x10\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+__asm__ __volatile__ ("t 0x10\n\t" \
"bcc 1f\n\t" \
- "or %%g0, %%o0, %0\n\t" \
+ "mov %%o0, %0\n\t" \
"sub %%g0, %%o0, %0\n\t" \
"1:\n\t" \
: "=r" (__res)\
- : "0" (__NR_##name) \
- : "g1", "o0", "cc"); \
+ : "r" (__g1) \
+ : "o0", "cc"); \
if (__res < -255 || __res >= 0) \
return (type) __res; \
errno = -__res; \
type name(type1 arg1) \
{ \
long __res; \
-__asm__ __volatile__ ("or %%g0, %0, %%g1\n\t" \
- "or %%g0, %1, %%o0\n\t" \
- "t 0x10\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+__asm__ __volatile__ ("t 0x10\n\t" \
"bcc 1f\n\t" \
- "or %%g0, %%o0, %0\n\t" \
+ "mov %%o0, %0\n\t" \
"sub %%g0, %%o0, %0\n\t" \
"1:\n\t" \
- : "=r" (__res), "=r" ((long)(arg1)) \
- : "0" (__NR_##name),"1" ((long)(arg1)) \
- : "g1", "o0", "cc"); \
+ : "=r" (__res), "=&r" (__o0) \
+ : "1" (__o0), "r" (__g1) \
+ : "cc"); \
if (__res < -255 || __res >= 0) \
return (type) __res; \
errno = -__res; \
type name(type1 arg1,type2 arg2) \
{ \
long __res; \
-__asm__ __volatile__ ("or %%g0, %0, %%g1\n\t" \
- "or %%g0, %1, %%o0\n\t" \
- "or %%g0, %2, %%o1\n\t" \
- "t 0x10\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+register long __o1 __asm__ ("o1") = (long)(arg2); \
+__asm__ __volatile__ ("t 0x10\n\t" \
"bcc 1f\n\t" \
- "or %%g0, %%o0, %0\n\t" \
+ "mov %%o0, %0\n\t" \
"sub %%g0, %%o0, %0\n\t" \
"1:\n\t" \
- : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)) \
- : "0" (__NR_##name),"1" ((long)(arg1)),"2" ((long)(arg2)) \
- : "g1", "o0", "o1", "cc"); \
+ : "=r" (__res), "=&r" (__o0) \
+ : "1" (__o0), "r" (__o1), "r" (__g1) \
+ : "cc"); \
if (__res < -255 || __res >= 0) \
return (type) __res; \
errno = -__res; \
type name(type1 arg1,type2 arg2,type3 arg3) \
{ \
long __res; \
-__asm__ __volatile__ ("or %%g0, %0, %%g1\n\t" \
- "or %%g0, %1, %%o0\n\t" \
- "or %%g0, %2, %%o1\n\t" \
- "or %%g0, %3, %%o2\n\t" \
- "t 0x10\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+register long __o1 __asm__ ("o1") = (long)(arg2); \
+register long __o2 __asm__ ("o2") = (long)(arg3); \
+__asm__ __volatile__ ("t 0x10\n\t" \
"bcc 1f\n\t" \
- "or %%g0, %%o0, %0\n\t" \
+ "mov %%o0, %0\n\t" \
"sub %%g0, %%o0, %0\n\t" \
"1:\n\t" \
- : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)), \
- "=r" ((long)(arg3)) \
- : "0" (__NR_##name), "1" ((long)(arg1)), "2" ((long)(arg2)), \
- "3" ((long)(arg3)) \
- : "g1", "o0", "o1", "o2", "cc"); \
+ : "=r" (__res), "=&r" (__o0) \
+ : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \
+ : "cc"); \
if (__res < -255 || __res>=0) \
return (type) __res; \
errno = -__res; \
type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
{ \
long __res; \
-__asm__ __volatile__ ("or %%g0, %0, %%g1\n\t" \
- "or %%g0, %1, %%o0\n\t" \
- "or %%g0, %2, %%o1\n\t" \
- "or %%g0, %3, %%o2\n\t" \
- "or %%g0, %4, %%o3\n\t" \
- "t 0x10\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+register long __o1 __asm__ ("o1") = (long)(arg2); \
+register long __o2 __asm__ ("o2") = (long)(arg3); \
+register long __o3 __asm__ ("o3") = (long)(arg4); \
+__asm__ __volatile__ ("t 0x10\n\t" \
"bcc 1f\n\t" \
- "or %%g0, %%o0, %0\n\t" \
- "sub %%g0,%%o0, %0\n\t" \
+ "mov %%o0, %0\n\t" \
+ "sub %%g0, %%o0, %0\n\t" \
"1:\n\t" \
- : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)), \
- "=r" ((long)(arg3)), "=r" ((long)(arg4)) \
- : "0" (__NR_##name),"1" ((long)(arg1)),"2" ((long)(arg2)), \
- "3" ((long)(arg3)),"4" ((long)(arg4)) \
- : "g1", "o0", "o1", "o2", "o3", "cc"); \
+ : "=r" (__res), "=&r" (__o0) \
+ : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \
+ : "cc"); \
if (__res < -255 || __res>=0) \
return (type) __res; \
errno = -__res; \
type5,arg5) \
type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
{ \
- long __res; \
-\
-__asm__ __volatile__ ("or %%g0, %1, %%o0\n\t" \
- "or %%g0, %2, %%o1\n\t" \
- "or %%g0, %3, %%o2\n\t" \
- "or %%g0, %4, %%o3\n\t" \
- "or %%g0, %5, %%o4\n\t" \
- "or %%g0, %6, %%g1\n\t" \
- "t 0x10\n\t" \
+long __res; \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+register long __o1 __asm__ ("o1") = (long)(arg2); \
+register long __o2 __asm__ ("o2") = (long)(arg3); \
+register long __o3 __asm__ ("o3") = (long)(arg4); \
+register long __o4 __asm__ ("o4") = (long)(arg5); \
+__asm__ __volatile__ ("t 0x10\n\t" \
"bcc 1f\n\t" \
- "or %%g0, %%o0, %0\n\t" \
+ "mov %%o0, %0\n\t" \
"sub %%g0, %%o0, %0\n\t" \
"1:\n\t" \
- : "=r" (__res) \
- : "r" ((long)(arg1)),"r" ((long)(arg2)), \
- "r" ((long)(arg3)),"r" ((long)(arg4)),"r" ((long)(arg5)), \
- "i" (__NR_##name) \
- : "g1", "o0", "o1", "o2", "o3", "o4", "cc"); \
+ : "=r" (__res), "=&r" (__o0) \
+ : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__g1) \
+ : "cc"); \
if (__res < -255 || __res>=0) \
return (type) __res; \
errno = -__res; \
-/* $Id: checksum.h,v 1.13 1999/07/30 09:31:13 davem Exp $ */
+/* $Id: checksum.h,v 1.14 2000/01/05 21:27:42 davem Exp $ */
#ifndef __SPARC64_CHECKSUM_H
#define __SPARC64_CHECKSUM_H
*
* it's best to have buff aligned on a 32-bit boundary
*/
-extern unsigned int csum_partial(unsigned char * buff, int len, unsigned int sum);
+extern unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
/* the same as csum_partial, but copies from user space while it
* checksums
}
#if 0
-/* Not implemented, but nobody uses it yet... */
+/* XXX should implement this now... -DaveM */
extern __inline__ unsigned int
csum_partial_copy_to_user(const char *src, char *dst, int len,
unsigned int sum, int *err)
-/* $Id: fcntl.h,v 1.5 1998/10/26 20:03:15 davem Exp $ */
+/* $Id: fcntl.h,v 1.7 2000/01/04 23:54:58 davem Exp $ */
#ifndef _SPARC64_FCNTL_H
#define _SPARC64_FCNTL_H
#define O_NOCTTY 0x8000 /* not fcntl */
#define O_DIRECTORY 0x10000 /* must be a directory */
#define O_NOFOLLOW 0x20000 /* don't follow links */
+#define O_LARGEFILE 0x40000
#define F_DUPFD 0 /* dup */
#define F_GETFD 1 /* get f_flags */
-/* $Id: unistd.h,v 1.36 1999/12/21 14:09:51 jj Exp $ */
+/* $Id: unistd.h,v 1.37 2000/01/05 07:37:55 jj Exp $ */
#ifndef _SPARC64_UNISTD_H
#define _SPARC64_UNISTD_H
type name(void) \
{ \
long __res; \
-__asm__ __volatile__ ("mov %0, %%g1\n\t" \
- "t 0x6d\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+__asm__ __volatile__ ("t 0x6d\n\t" \
"sub %%g0, %%o0, %0\n\t" \
"movcc %%xcc, %%o0, %0\n\t" \
: "=r" (__res)\
- : "0" (__NR_##name) \
- : "g1", "o0", "cc"); \
+ : "r" (__g1) \
+ : "o0", "cc"); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
type name(type1 arg1) \
{ \
long __res; \
-__asm__ __volatile__ ("mov %0, %%g1\n\t" \
- "mov %1, %%o0\n\t" \
- "t 0x6d\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+__asm__ __volatile__ ("t 0x6d\n\t" \
"sub %%g0, %%o0, %0\n\t" \
"movcc %%xcc, %%o0, %0\n\t" \
- : "=r" (__res), "=r" ((long)(arg1)) \
- : "0" (__NR_##name),"1" ((long)(arg1)) \
- : "g1", "o0", "cc"); \
+ : "=r" (__res), "=&r" (__o0) \
+ : "1" (__o0), "r" (__g1) \
+ : "cc"); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
type name(type1 arg1,type2 arg2) \
{ \
long __res; \
-__asm__ __volatile__ ("mov %0, %%g1\n\t" \
- "mov %1, %%o0\n\t" \
- "mov %2, %%o1\n\t" \
- "t 0x6d\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+register long __o1 __asm__ ("o1") = (long)(arg2); \
+__asm__ __volatile__ ("t 0x6d\n\t" \
"sub %%g0, %%o0, %0\n\t" \
"movcc %%xcc, %%o0, %0\n\t" \
- : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)) \
- : "0" (__NR_##name),"1" ((long)(arg1)),"2" ((long)(arg2)) \
- : "g1", "o0", "o1", "cc"); \
+ : "=r" (__res), "=&r" (__o0) \
+ : "1" (__o0), "r" (__o1), "r" (__g1) \
+ : "cc"); \
if (__res >= 0) \
return (type) __res; \
errno = -__res; \
type name(type1 arg1,type2 arg2,type3 arg3) \
{ \
long __res; \
-__asm__ __volatile__ ("mov %0, %%g1\n\t" \
- "mov %1, %%o0\n\t" \
- "mov %2, %%o1\n\t" \
- "mov %3, %%o2\n\t" \
- "t 0x6d\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+register long __o1 __asm__ ("o1") = (long)(arg2); \
+register long __o2 __asm__ ("o2") = (long)(arg3); \
+__asm__ __volatile__ ("t 0x6d\n\t" \
"sub %%g0, %%o0, %0\n\t" \
"movcc %%xcc, %%o0, %0\n\t" \
- : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)), \
- "=r" ((long)(arg3)) \
- : "0" (__NR_##name), "1" ((long)(arg1)), "2" ((long)(arg2)), \
- "3" ((long)(arg3)) \
- : "g1", "o0", "o1", "o2", "cc"); \
+ : "=r" (__res), "=&r" (__o0) \
+ : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1) \
+ : "cc"); \
if (__res>=0) \
return (type) __res; \
errno = -__res; \
type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
{ \
long __res; \
-__asm__ __volatile__ ("mov %0, %%g1\n\t" \
- "mov %1, %%o0\n\t" \
- "mov %2, %%o1\n\t" \
- "mov %3, %%o2\n\t" \
- "mov %4, %%o3\n\t" \
- "t 0x6d\n\t" \
- "sub %%g0,%%o0, %0\n\t" \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+register long __o1 __asm__ ("o1") = (long)(arg2); \
+register long __o2 __asm__ ("o2") = (long)(arg3); \
+register long __o3 __asm__ ("o3") = (long)(arg4); \
+__asm__ __volatile__ ("t 0x6d\n\t" \
+ "sub %%g0, %%o0, %0\n\t" \
"movcc %%xcc, %%o0, %0\n\t" \
- : "=r" (__res), "=r" ((long)(arg1)), "=r" ((long)(arg2)), \
- "=r" ((long)(arg3)), "=r" ((long)(arg4)) \
- : "0" (__NR_##name),"1" ((long)(arg1)),"2" ((long)(arg2)), \
- "3" ((long)(arg3)),"4" ((long)(arg4)) \
- : "g1", "o0", "o1", "o2", "o3", "cc"); \
+ : "=r" (__res), "=&r" (__o0) \
+ : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__g1) \
+ : "cc"); \
if (__res>=0) \
return (type) __res; \
errno = -__res; \
type5,arg5) \
type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
{ \
- long __res; \
-\
-__asm__ __volatile__ ("mov %1, %%o0\n\t" \
- "mov %2, %%o1\n\t" \
- "mov %3, %%o2\n\t" \
- "mov %4, %%o3\n\t" \
- "mov %5, %%o4\n\t" \
- "mov %6, %%g1\n\t" \
- "t 0x6d\n\t" \
+long __res; \
+register long __g1 __asm__ ("g1") = __NR_##name; \
+register long __o0 __asm__ ("o0") = (long)(arg1); \
+register long __o1 __asm__ ("o1") = (long)(arg2); \
+register long __o2 __asm__ ("o2") = (long)(arg3); \
+register long __o3 __asm__ ("o3") = (long)(arg4); \
+register long __o4 __asm__ ("o4") = (long)(arg5); \
+__asm__ __volatile__ ("t 0x6d\n\t" \
"sub %%g0, %%o0, %0\n\t" \
"movcc %%xcc, %%o0, %0\n\t" \
- : "=r" (__res) \
- : "r" ((long)(arg1)),"r" ((long)(arg2)), \
- "r" ((long)(arg3)),"r" ((long)(arg4)),"r" ((long)(arg5)), \
- "i" (__NR_##name) \
- : "g1", "o0", "o1", "o2", "o3", "o4", "cc"); \
+ : "=r" (__res), "=&r" (__o0) \
+ : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__o3), "r" (__o4), "r" (__g1) \
+ : "cc"); \
if (__res>=0) \
return (type) __res; \
errno = -__res; \
#elif (MAJOR_NR == COMPAQ_SMART2_MAJOR)
-#define DEVICE_NAME "ida"
-#define DEVICE_INTR do_ida
-#define TIMEOUT_VALUE (25*HZ)
-#define DEVICE_REQUEST do_ida_request0
-#define DEVICE_NR(device) (MINOR(device) >> 4)
-#define DEVICE_ON(device)
-#define DEVICE_OFF(device)
-
-#elif (MAJOR_NR == COMPAQ_SMART2_MAJOR)
-
#define DEVICE_NAME "ida"
#define TIMEOUT_VALUE (25*HZ)
#define DEVICE_REQUEST do_ida_request0
extern int d_invalidate(struct dentry *);
#define shrink_dcache() prune_dcache(0)
-
+struct zone_struct;
/* dcache memory management */
-extern int shrink_dcache_memory(int, unsigned int);
+extern int shrink_dcache_memory(int, unsigned int, struct zone_struct *);
extern void prune_dcache(int);
/* icache memory management (defined in linux/fs/inode.c) */
-extern int shrink_icache_memory(int, int);
+extern int shrink_icache_memory(int, int, struct zone_struct *);
extern void prune_icache(int);
/* only used at mount-time */
#ifndef _LINUX_ERRQUEUE_H
#define _LINUX_ERRQUEUE_H 1
-#include <linux/config.h>
-
struct sock_extended_err
{
__u32 ee_errno;
#define SO_EE_OFFENDER(ee) ((struct sockaddr*)((ee)+1))
#ifdef __KERNEL__
+
+#include <linux/config.h>
+
#define SKB_EXT_ERR(skb) ((struct sock_exterr_skb *) ((skb)->cb))
struct sock_exterr_skb
#define IFF_MULTICAST 0x1000 /* Supports multicast */
-#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ALLMULTI)
+#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_MASTER|IFF_SLAVE|IFF_RUNNING)
#define IFF_PORTSEL 0x2000 /* can set media type */
#define IFF_AUTOMEDIA 0x4000 /* auto media select active */
#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/
-#ifdef __KERNEL__
-/*
- * The ifaddr structure contains information about one address
- * of an interface. They are maintained by the different address
- * families, are allocated and attached when an address is set,
- * and are linked together so all addresses for an interface can
- * be located.
- */
-
-struct ifaddr
-{
- struct sockaddr ifa_addr; /* address of interface */
- union {
- struct sockaddr ifu_broadaddr;
- struct sockaddr ifu_dstaddr;
- } ifa_ifu;
- struct iface *ifa_ifp; /* back-pointer to interface */
- struct ifaddr *ifa_next; /* next address for interface */
-};
-
-#define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */
-#define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of link */
-
-#endif /* __KERNEL__ */
-
/*
* Device mapping structure. I'd just gone off and designed a
* beautiful scheme using only loadable modules with arguments
#define IPOPT_TS_TSANDADDR 1 /* timestamps and addresses */
#define IPOPT_TS_PRESPEC 3 /* specified modules only */
+#ifdef __KERNEL__
+
struct ip_options {
__u32 faddr; /* Saved first hop address */
unsigned char optlen;
unsigned char __data[0];
};
-#ifdef __KERNEL__
#define optlength(opt) (sizeof(struct ip_options) + opt->optlen)
#endif
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Mon Mar 8 14:06:12 1999
- * Modified at: Tue Dec 21 09:00:59 1999
+ * Modified at: Sat Dec 25 16:06:42 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
* provide warranty for any of this software. This material is
* provided "AS-IS" and at no charge.
*
- * You probably need to include <sys/types.h> before this one if your
- * including this file from user-space
- *
********************************************************************/
#ifndef KERNEL_IRDA_H
#define LSAP_ANY 0xff
struct sockaddr_irda {
- sa_family_t sir_family; /* AF_IRDA */
- u_int8_t sir_lsap_sel; /* LSAP selector */
- u_int32_t sir_addr; /* Device address */
- char sir_name[25]; /* Usually <service>:IrDA:TinyTP */
+ sa_family_t sir_family; /* AF_IRDA */
+ __u8 sir_lsap_sel; /* LSAP selector */
+ __u32 sir_addr; /* Device address */
+ char sir_name[25]; /* Usually <service>:IrDA:TinyTP */
};
struct irda_device_info {
- u_int32_t saddr; /* Address of local interface */
- u_int32_t daddr; /* Address of remote device */
- char info[22]; /* Description */
- u_int8_t charset; /* Charset used for description */
- u_int8_t hints[2]; /* Hint bits */
+ __u32 saddr; /* Address of local interface */
+ __u32 daddr; /* Address of remote device */
+ char info[22]; /* Description */
+ __u8 charset; /* Charset used for description */
+ __u8 hints[2]; /* Hint bits */
};
struct irda_device_list {
- u_int32_t len;
+ __u32 len;
struct irda_device_info dev[1];
};
unsigned int irda_attrib_int;
struct {
unsigned short len;
- u_char OctetSeq[IAS_MAX_OCTET_STRING];
+ __u8 octet_seq[IAS_MAX_OCTET_STRING];
} irda_attrib_octet_seq;
struct {
- unsigned char len;
- unsigned char charset;
- unsigned char string[IAS_MAX_STRING];
+ __u8 len;
+ __u8 charset;
+ __u8 string[IAS_MAX_STRING];
} irda_attrib_string;
} attribute;
};
/* For setting RTS and DTR lines of a dongle */
struct if_irda_line {
- unsigned char dtr;
- unsigned char rts;
+ __u8 dtr;
+ __u8 rts;
};
/* IrDA interface configuration (data part must not exceed 16 bytes) */
struct isapnp_mem32 *next; /* next 32-bit memory resource */
};
+struct isapnp_fixup {
+ unsigned short vendor; /* matching vendor */
+ unsigned short device; /* matching device */
+ void (*quirk_function)(struct pci_dev *dev); /* fixup function */
+};
+
+
#define ISAPNP_RES_PRIORITY_PREFERRED 0
#define ISAPNP_RES_PRIORITY_ACCEPTABLE 1
#define ISAPNP_RES_PRIORITY_FUNCTIONAL 2
void isapnp_device(unsigned char device);
void isapnp_activate(unsigned char device);
void isapnp_deactivate(unsigned char device);
+void isapnp_fixup_device(struct pci_dev *dev);
+void *isapnp_alloc(long size);
/* manager */
struct pci_bus *isapnp_find_card(unsigned short vendor,
unsigned short device,
#define ClearPageError(page) clear_bit(PG_error, &(page)->flags)
#define PageReferenced(page) test_bit(PG_referenced, &(page)->flags)
#define PageDecrAfter(page) test_bit(PG_decr_after, &(page)->flags)
-#define PageDMA(page) (contig_page_data.node_zones + ZONE_DMA == (page)->zone)
#define PageSlab(page) test_bit(PG_slab, &(page)->flags)
#define PageSwapCache(page) test_bit(PG_swap_cache, &(page)->flags)
#define PageReserved(page) test_bit(PG_reserved, &(page)->flags)
extern int do_munmap(unsigned long, size_t);
extern unsigned long do_brk(unsigned long, unsigned long);
+struct zone_t;
/* filemap.c */
extern void remove_inode_page(struct page *);
extern unsigned long page_unuse(struct page *);
-extern int shrink_mmap(int, int);
+extern int shrink_mmap(int, int, zone_t *);
extern void truncate_inode_pages(struct inode *, loff_t);
/* generic vm_area_ops exported for stackable file systems */
unsigned int * map;
} free_area_t;
+struct pglist_data;
+
typedef struct zone_struct {
/*
* Commonly accessed fields:
unsigned long free_pages;
int low_on_memory;
unsigned long pages_low, pages_high;
+ struct pglist_data *zone_pgdat;
/*
* free areas of different sizes
extern int numnodes;
+#define memclass(pgzone, tzone) (((pgzone)->zone_pgdat == (tzone)->zone_pgdat) \
+ && (((pgzone) - (pgzone)->zone_pgdat->node_zones) <= \
+ ((tzone) - (pgzone)->zone_pgdat->node_zones)))
+
#ifndef CONFIG_DISCONTIGMEM
extern pg_data_t contig_page_data;
#ifndef _LINUX_NETDEVICE_H
#define _LINUX_NETDEVICE_H
-#include <linux/config.h>
#include <linux/if.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <asm/atomic.h>
#ifdef __KERNEL__
+#include <linux/config.h>
#ifdef CONFIG_NET_PROFILE
#include <net/profile.h>
#endif
#ifndef __LINUX_RTNETLINK_H
#define __LINUX_RTNETLINK_H
-#include <linux/config.h>
#include <linux/netlink.h>
#define RTNL_DEBUG 1
#ifdef __KERNEL__
+#include <linux/config.h>
+
extern __inline__ int rtattr_strcmp(struct rtattr *rta, char *str)
{
int len = strlen(str) + 1;
signed long timeout));
extern void FASTCALL(wake_up_process(struct task_struct * tsk));
-#define wake_up(x) __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
-#define wake_up_sync(x) __wake_up_sync((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
-#define wake_up_interruptible(x) __wake_up((x),TASK_INTERRUPTIBLE)
-#define wake_up_interruptible_sync(x) __wake_up_sync((x),TASK_INTERRUPTIBLE)
+#define wake_up(x) __wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE | TASK_EXCLUSIVE)
+#define wake_up_all(x) __wake_up_all((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE)
+#define wake_up_sync(x) __wake_up_sync((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE | TASK_EXCLUSIVE)
+#define wake_up_interruptible(x) __wake_up((x),TASK_INTERRUPTIBLE | TASK_EXCLUSIVE)
+#define wake_up_interruptible_all(x) __wake_up_all((x),TASK_INTERRUPTIBLE)
+#define wake_up_interruptible_sync(x) __wake_up_sync((x),TASK_INTERRUPTIBLE | TASK_EXCLUSIVE)
extern int in_group_p(gid_t);
extern int in_egroup_p(gid_t);
__ptr = (struct cmsghdr*)(((unsigned char *) __cmsg) + CMSG_ALIGN(__cmsg->cmsg_len));
if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
- return NULL;
+ return (struct cmsghdr *)0;
return __ptr;
}
/* IPX options */
#define IPX_TYPE 1
-/* TCP options - this way around because someone left a set in the c library includes */
-#define TCP_NODELAY 1
-#define TCP_MAXSEG 2
-#define TCP_CORK 3 /* Linux specific (for use with sendfile) */
-#define TCP_KEEPIDLE 4
-#define TCP_KEEPINTVL 5
-#define TCP_KEEPCNT 6
-#define TCP_SYNCNT 7
-
#ifdef __KERNEL__
extern int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len);
extern int memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov,
struct vm_area_struct;
struct sysinfo;
+struct zone_t;
/* linux/ipc/shm.c */
-extern int shm_swap (int, int);
+extern int shm_swap (int, int, zone_t *);
/* linux/mm/swap.c */
extern void swap_setup (void);
/* linux/mm/vmscan.c */
-extern int try_to_free_pages(unsigned int gfp_mask);
+extern int try_to_free_pages(unsigned int gfp_mask, zone_t *zone);
/* linux/mm/page_io.c */
extern void rw_swap_page(int, struct page *, int);
psh:1,
ack:1,
urg:1,
- res2:2;
+ ece:1,
+ cwr:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
__u16 doff:4,
res1:4,
- res2:2,
+ cwr:1,
+ ece:1,
urg:1,
ack:1,
psh:1,
#define tcp_flag_word(tp) ( ((union tcp_word_hdr *)(tp))->words [3])
enum {
+ TCP_FLAG_CWR = __constant_htonl(0x00800000),
+ TCP_FLAG_ECE = __constant_htonl(0x00400000),
TCP_FLAG_URG = __constant_htonl(0x00200000),
TCP_FLAG_ACK = __constant_htonl(0x00100000),
TCP_FLAG_PSH = __constant_htonl(0x00080000),
TCP_DATA_OFFSET = __constant_htonl(0xF0000000)
};
+/* TCP socket options */
+#define TCP_NODELAY 1 /* Turn off Nagle's algorithm. */
+#define TCP_MAXSEG 2 /* Limit MSS */
+#define TCP_CORK 3 /* Never send partially complete segments */
+#define TCP_KEEPIDLE 4 /* Start keeplives after this period */
+#define TCP_KEEPINTVL 5 /* Interval between keepalives */
+#define TCP_KEEPCNT 6 /* Number of keepalives before death */
+#define TCP_SYNCNT 7 /* Number of SYN retransmits */
+#define TCP_LINGER2 8 /* Life time of orphaned FIN-WAIT-2 state */
+#define TCP_DEFER_ACCEPT 9 /* Wake up listener only when data arrive */
+
#endif /* _LINUX_TCP_H */
}
#endif
+#ifndef HAVE_CSUM_COPY_USER
+static __inline__ unsigned int csum_and_copy_to_user
+(const char *src, char *dst, int len, unsigned int sum, int *err_ptr)
+{
+ sum = csum_partial(src, len, sum);
+
+ if (access_ok(VERIFY_WRITE, dst, len)) {
+ if (copy_to_user(dst, src, len) == 0)
+ return sum;
+ }
+ if (len)
+ *err_ptr = -EFAULT;
+
+ return -1; /* invalid checksum */
+}
+#endif
+
+
#endif
* Status: Stable
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Dec 9 21:13:12 1997
- * Modified at: Tue Dec 14 19:01:26 1999
+ * Modified at: Sat Dec 25 18:58:49 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
#define IAS_ATTRIB_MAGIC 0x45232
#define IRDA_TASK_MAGIC 0x38423
-#define IAS_DEVICE_ID 0x5342
+#define IAS_DEVICE_ID 0x0000 /* Defined by IrDA, IrLMP section 4.1 (page 68) */
#define IAS_PNP_ID 0xd342
#define IAS_OBEX_ID 0x34323
#define IAS_IRLAN_ID 0x34234
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Thu Aug 21 00:02:07 1997
- * Modified at: Tue Dec 14 21:55:18 1999
+ * Modified at: Sat Dec 25 16:42:09 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1997-1999 Dag Brattli <dagb@cs.uit.no>,
__u32 saddr, __u32 daddr,
char *name, char *attr);
void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb);
-
+void iriap_connect_request(struct iriap_cb *self);
void iriap_send_ack( struct iriap_cb *self);
void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb);
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Aug 19 10:27:26 1997
- * Modified at: Tue Dec 21 11:10:12 1999
+ * Modified at: Sat Dec 25 21:07:26 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1997-1999 Dag Brattli <dagb@cs.uit.no>,
void irlap_send_discovery_xid_frame(struct irlap_cb *, int S, __u8 s,
__u8 command, discovery_t *discovery);
void irlap_send_snrm_frame(struct irlap_cb *, struct qos_info *);
-void irlap_send_test_frame(struct irlap_cb *self, __u32 daddr,
+void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr,
struct sk_buff *cmd);
void irlap_send_ua_response_frame(struct irlap_cb *, struct qos_info *);
void irlap_send_dm_frame(struct irlap_cb *self);
#ifndef IRMLP_FRAME_H
#define IRMLP_FRAME_H
-#include <linux/config.h>
#include <linux/skbuff.h>
#include <net/irda/discovery.h>
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 3 13:49:59 1997
- * Modified at: Sat Dec 11 14:34:18 1999
+ * Modified at: Mon Jan 3 10:23:34 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
- * Copyright (c) 1997, 1998-1999 Dag Brattli <dagb@cs.uit.no>
+ * Copyright (c) 1997, 1998-2000 Dag Brattli <dagb@cs.uit.no>
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
__u32 flags; /* Interface flags */
__u32 new_speed;
int mode;
+ int index; /* Instance index */
spinlock_t lock; /* For serializing operations */
--- /dev/null
+/*********************************************************************
+ *
+ * Filename: nsc_fir.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 by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>
+ * Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
+ * Copyright (c) 1998 Actisys Corp., www.actisys.com
+ * 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 Dag Brattli nor University of Tromsø admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef NSC_FIR_H
+#define NSC_FIR_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. */
+
+/* Flags for configuration register CRF0 */
+#define APEDCRC 0x02
+#define ENBNKSEL 0x01
+
+/* Set 0 */
+#define TXD 0x00 /* Transmit data port */
+#define RXD 0x00 /* Receive data port */
+
+/* Register 1 */
+#define IER 0x01 /* Interrupt Enable Register*/
+#define IER_RXHDL_IE 0x01 /* Receiver high data level interrupt */
+#define IER_TXLDL_IE 0x02 /* Transeiver low data level interrupt */
+#define IER_LS_IE 0x04//* Link Status Interrupt */
+#define IER_ETXURI 0x04 /* Tx underrun */
+#define IER_DMA_IE 0x10 /* DMA finished interrupt */
+#define IER_TXEMP_IE 0x20
+#define IER_SFIF_IE 0x40 /* Frame status FIFO intr */
+#define IER_TMR_IE 0x80 /* Timer event */
+
+#define FCR 0x02 /* (write only) */
+#define FCR_FIFO_EN 0x01 /* Enable FIFO's */
+#define FCR_RXSR 0x02 /* Rx FIFO soft reset */
+#define FCR_TXSR 0x04 /* Tx FIFO soft reset */
+#define FCR_RXTH 0x40 /* Rx FIFO threshold (set to 16) */
+#define FCR_TXTH 0x20 /* Tx FIFO threshold (set to 17) */
+
+#define EIR 0x02 /* (read only) */
+#define EIR_RXHDL_EV 0x01
+#define EIR_TXLDL_EV 0x02
+#define EIR_LS_EV 0x04
+#define EIR_DMA_EV 0x10
+#define EIR_TXEMP_EV 0x20
+#define EIR_SFIF_EV 0x40
+#define EIR_TMR_EV 0x80
+
+#define LCR 0x03 /* Link control register */
+#define LCR_WLS_8 0x03 /* 8 bits */
+
+#define BSR 0x03 /* Bank select register */
+#define BSR_BKSE 0x80
+#define BANK0 LCR_WLS_8 /* Must make sure that we set 8N1 */
+#define BANK1 0x80
+#define BANK2 0xe0
+#define BANK3 0xe4
+#define BANK4 0xe8
+#define BANK5 0xec
+#define BANK6 0xf0
+#define BANK7 0xf4
+
+#define MCR 0x04 /* Mode Control Register */
+#define MCR_MODE_MASK ~(0xd0)
+#define MCR_UART 0x00
+#define MCR_RESERVED 0x20
+#define MCR_SHARP_IR 0x40
+#define MCR_SIR 0x60
+#define MCR_MIR 0x80
+#define MCR_FIR 0xa0
+#define MCR_CEIR 0xb0
+#define MCR_IR_PLS 0x10
+#define MCR_DMA_EN 0x04
+#define MCR_EN_IRQ 0x08
+#define MCR_TX_DFR 0x08
+
+#define LSR 0x05 /* Link status register */
+#define LSR_RXDA 0x01 /* Receiver data available */
+#define LSR_TXRDY 0x20 /* Transmitter ready */
+#define LSR_TXEMP 0x40 /* Transmitter empty */
+
+#define ASCR 0x07 /* Auxillary Status and Control Register */
+#define ASCR_RXF_TOUT 0x01 /* Rx FIFO timeout */
+#define ASCR_FEND_INF 0x02 /* Frame end bytes in rx FIFO */
+#define ASCR_S_EOT 0x04 /* Set end of transmission */
+#define ASCT_RXBSY 0x20 /* Rx busy */
+#define ASCR_TXUR 0x40 /* Transeiver underrun */
+#define ASCR_CTE 0x80 /* Clear timer event */
+
+/* Bank 2 */
+#define BGDL 0x00 /* Baud Generator Divisor Port (Low Byte) */
+#define BGDH 0x01 /* Baud Generator Divisor Port (High Byte) */
+
+#define ECR1 0x02 /* Extended Control Register 1 */
+#define ECR1_EXT_SL 0x01 /* Extended Mode Select */
+#define ECR1_DMANF 0x02 /* DMA Fairness */
+#define ECR1_DMATH 0x04 /* DMA Threshold */
+#define ECR1_DMASWP 0x08 /* DMA Swap */
+
+#define EXCR2 0x04
+#define EXCR2_TFSIZ 0x01 /* Rx FIFO size = 32 */
+#define EXCR2_RFSIZ 0x04 /* Tx FIFO size = 32 */
+
+#define TXFLV 0x06 /* Tx FIFO level */
+#define RXFLV 0x07 /* Rx FIFO level */
+
+/* Bank 3 */
+#define MID 0x00
+
+/* Bank 4 */
+#define TMRL 0x00 /* Timer low byte */
+#define TMRH 0x01 /* Timer high byte */
+#define IRCR1 0x02 /* Infrared control register 1 */
+#define IRCR1_TMR_EN 0x01 /* Timer enable */
+
+#define TFRLL 0x04
+#define TFRLH 0x05
+#define RFRLL 0x06
+#define RFRLH 0x07
+
+/* Bank 5 */
+#define IRCR2 0x04 /* Infrared control register 2 */
+#define IRCR2_MDRS 0x04 /* MIR data rate select */
+#define IRCR2_FEND_MD 0x20 /* */
+
+#define FRM_ST 0x05 /* Frame status FIFO */
+#define FRM_ST_VLD 0x80 /* Frame status FIFO data valid */
+#define FRM_ST_ERR_MSK 0x5f
+#define FRM_ST_LOST_FR 0x40 /* Frame lost */
+#define FRM_ST_MAX_LEN 0x10 /* Max frame len exceeded */
+#define FRM_ST_PHY_ERR 0x08 /* Physical layer error */
+#define FRM_ST_BAD_CRC 0x04
+#define FRM_ST_OVR1 0x02 /* Rx FIFO overrun */
+#define FRM_ST_OVR2 0x01 /* Frame status FIFO overrun */
+
+#define RFLFL 0x06
+#define RFLFH 0x07
+
+/* Bank 6 */
+#define IR_CFG2 0x00
+#define IR_CFG2_DIS_CRC 0x02
+
+/* Bank 7 */
+#define IRM_CR 0x07 /* Infrared module control register */
+#define IRM_CR_IRX_MSL 0x40
+#define IRM_CR_AF_MNT 0x80 /* Automatic format */
+
+/* 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;
+};
+
+struct frame_cb {
+ void *start; /* Start of frame in DMA mem */
+ 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 */
+};
+
+/* Private data for each instance */
+struct nsc_fir_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 */
+
+ struct timeval stamp;
+ struct timeval now;
+
+ spinlock_t lock; /* For serializing operations */
+
+ __u32 flags; /* Interface flags */
+ __u32 new_speed;
+ int suspend;
+};
+
+static inline void switch_bank(int iobase, int bank)
+{
+ outb(bank, iobase+BSR);
+}
+
+#endif /* NSC_FIR_H */
+++ /dev/null
-/*********************************************************************
- *
- * Filename: pc87108.h
- * Version:
- * Description:
- * Status: Experimental.
- * Author: Dag Brattli <dagb@cs.uit.no>
- * Created at: Fri Nov 13 14:37:40 1998
- * Modified at: Mon Nov 8 10:00:27 1999
- * Modified by: Dag Brattli <dagb@cs.uit.no>
- *
- * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>
- * Copyright (c) 1998 Lichen Wang, <lwang@actisys.com>
- * Copyright (c) 1998 Actisys Corp., www.actisys.com
- * 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 Dag Brattli nor University of Tromsø admit liability nor
- * provide warranty for any of this software. This material is
- * provided "AS-IS" and at no charge.
- *
- ********************************************************************/
-
-#ifndef PC87108_H
-#define PC87108_H
-
-#include <asm/io.h>
-
-/* Flags for configuration register CRF0 */
-#define APEDCRC 0x02
-#define ENBNKSEL 0x01
-
-/* Set 0 */
-#define TXD 0x00 /* Transmit data port */
-#define RXD 0x00 /* Receive data port */
-
-/* Register 1 */
-#define IER 0x01 /* Interrupt Enable Register*/
-#define IER_RXHDL_IE 0x01 /* Receiver high data level interrupt */
-#define IER_TXLDL_IE 0x02 /* Transeiver low data level interrupt */
-#define IER_LS_IE 0x04//* Link Status Interrupt */
-#define IER_ETXURI 0x04 /* Tx underrun */
-#define IER_DMA_IE 0x10 /* DMA finished interrupt */
-#define IER_TXEMP_IE 0x20
-#define IER_SFIF_IE 0x40 /* Frame status FIFO intr */
-#define IER_TMR_IE 0x80 /* Timer event */
-
-#define FCR 0x02 /* (write only) */
-#define FCR_FIFO_EN 0x01 /* Enable FIFO's */
-#define FCR_RXSR 0x02 /* Rx FIFO soft reset */
-#define FCR_TXSR 0x04 /* Tx FIFO soft reset */
-#define FCR_RXTH 0x80 /* Rx FIFO threshold (set to 16) */
-#define FCR_TXTH 0x20 /* Tx FIFO threshold (set to 17) */
-
-#define EIR 0x02 /* (read only) */
-#define EIR_RXHDL_EV 0x01
-#define EIR_TXLDL_EV 0x02
-#define EIR_LS_EV 0x04
-#define EIR_DMA_EV 0x10
-#define EIR_TXEMP_EV 0x20
-#define EIR_SFIF_EV 0x40
-#define EIR_TMR_EV 0x80
-
-#define LCR 0x03 /* Link control register */
-#define LCR_WLS_8 0x03 /* 8 bits */
-
-#define BSR 0x03 /* Bank select register */
-#define BSR_BKSE 0x80
-#define BANK0 LCR_WLS_8 /* Must make sure that we set 8N1 */
-#define BANK1 0x80
-#define BANK2 0xe0
-#define BANK3 0xe4
-#define BANK4 0xe8
-#define BANK5 0xec
-#define BANK6 0xf0
-#define BANK7 0xf4
-
-#define MCR 0x04 /* Mode Control Register */
-#define MCR_MODE_MASK ~(0xd0)
-#define MCR_UART 0x00
-#define MCR_RESERVED 0x20
-#define MCR_SHARP_IR 0x40
-#define MCR_SIR 0x60
-#define MCR_MIR 0x80
-#define MCR_FIR 0xa0
-#define MCR_CEIR 0xb0
-#define MCR_DMA_EN 0x04
-#define MCR_EN_IRQ 0x08
-#define MCR_TX_DFR 0x08
-
-#define LSR 0x05 /* Link status register */
-#define LSR_RXDA 0x01 /* Receiver data available */
-#define LSR_TXRDY 0x20 /* Transmitter ready */
-#define LSR_TXEMP 0x40 /* Transmitter empty */
-
-#define ASCR 0x07 /* Auxillary Status and Control Register */
-#define ASCR_RXF_TOUT 0x01 /* Rx FIFO timeout */
-#define ASCR_FEND_INF 0x02 /* Frame end bytes in rx FIFO */
-#define ASCR_S_EOT 0x04 /* Set end of transmission */
-#define ASCT_RXBSY 0x20 /* Rx busy */
-#define ASCR_TXUR 0x40 /* Transeiver underrun */
-#define ASCR_CTE 0x80 /* Clear timer event */
-
-/* Bank 2 */
-#define BGDL 0x00 /* Baud Generator Divisor Port (Low Byte) */
-#define BGDH 0x01 /* Baud Generator Divisor Port (High Byte) */
-
-#define ECR1 0x02 /* Extended Control Register 1 */
-#define ECR1_EXT_SL 0x01 /* Extended Mode Select */
-#define ECR1_DMANF 0x02 /* DMA Fairness */
-#define ECR1_DMATH 0x04
-#define ECR1_DMASWP 0x08 /* DMA Swap */
-
-#define EXCR2 0x04
-#define EXCR2_TFSIZ 0x01 /* Rx FIFO size = 32 */
-#define EXCR2_RFSIZ 0x04 /* Tx FIFO size = 32 */
-
-#define TXFLV 0x06 /* Tx FIFO level */
-#define RXFLV 0x07 /* Rx FIFO level */
-
-/* Bank 3 */
-#define MID 0x00
-
-/* Bank 4 */
-#define TMRL 0x00 /* Timer low byte */
-#define TMRH 0x01 /* Timer high byte */
-#define IRCR1 0x02 /* Infrared control register 1 */
-#define IRCR1_TMR_EN 0x01 /* Timer enable */
-
-#define TFRLL 0x04
-#define TFRLH 0x05
-#define RFRLL 0x06
-#define RFRLH 0x07
-
-/* Bank 5 */
-#define IRCR2 0x04 /* Infrared control register 2 */
-#define IRCR2_MDRS 0x04 /* MIR data rate select */
-#define IRCR2_FEND_MD 0x20 /* */
-
-#define FRM_ST 0x05 /* Frame status FIFO */
-#define FRM_ST_VLD 0x80 /* Frame status FIFO data valid */
-#define FRM_ST_ERR_MSK 0x5f
-#define FRM_ST_LOST_FR 0x40 /* Frame lost */
-#define FRM_ST_MAX_LEN 0x10 /* Max frame len exceeded */
-#define FRM_ST_PHY_ERR 0x08 /* Physical layer error */
-#define FRM_ST_BAD_CRC 0x04
-#define FRM_ST_OVR1 0x02 /* Receive overrun */
-#define FRM_ST_OVR2 0x01 /* Frame status FIFO overrun */
-
-#define RFLFL 0x06
-#define RFLFH 0x07
-
-/* Bank 6 */
-#define IR_CFG2 0x00
-#define IR_CFG2_DIS_CRC 0x02
-
-/* Bank 7 */
-#define IRM_CR 0x07 /* Infrared module control register */
-#define IRM_CR_IRX_MSL 0x40
-#define IRM_CR_AF_MNT 0x80 /* Automatic format */
-
-/* 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;
-};
-
-/* Private data for each instance */
-struct pc87108 {
- 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 */
-
- 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 */
-
- __u32 flags; /* Interface flags */
- __u32 new_speed;
-};
-
-static inline void switch_bank(int iobase, int bank)
-{
- outb(bank, iobase+BSR);
-}
-
-#endif
/*********************************************************************
*
* Filename: smc-ircc.h
- * Version:
- * Description:
+ * Version: 0.3
+ * Description: Definitions for the SMC IrCC chipset
* Status: Experimental.
* Author: Thomas Davis (tadavis@jps.net)
*
- * Copyright (c) 1998, 1999 Thomas Davis (tadavis@jps.net>
+ * Copyright (c) 1999-2000, Dag Brattli <dagb@cs.uit.no>
+ * Copyright (c) 1998-1999, Thomas Davis (tadavis@jps.net>
* 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.
- *
- * I, Thomas Davis, admit no liability nor provide warranty for any
- * of this software. This material is provided "AS-IS" and at no charge.
- *
- * Definitions for the SMC IrCC controller.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
*
********************************************************************/
-#include <net/irda/irport.h>
-
#ifndef SMC_IRCC_H
#define SMC_IRCC_H
-#define UART_MASTER 0x07
-#define UART_MASTER_POWERDOWN 1<<7
-#define UART_MASTER_RESET 1<<6
-#define UART_MASTER_INT_EN 1<<5
-#define UART_MASTER_ERROR_RESET 1<<4
+#include <linux/spinlock.h>
-/* Register block 0 */
+#include <net/irda/irport.h>
-#define UART_IIR 0x01
-#define UART_IER 0x02
-#define UART_LSR 0x03
-#define UART_LCR_A 0x04
-#define UART_LCR_B 0x05
-#define UART_BSR 0x06
-
-#define UART_IIR_ACTIVE_FRAME 1<<7
-#define UART_IIR_EOM 1<<6
-#define UART_IIR_RAW_MODE 1<<5
-#define UART_IIR_FIFO 1<<4
-
-#define UART_IER_ACTIVE_FRAME 1<<7
-#define UART_IER_EOM 1<<6
-#define UART_IER_RAW_MODE 1<<5
-#define UART_IER_FIFO 1<<4
-
-#define UART_LSR_UNDERRUN 1<<7
-#define UART_LSR_OVERRUN 1<<6
-#define UART_LSR_FRAME_ERROR 1<<5
-#define UART_LSR_SIZE_ERROR 1<<4
-#define UART_LSR_CRC_ERROR 1<<3
-#define UART_LSR_FRAME_ABORT 1<<2
-
-#define UART_LCR_A_FIFO_RESET 1<<7
-#define UART_LCR_A_FAST 1<<6
-#define UART_LCR_A_GP_DATA 1<<5
-#define UART_LCR_A_RAW_TX 1<<4
-#define UART_LCR_A_RAW_RX 1<<3
-#define UART_LCR_A_ABORT 1<<2
-#define UART_LCR_A_DATA_DONE 1<<1
-
-#define UART_LCR_B_SCE_DISABLED 0x00<<6
-#define UART_LCR_B_SCE_TRANSMIT 0x01<<6
-#define UART_LCR_B_SCE_RECEIVE 0x02<<6
-#define UART_LCR_B_SCE_UNDEFINED 0x03<<6
-#define UART_LCR_B_SIP_ENABLE 1<<5
-#define UART_LCR_B_BRICK_WALL 1<<4
-
-#define UART_BSR_NOT_EMPTY 1<<7
-#define UART_BSR_FIFO_FULL 1<<6
-#define UART_BSR_TIMEOUT 1<<5
+/* DMA modes needed */
+#define DMA_TX_MODE 0x08 /* Mem to I/O, ++, demand. */
+#define DMA_RX_MODE 0x04 /* I/O to mem, ++, demand. */
-/* Register block 1 */
+#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
-#define UART_SCE_CFGA 0x00
-#define UART_SCE_CFGB 0x01
-#define UART_FIFO_THRESHOLD 0x02
-
-#define UART_CFGA_AUX_IR 0x01<<7
-#define UART_CFGA_HALF_DUPLEX 0x01<<2
-#define UART_CFGA_TX_POLARITY 0x01<<1
-#define UART_CFGA_RX_POLARITY 0x01
-
-#define UART_CFGA_COM 0x00<<3
-#define UART_CFGA_IRDA_SIR_A 0x01<<3
-#define UART_CFGA_ASK_SIR 0x02<<3
-#define UART_CFGA_IRDA_SIR_B 0x03<<3
-#define UART_CFGA_IRDA_HDLC 0x04<<3
-#define UART_CFGA_IRDA_4PPM 0x05<<3
-#define UART_CFGA_CONSUMER 0x06<<3
-#define UART_CFGA_RAW_IR 0x07<<3
-#define UART_CFGA_OTHER 0x08<<3
-
-#define UART_IR_HDLC 0x04
-#define UART_IR_4PPM 0x01
-#define UART_IR_CONSUMER 0x02
-
-#define UART_CFGB_LOOPBACK 0x01<<5
-#define UART_CFGB_LPBCK_TX_CRC 0x01<<4
-#define UART_CFGB_NOWAIT 0x01<<3
-#define UART_CFGB_STRING_MOVE 0x01<<2
-#define UART_CFGB_DMA_BURST 0x01<<1
-#define UART_CFGB_DMA_ENABLE 0x01
-
-#define UART_CFGB_COM 0x00<<6
-#define UART_CFGB_IR 0x01<<6
-#define UART_CFGB_AUX 0x02<<6
-#define UART_CFGB_INACTIVE 0x03<<6
-
-/* Register block 2 - Consumer IR - not used */
+/* 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
-/* Register block 3 - Identification Registers! */
+/* 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 UART_ID_HIGH 0x00 /* 0x10 */
-#define UART_ID_LOW 0x01 /* 0xB8 */
-#define UART_CHIP_ID 0x02 /* 0xF1 */
-#define UART_VERSION 0x03 /* 0x01 */
-#define UART_INTERFACE 0x04 /* low 4 = DMA, high 4 = IRQ */
+/* 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 */
/* Register block 4 - IrDA */
-#define UART_CONTROL 0x00
-#define UART_BOF_COUNT_LO 0x01
-#define UART_BRICKWALL_CNT_LO 0x02
-#define UART_BRICKWALL_TX_CNT_HI 0x03
-#define UART_TX_SIZE_LO 0x04
-#define UART_RX_SIZE_HI 0x05
-#define UART_RX_SIZE_LO 0x06
+#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 UART_1152 0x01<<7
-#define UART_CRC 0x01<<6
+#define IRCC_1152 0x01<<7
+#define IRCC_CRC 0x01<<6
/* For storing entries in the status FIFO */
struct st_fifo_entry {
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 */
struct irport_cb *irport;
+
+ spinlock_t lock; /* For serializing operations */
__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 */
+ int tx_buff_offsets[10]; /* Offsets between frames in tx_buff */
+ int tx_len; /* Number of frames in tx_buff */
};
-#endif
+#endif /* SMC_IRCC_H */
#warning This file is not supposed to be used outside of kernel.
#endif
-#define RT_HASH_DIVISOR 256
-
#define RTO_ONLINK 0x01
#define RTO_TPROXY 0x80000000
extern void sysctl_init(void);
extern void filescache_init(void);
extern void signals_init(void);
+extern void bdev_init(void);
extern int init_pcmcia_ds(void);
extern void free_initmem(void);
static unsigned long swap_id = 0; /* currently being swapped */
static unsigned long swap_idx = 0; /* next to swap */
-int shm_swap (int prio, int gfp_mask)
+int shm_swap (int prio, int gfp_mask, zone_t *zone)
{
pte_t page;
struct shmid_kernel *shp;
if (!pte_present(page))
goto check_table;
page_map = pte_page(page);
- if ((gfp_mask & __GFP_DMA) && !PageDMA(page_map))
- goto check_table;
- if (!(gfp_mask & __GFP_HIGHMEM) && PageHighMem(page_map))
+ if (zone && (!memclass(page_map->zone, zone)))
goto check_table;
swap_attempts++;
return;
}
-int shm_swap (int prio, int gfp_mask)
+int shm_swap (int prio, int gfp_mask, zone_t *zone)
{
return 0;
}
Modified to avoid chroot and file sharing problems.
Mikael Pettersson
+
+ Limit the concurrent number of kmod modprobes to catch loops from
+ "modprobe needs a service that is in a module".
+ Keith Owens <kaos@ocs.com.au> December 1999
*/
#define __KERNEL_SYSCALLS__
*/
char modprobe_path[256] = "/sbin/modprobe";
+extern int max_threads;
+
static inline void
use_init_fs_context(void)
{
int pid;
int waitpid_result;
sigset_t tmpsig;
+ int i;
+ static atomic_t kmod_concurrent = ATOMIC_INIT(0);
+#define MAX_KMOD_CONCURRENT 50 /* Completely arbitrary value - KAO */
+ static int kmod_loop_msg;
/* Don't allow request_module() before the root fs is mounted! */
if ( ! current->fs->root ) {
return -EPERM;
}
+ /* If modprobe needs a service that is in a module, we get a recursive
+ * loop. Limit the number of running kmod threads to max_threads/2 or
+ * MAX_KMOD_CONCURRENT, whichever is the smaller. A cleaner method
+ * would be to run the parents of this process, counting how many times
+ * kmod was invoked. That would mean accessing the internals of the
+ * process tables to get the command line, proc_pid_cmdline is static
+ * and it is not worth changing the proc code just to handle this case.
+ * KAO.
+ */
+ i = max_threads/2;
+ if (i > MAX_KMOD_CONCURRENT)
+ i = MAX_KMOD_CONCURRENT;
+ atomic_inc(&kmod_concurrent);
+ if (atomic_read(&kmod_concurrent) > i) {
+ if (kmod_loop_msg++ < 5)
+ printk(KERN_ERR
+ "kmod: runaway modprobe loop assumed and stopped\n");
+ atomic_dec(&kmod_concurrent);
+ return -ENOMEM;
+ }
+
pid = kernel_thread(exec_modprobe, (void*) module_name, 0);
if (pid < 0) {
printk(KERN_ERR "request_module[%s]: fork failed, errno %d\n", module_name, -pid);
+ atomic_dec(&kmod_concurrent);
return pid;
}
spin_unlock_irq(¤t->sigmask_lock);
waitpid_result = waitpid(pid, NULL, __WCLONE);
+ atomic_dec(&kmod_concurrent);
/* Allow signals again.. */
spin_lock_irq(¤t->sigmask_lock);
#ifndef CONFIG_DISCONTIGMEM
EXPORT_SYMBOL(contig_page_data);
#endif
+EXPORT_SYMBOL(num_physpages);
EXPORT_SYMBOL(kmem_find_general_cachep);
EXPORT_SYMBOL(kmem_cache_create);
EXPORT_SYMBOL(kmem_cache_destroy);
#endif
p = curr->task;
state = p->state;
- if (state & mode) {
+ if (state & (mode & ~TASK_EXCLUSIVE)) {
#if WAITQUEUE_DEBUG
curr->__waker = (long)__builtin_return_address(0);
#endif
wake_up_process_synchronous(p);
else
wake_up_process(p);
- if (state & TASK_EXCLUSIVE)
+ if (state & mode & TASK_EXCLUSIVE)
break;
}
}
spin_unlock(&pagecache_lock);
}
-int shrink_mmap(int priority, int gfp_mask)
+int shrink_mmap(int priority, int gfp_mask, zone_t *zone)
{
int ret = 0, count;
LIST_HEAD(young);
dispose = &old;
/* don't account passes over not DMA pages */
- if ((gfp_mask & __GFP_DMA) && !PageDMA(page))
- goto dispose_continue;
- if (!(gfp_mask & __GFP_HIGHMEM) && PageHighMem(page))
+ if (zone && (!memclass(page->zone, zone)))
goto dispose_continue;
count--;
static unsigned long map_new_virtual(struct page *page)
{
unsigned long vaddr;
- int count = LAST_PKMAP;
+ int count;
+start:
+ count = LAST_PKMAP;
/* Find an empty entry */
for (;;) {
last_pkmap_nr = (last_pkmap_nr + 1) & LAST_PKMAP_MASK;
- if (!last_pkmap_nr)
+ if (!last_pkmap_nr) {
flush_all_zero_pkmaps();
+ count = LAST_PKMAP;
+ }
if (!pkmap_count[last_pkmap_nr])
break; /* Found a usable entry */
if (--count)
return page->virtual;
/* Re-start */
- count = LAST_PKMAP;
+ goto start;
}
}
vaddr = PKMAP_ADDR(last_pkmap_nr);
return 1;
current->flags |= PF_MEMALLOC;
- freed = try_to_free_pages(gfp_mask);
+ freed = try_to_free_pages(gfp_mask, zone);
current->flags &= ~PF_MEMALLOC;
if (!freed && !(gfp_mask & (__GFP_MED | __GFP_HIGH)))
/*
* We are still balancing memory in a global way:
*/
-static inline int balance_memory (int gfp_mask)
+static inline int balance_memory (zone_t *zone, int gfp_mask)
{
unsigned long free = nr_free_pages();
static int low_on_memory = 0;
return 1;
current->flags |= PF_MEMALLOC;
- freed = try_to_free_pages(gfp_mask);
+ freed = try_to_free_pages(gfp_mask, zone);
current->flags &= ~PF_MEMALLOC;
if (!freed && !(gfp_mask & (__GFP_MED | __GFP_HIGH)))
* The main chunk of the balancing code is in this offline branch:
*/
balance:
- if (!balance_memory(gfp_mask))
+ if (!balance_memory(z, gfp_mask))
goto nopage;
goto ready;
}
i = 10;
if (i > 256)
i = 256;
- freepages.min = i;
- freepages.low = i * 2;
- freepages.high = i * 3;
+ freepages.min += i;
+ freepages.low += i * 2;
+ freepages.high += i * 3;
/*
* Some architectures (with lots of mem and discontinous memory
zone->size = size;
zone->name = zone_names[j];
zone->lock = SPIN_LOCK_UNLOCKED;
+ zone->zone_pgdat = pgdat;
if (!size)
continue;
{
void *addr;
+ /*
+ * If we requested dmaable memory, we will get it. Even if we
+ * did not request dmaable memory, we might get it, but that
+ * would be relatively rare and ignorable.
+ */
*dma = flags & SLAB_DMA;
addr = (void*) __get_free_pages(flags, cachep->c_gfporder);
/* Assume that now we have the pages no one else can legally
* it is a named-page or buffer-page. The members it tests are
* of no interest here.....
*/
- if (!*dma && addr) {
- /* Need to check if can dma. */
- struct page *page = mem_map + MAP_NR(addr);
- *dma = 1<<cachep->c_gfporder;
- while ((*dma)--) {
- if (!PageDMA(page)) {
- *dma = 0;
- break;
- }
- page++;
- }
- }
return addr;
}
* using a process that no longer actually exists (it might
* have died while we slept).
*/
-static int try_to_swap_out(struct vm_area_struct* vma, unsigned long address, pte_t * page_table, int gfp_mask)
+static int try_to_swap_out(struct vm_area_struct* vma, unsigned long address, pte_t * page_table, int gfp_mask, zone_t *zone)
{
pte_t pte;
swp_entry_t entry;
if (PageReserved(page)
|| PageLocked(page)
- || ((gfp_mask & __GFP_DMA) && !PageDMA(page))
- || (!(gfp_mask & __GFP_HIGHMEM) && PageHighMem(page)))
+ || (zone && (!memclass(page->zone, zone))))
goto out_failed;
/*
* (C) 1993 Kai Petzke, wpp@marie.physik.tu-berlin.de
*/
-static inline int swap_out_pmd(struct vm_area_struct * vma, pmd_t *dir, unsigned long address, unsigned long end, int gfp_mask)
+static inline int swap_out_pmd(struct vm_area_struct * vma, pmd_t *dir, unsigned long address, unsigned long end, int gfp_mask, zone_t *zone)
{
pte_t * pte;
unsigned long pmd_end;
do {
int result;
vma->vm_mm->swap_address = address + PAGE_SIZE;
- result = try_to_swap_out(vma, address, pte, gfp_mask);
+ result = try_to_swap_out(vma, address, pte, gfp_mask, zone);
if (result)
return result;
address += PAGE_SIZE;
return 0;
}
-static inline int swap_out_pgd(struct vm_area_struct * vma, pgd_t *dir, unsigned long address, unsigned long end, int gfp_mask)
+static inline int swap_out_pgd(struct vm_area_struct * vma, pgd_t *dir, unsigned long address, unsigned long end, int gfp_mask, zone_t *zone)
{
pmd_t * pmd;
unsigned long pgd_end;
end = pgd_end;
do {
- int result = swap_out_pmd(vma, pmd, address, end, gfp_mask);
+ int result = swap_out_pmd(vma, pmd, address, end, gfp_mask, zone);
if (result)
return result;
address = (address + PMD_SIZE) & PMD_MASK;
return 0;
}
-static int swap_out_vma(struct vm_area_struct * vma, unsigned long address, int gfp_mask)
+static int swap_out_vma(struct vm_area_struct * vma, unsigned long address, int gfp_mask, zone_t *zone)
{
pgd_t *pgdir;
unsigned long end;
if (address >= end)
BUG();
do {
- int result = swap_out_pgd(vma, pgdir, address, end, gfp_mask);
+ int result = swap_out_pgd(vma, pgdir, address, end, gfp_mask, zone);
if (result)
return result;
address = (address + PGDIR_SIZE) & PGDIR_MASK;
return 0;
}
-static int swap_out_mm(struct mm_struct * mm, int gfp_mask)
+static int swap_out_mm(struct mm_struct * mm, int gfp_mask, zone_t *zone)
{
unsigned long address;
struct vm_area_struct* vma;
address = vma->vm_start;
for (;;) {
- int result = swap_out_vma(vma, address, gfp_mask);
+ int result = swap_out_vma(vma, address, gfp_mask, zone);
if (result)
return result;
vma = vma->vm_next;
* N.B. This function returns only 0 or 1. Return values != 1 from
* the lower level routines result in continued processing.
*/
-static int swap_out(unsigned int priority, int gfp_mask)
+static int swap_out(unsigned int priority, int gfp_mask, zone_t *zone)
{
struct task_struct * p;
int counter;
int ret;
atomic_inc(&best->mm_count);
- ret = swap_out_mm(best, gfp_mask);
+ ret = swap_out_mm(best, gfp_mask, zone);
mmdrop(best);
if (!ret)
* cluster them so that we get good swap-out behaviour. See
* the "free_memory()" macro for details.
*/
-static int do_try_to_free_pages(unsigned int gfp_mask)
+static int do_try_to_free_pages(unsigned int gfp_mask, zone_t *zone)
{
int priority;
int count = SWAP_CLUSTER_MAX;
priority = 6;
do {
- while (shrink_mmap(priority, gfp_mask)) {
+ while (shrink_mmap(priority, gfp_mask, zone)) {
if (!--count)
goto done;
}
/* don't be too light against the d/i cache since
shrink_mmap() almost never fail when there's
really plenty of memory free. */
- count -= shrink_dcache_memory(priority, gfp_mask);
- count -= shrink_icache_memory(priority, gfp_mask);
+ count -= shrink_dcache_memory(priority, gfp_mask, zone);
+ count -= shrink_icache_memory(priority, gfp_mask, zone);
if (count <= 0)
goto done;
/* Try to get rid of some shared memory pages.. */
if (gfp_mask & __GFP_IO) {
- while (shm_swap(priority, gfp_mask)) {
+ while (shm_swap(priority, gfp_mask, zone)) {
if (!--count)
goto done;
}
}
/* Then, try to page stuff out.. */
- while (swap_out(priority, gfp_mask)) {
+ while (swap_out(priority, gfp_mask, zone)) {
if (!--count)
goto done;
}
allocations (not GFP_HIGHMEM ones). */
if (nr_free_buffer_pages() >= freepages.high)
break;
- if (!do_try_to_free_pages(GFP_KSWAPD))
+ if (!do_try_to_free_pages(GFP_KSWAPD, 0))
break;
run_task_queue(&tq_disk);
} while (!tsk->need_resched);
* can be done by just dropping cached pages without having
* any deadlock issues.
*/
-int try_to_free_pages(unsigned int gfp_mask)
+int try_to_free_pages(unsigned int gfp_mask, zone_t *zone)
{
int retval = 1;
wake_up_process(kswapd_process);
if (gfp_mask & __GFP_WAIT)
- retval = do_try_to_free_pages(gfp_mask);
+ retval = do_try_to_free_pages(gfp_mask, zone);
return retval;
}
-------------------+-------------------------------------------
802 [other ] alan@lxorguk.ukuu.org.uk
[token ring ] p.norton@computer.org
-appletalk Jay.Schulist@spacs.k12.wi.us
+appletalk jschlst@turbolinux.com
ax25 g4klx@g4klx.demon.co.uk
core alan@lxorguk.ukuu.org.uk
decnet SteveW@ACM.org
ethernet alan@lxorguk.ukuu.org.uk
ipv4 davem@caip.rutgers.edu,Eric.Schenk@dna.lth.se
ipv6 davem@caip.rutgers.edu,Eric.Schenk@dna.lth.se
-ipx/spx Jay.Schulist@spacs.k12.wi.us
+ipx/spx jschlst@turbolinux.com
irda dagb@cs.uit.no
lapb g4klx@g4klx.demon.co.uk
netrom g4klx@g4klx.demon.co.uk
* Linux Socket Filter - Kernel level socket filtering
*
* Author:
- * Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ * Jay Schulist <jschlst@turbolinux.com>
*
* Based on the design of:
* - The Berkeley Packet Filter
* Steve Whitehouse : More SMP locking changes & dn_cache_dump()
* Steve Whitehouse : Prerouting NF hook, now really is prerouting.
* Fixed possible skb leak in rtnetlink funcs.
+ * Steve Whitehouse : Dave Miller's dynamic hash table sizing and
+ * Alexey Kuznetsov's finer grained locking
+ * from ipv4/route.c.
*/
/******************************************************************************
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
-#include <linux/timer.h>
#include <linux/sockios.h>
#include <linux/net.h>
#include <linux/netdevice.h>
#include <net/dn_fib.h>
#include <net/dn_raw.h>
+struct dn_rt_hash_bucket
+{
+ struct dn_route *chain;
+ rwlock_t lock;
+} __attribute__((__aligned__(8)));
+
extern struct neigh_table dn_neigh_table;
-#define DN_HASHBUCKETS 16
static unsigned char dn_hiord_addr[6] = {0xAA,0x00,0x04,0x00,0x00,0x00};
static void dn_dst_link_failure(struct sk_buff *);
static int dn_route_input(struct sk_buff *);
-static struct dn_route *dn_route_cache[DN_HASHBUCKETS];
-static rwlock_t dn_hash_lock = RW_LOCK_UNLOCKED;
+static struct dn_rt_hash_bucket *dn_rt_hash_table;
+static unsigned dn_rt_hash_mask;
static struct timer_list dn_route_timer = { NULL, NULL, 0, 0L, NULL };
int decnet_dst_gc_interval = 2;
static __inline__ unsigned dn_hash(unsigned short dest)
{
- unsigned short tmp = (dest&0xff) ^ (dest>>8);
- return (tmp&0x0f) ^ (tmp>>4);
+ unsigned short tmp = dest;
+ tmp ^= (dest >> 3);
+ tmp ^= (dest >> 5);
+ tmp ^= (dest >> 10);
+ return dn_rt_hash_mask & (unsigned)tmp;
}
static void dn_dst_check_expire(unsigned long dummy)
unsigned long now = jiffies;
unsigned long expire = 120 * HZ;
- for(i = 0; i < DN_HASHBUCKETS; i++) {
- rtp = &dn_route_cache[i];
+ for(i = 0; i <= dn_rt_hash_mask; i++) {
+ rtp = &dn_rt_hash_table[i].chain;
- write_lock(&dn_hash_lock);
+ write_lock(&dn_rt_hash_table[i].lock);
for(;(rt=*rtp); rtp = &rt->u.rt_next) {
if (atomic_read(&rt->u.dst.__refcnt) ||
(now - rt->u.dst.lastuse) < expire)
rt->u.rt_next = NULL;
dst_free(&rt->u.dst);
}
- write_unlock(&dn_hash_lock);
+ write_unlock(&dn_rt_hash_table[i].lock);
if ((jiffies - now) > 0)
break;
unsigned long now = jiffies;
unsigned long expire = 10 * HZ;
- write_lock_bh(&dn_hash_lock);
- for(i = 0; i < DN_HASHBUCKETS; i++) {
- rtp = &dn_route_cache[i];
+ for(i = 0; i <= dn_rt_hash_mask; i++) {
+ write_lock_bh(&dn_rt_hash_table[i].lock);
+ rtp = &dn_rt_hash_table[i].chain;
for(; (rt=*rtp); rtp = &rt->u.rt_next) {
if (atomic_read(&rt->u.dst.__refcnt) ||
(now - rt->u.dst.lastuse) < expire)
dst_free(&rt->u.dst);
break;
}
+ write_unlock_bh(&dn_rt_hash_table[i].lock);
}
- write_unlock_bh(&dn_hash_lock);
return 0;
}
unsigned hash = dn_hash(rt->rt_daddr);
unsigned long now = jiffies;
- write_lock_bh(&dn_hash_lock);
- rt->u.rt_next = dn_route_cache[hash];
- dn_route_cache[hash] = rt;
+ write_lock_bh(&dn_rt_hash_table[hash].lock);
+ rt->u.rt_next = dn_rt_hash_table[hash].chain;
+ dn_rt_hash_table[hash].chain = rt;
dst_hold(&rt->u.dst);
rt->u.dst.__use++;
rt->u.dst.lastuse = now;
- write_unlock_bh(&dn_hash_lock);
+ write_unlock_bh(&dn_rt_hash_table[hash].lock);
}
void dn_run_flush(unsigned long dummy)
int i;
struct dn_route *rt, *next;
- write_lock_bh(&dn_hash_lock);
- for(i = 0; i < DN_HASHBUCKETS; i++) {
- if ((rt = xchg(&dn_route_cache[i], NULL)) == NULL)
- continue;
+ for(i = 0; i < dn_rt_hash_mask; i++) {
+ write_lock_bh(&dn_rt_hash_table[i].lock);
+
+ if ((rt = xchg(&dn_rt_hash_table[i].chain, NULL)) == NULL)
+ goto nothing_to_declare;
for(; rt; rt=next) {
next = rt->u.rt_next;
rt->u.rt_next = NULL;
dst_free((struct dst_entry *)rt);
}
+
+nothing_to_declare:
+ write_unlock_bh(&dn_rt_hash_table[i].lock);
}
- write_unlock_bh(&dn_hash_lock);
}
static int dn_route_rx_packet(struct sk_buff *skb)
struct dn_route *rt = NULL;
if (!(flags & MSG_TRYHARD)) {
- read_lock_bh(&dn_hash_lock);
- for(rt = dn_route_cache[hash]; rt; rt = rt->u.rt_next) {
+ read_lock_bh(&dn_rt_hash_table[hash].lock);
+ for(rt = dn_rt_hash_table[hash].chain; rt; rt = rt->u.rt_next) {
if ((dst == rt->rt_daddr) &&
(src == rt->rt_saddr) &&
(rt->rt_iif == 0) &&
rt->u.dst.lastuse = jiffies;
dst_hold(&rt->u.dst);
rt->u.dst.__use++;
- read_unlock_bh(&dn_hash_lock);
+ read_unlock_bh(&dn_rt_hash_table[hash].lock);
*pprt = &rt->u.dst;
return 0;
}
}
- read_unlock_bh(&dn_hash_lock);
+ read_unlock_bh(&dn_rt_hash_table[hash].lock);
}
return dn_route_output_slow(pprt, dst, src, flags);
if (skb->dst)
return 0;
- read_lock_bh(&dn_hash_lock);
- for(rt = dn_route_cache[hash]; rt != NULL; rt = rt->u.rt_next) {
+ read_lock(&dn_rt_hash_table[hash].lock);
+ for(rt = dn_rt_hash_table[hash].chain; rt != NULL; rt = rt->u.rt_next) {
if ((rt->rt_saddr == cb->dst) &&
(rt->rt_daddr == cb->src) &&
(rt->rt_oif == 0) &&
rt->u.dst.lastuse = jiffies;
dst_hold(&rt->u.dst);
rt->u.dst.__use++;
- read_unlock_bh(&dn_hash_lock);
+ read_unlock(&dn_rt_hash_table[hash].lock);
skb->dst = (struct dst_entry *)rt;
return 0;
}
}
- read_unlock_bh(&dn_hash_lock);
+ read_unlock(&dn_rt_hash_table[hash].lock);
return dn_route_input_slow(skb);
}
skb->rx_dev = dev;
cb->src = src;
cb->dst = dst;
+ local_bh_disable();
err = dn_route_input(skb);
+ local_bh_enable();
memset(cb, 0, sizeof(struct dn_skb_cb));
rt = (struct dn_route *)skb->dst;
} else {
s_h = cb->args[0];
s_idx = idx = cb->args[1];
- for(h = 0; h < DN_HASHBUCKETS; h++) {
+ for(h = 0; h <= dn_rt_hash_mask; h++) {
if (h < s_h)
continue;
if (h > s_h)
s_idx = 0;
- read_lock_bh(&dn_hash_lock);
- for(rt = dn_route_cache[h], idx = 0; rt; rt = rt->u.rt_next, idx++) {
+ read_lock_bh(&dn_rt_hash_table[h].lock);
+ for(rt = dn_rt_hash_table[h].chain, idx = 0; rt; rt = rt->u.rt_next, idx++) {
if (idx < s_idx)
continue;
skb->dst = dst_clone(&rt->u.dst);
if (dn_rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1) <= 0) {
dst_release(xchg(&skb->dst, NULL));
- read_unlock_bh(&dn_hash_lock);
+ read_unlock_bh(&dn_rt_hash_table[h].lock);
goto done;
}
dst_release(xchg(&skb->dst, NULL));
}
- read_unlock_bh(&dn_hash_lock);
+ read_unlock_bh(&dn_rt_hash_table[h].lock);
}
done:
int i;
char buf1[DN_ASCBUF_LEN], buf2[DN_ASCBUF_LEN];
- read_lock_bh(&dn_hash_lock);
- for(i = 0; i < DN_HASHBUCKETS; i++) {
- rt = dn_route_cache[i];
+ for(i = 0; i <= dn_rt_hash_mask; i++) {
+ read_lock_bh(&dn_rt_hash_table[i].lock);
+ rt = dn_rt_hash_table[i].chain;
for(; rt != NULL; rt = rt->u.rt_next) {
len += sprintf(buffer + len, "%-8s %-7s %-7s %04d %04d %04d\n",
rt->u.dst.dev ? rt->u.dst.dev->name : "*",
(int)rt->u.dst.rtt
);
+
pos = begin + len;
if (pos < offset) {
if (pos > offset + length)
break;
}
+ read_unlock_bh(&dn_rt_hash_table[i].lock);
if (pos > offset + length)
break;
}
- read_unlock_bh(&dn_hash_lock);
*start = buffer + (offset - begin);
len -= (offset - begin);
void __init dn_route_init(void)
{
- memset(dn_route_cache, 0, sizeof(struct dn_route *) * DN_HASHBUCKETS);
+ int i, goal, order;
dn_dst_ops.kmem_cachep = kmem_cache_create("dn_dst_cache",
sizeof(struct dn_route),
0, SLAB_HWCACHE_ALIGN,
NULL, NULL);
+ if (!dn_dst_ops.kmem_cachep)
+ panic("DECnet: Failed to allocate dn_dst_cache\n");
+
dn_route_timer.function = dn_dst_check_expire;
dn_route_timer.expires = jiffies + decnet_dst_gc_interval * HZ;
add_timer(&dn_route_timer);
+ goal = num_physpages >> (26 - PAGE_SHIFT);
+
+ for(order = 0; (1UL << order) < goal; order++)
+ /* NOTHING */;
+
+ /*
+ * Only want 1024 entries max, since the table is very, very unlikely
+ * to be larger than that.
+ */
+ while(order && ((((1UL << order) * PAGE_SIZE) /
+ sizeof(struct dn_rt_hash_bucket)) >= 2048))
+ order--;
+
+ do {
+ dn_rt_hash_mask = (1UL << order) * PAGE_SIZE /
+ sizeof(struct dn_rt_hash_bucket);
+ while(dn_rt_hash_mask & (dn_rt_hash_mask - 1))
+ dn_rt_hash_mask--;
+ dn_rt_hash_table = (struct dn_rt_hash_bucket *)
+ __get_free_pages(GFP_ATOMIC, order);
+ } while (dn_rt_hash_table == NULL && --order > 0);
+
+ if (!dn_rt_hash_table)
+ panic("Failed to allocate DECnet route cache hash table\n");
+
+ printk(KERN_INFO "DECnet: Routing cache hash table of %u buckets, %dKbytes\n", dn_rt_hash_mask, (dn_rt_hash_mask*sizeof(struct dn_rt_hash_bucket))/1024);
+
+ dn_rt_hash_mask--;
+ for(i = 0; i <= dn_rt_hash_mask; i++) {
+ dn_rt_hash_table[i].lock = RW_LOCK_UNLOCKED;
+ dn_rt_hash_table[i].chain = NULL;
+ }
+
+ dn_dst_ops.gc_thresh = (dn_rt_hash_mask + 1);
+
#ifdef CONFIG_PROC_FS
proc_net_create("decnet_cache",0,decnet_cache_get_info);
#endif /* CONFIG_PROC_FS */
*
* ROUTE - implementation of the IP router.
*
- * Version: $Id: route.c,v 1.75 1999/12/23 01:41:44 davem Exp $
+ * Version: $Id: route.c,v 1.77 2000/01/06 00:41:59 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
int ip_rt_min_delay = 2*HZ;
int ip_rt_max_delay = 10*HZ;
-int ip_rt_gc_thresh = RT_HASH_DIVISOR;
-int ip_rt_max_size = RT_HASH_DIVISOR*16;
+int ip_rt_max_size;
int ip_rt_gc_timeout = RT_GC_TIMEOUT;
int ip_rt_gc_interval = 60*HZ;
int ip_rt_gc_min_interval = 5*HZ;
#define RTprint(a...) printk(KERN_DEBUG a)
-static void rt_run_flush(unsigned long dummy);
-
-static struct timer_list rt_flush_timer =
- { NULL, NULL, 0, 0L, rt_run_flush };
-static struct timer_list rt_periodic_timer =
- { NULL, NULL, 0, 0L, NULL };
+static struct timer_list rt_flush_timer;
+static struct timer_list rt_periodic_timer;
/*
* Interface to generic destination cache.
{
AF_INET,
__constant_htons(ETH_P_IP),
- RT_HASH_DIVISOR,
+ 0,
rt_garbage_collect,
ipv4_dst_check,
/* The locking scheme is rather straight forward:
*
- * 1) A BH protected rwlock protects the central route hash.
+ * 1) A BH protected rwlocks protect buckets of the central route hash.
* 2) Only writers remove entries, and they hold the lock
* as they look at rtable reference counts.
* 3) Only readers acquire references to rtable entries,
* lock held.
*/
-static struct rtable *rt_hash_table[RT_HASH_DIVISOR];
-static rwlock_t rt_hash_lock = RW_LOCK_UNLOCKED;
+struct rt_hash_bucket {
+ struct rtable *chain;
+ rwlock_t lock;
+} __attribute__((__aligned__(8)));
+
+static struct rt_hash_bucket *rt_hash_table;
+static unsigned rt_hash_mask;
+static int rt_hash_log;
static int rt_intern_hash(unsigned hash, struct rtable * rth, struct rtable ** res);
static __inline__ unsigned rt_hash_code(u32 daddr, u32 saddr, u8 tos)
{
unsigned hash = ((daddr&0xF0F0F0F0)>>4)|((daddr&0x0F0F0F0F)<<4);
- hash = hash^saddr^tos;
- hash = hash^(hash>>16);
- return (hash^(hash>>8)) & 0xFF;
+ hash ^= saddr^tos;
+ hash ^= (hash>>16);
+ return (hash^(hash>>8)) & rt_hash_mask;
}
#ifndef CONFIG_PROC_FS
len = 128;
}
-
- read_lock_bh(&rt_hash_lock);
-
- for (i = 0; i<RT_HASH_DIVISOR; i++) {
- for (r = rt_hash_table[i]; r; r = r->u.rt_next) {
+ for (i = rt_hash_mask; i>=0; i--) {
+ read_lock_bh(&rt_hash_table[i].lock);
+ for (r = rt_hash_table[i].chain; r; r = r->u.rt_next) {
/*
* Spin through entries until we are ready
*/
r->rt_spec_dst);
sprintf(buffer+len,"%-127s\n",temp);
len += 128;
- if (pos >= offset+length)
+ if (pos >= offset+length) {
+ read_unlock_bh(&rt_hash_table[i].lock);
goto done;
+ }
}
+ read_unlock_bh(&rt_hash_table[i].lock);
}
done:
- read_unlock_bh(&rt_hash_lock);
-
*start = buffer+len-(pos-offset);
len = pos-offset;
if (len>length)
/* This runs via a timer and thus is always in BH context. */
static void rt_check_expire(unsigned long dummy)
{
- int i;
+ int i, t;
static int rover;
struct rtable *rth, **rthp;
unsigned long now = jiffies;
- for (i=0; i<RT_HASH_DIVISOR/5; i++) {
+ i = rover;
+
+ for (t=(ip_rt_gc_interval<<rt_hash_log); t>=0; t -= ip_rt_gc_timeout) {
unsigned tmo = ip_rt_gc_timeout;
- rover = (rover + 1) & (RT_HASH_DIVISOR-1);
- rthp = &rt_hash_table[rover];
+ i = (i + 1) & rt_hash_mask;
+ rthp = &rt_hash_table[i].chain;
- write_lock(&rt_hash_lock);
+ write_lock(&rt_hash_table[i].lock);
while ((rth = *rthp) != NULL) {
if (rth->u.dst.expires) {
- /* Entrie is expired even if it is in use */
+ /* Entry is expired even if it is in use */
if ((long)(now - rth->u.dst.expires) <= 0) {
tmo >>= 1;
rthp = &rth->u.rt_next;
*rthp = rth->u.rt_next;
rt_free(rth);
}
- write_unlock(&rt_hash_lock);
+ write_unlock(&rt_hash_table[i].lock);
/* Fallback loop breaker. */
if ((jiffies - now) > 0)
break;
}
- rt_periodic_timer.expires = now + ip_rt_gc_interval;
- add_timer(&rt_periodic_timer);
+ rover = i;
+ mod_timer(&rt_periodic_timer, now + ip_rt_gc_interval);
}
/* This can run from both BH and non-BH contexts, the latter
rt_deadline = 0;
- for (i=0; i<RT_HASH_DIVISOR; i++) {
- write_lock_bh(&rt_hash_lock);
- rth = rt_hash_table[i];
- rt_hash_table[i] = NULL;
- write_unlock_bh(&rt_hash_lock);
+ for (i=rt_hash_mask; i>=0; i--) {
+ write_lock_bh(&rt_hash_table[i].lock);
+ rth = rt_hash_table[i].chain;
+ if (rth)
+ rt_hash_table[i].chain = NULL;
+ write_unlock_bh(&rt_hash_table[i].lock);
for (; rth; rth=next) {
next = rth->u.rt_next;
if (rt_deadline == 0)
rt_deadline = now + ip_rt_max_delay;
- rt_flush_timer.expires = now + delay;
- add_timer(&rt_flush_timer);
+ mod_timer(&rt_flush_timer, now+delay);
spin_unlock_bh(&rt_flush_lock);
}
return 0;
/* Calculate number of entries, which we want to expire now. */
- goal = atomic_read(&ipv4_dst_ops.entries) - RT_HASH_DIVISOR*ip_rt_gc_elasticity;
+ goal = atomic_read(&ipv4_dst_ops.entries) - (ip_rt_gc_elasticity<<rt_hash_log);
if (goal <= 0) {
if (equilibrium < ipv4_dst_ops.gc_thresh)
equilibrium = ipv4_dst_ops.gc_thresh;
goal = atomic_read(&ipv4_dst_ops.entries) - equilibrium;
if (goal > 0) {
- equilibrium += min(goal/2, RT_HASH_DIVISOR);
+ equilibrium += min(goal/2, rt_hash_mask+1);
goal = atomic_read(&ipv4_dst_ops.entries) - equilibrium;
}
} else {
/* We are in dangerous area. Try to reduce cache really
* aggressively.
*/
- goal = max(goal/2, RT_HASH_DIVISOR);
+ goal = max(goal/2, rt_hash_mask+1);
equilibrium = atomic_read(&ipv4_dst_ops.entries) - goal;
}
do {
int i, k;
- /* The write lock is held during the entire hash
- * traversal to ensure consistent state of the rover.
- */
- write_lock_bh(&rt_hash_lock);
- for (i=0, k=rover; i<RT_HASH_DIVISOR; i++) {
+ for (i=rt_hash_mask, k=rover; i>=0; i--) {
unsigned tmo = expire;
- k = (k + 1) & (RT_HASH_DIVISOR-1);
- rthp = &rt_hash_table[k];
+ k = (k + 1) & rt_hash_mask;
+ rthp = &rt_hash_table[k].chain;
+ write_lock_bh(&rt_hash_table[k].lock);
while ((rth = *rthp) != NULL) {
if (!rt_may_expire(rth, tmo, expire)) {
tmo >>= 1;
rt_free(rth);
goal--;
}
+ write_unlock_bh(&rt_hash_table[k].lock);
if (goal <= 0)
break;
}
rover = k;
- write_unlock_bh(&rt_hash_lock);
if (goal <= 0)
goto work_done;
int attempts = !in_interrupt();
restart:
- rthp = &rt_hash_table[hash];
+ rthp = &rt_hash_table[hash].chain;
- write_lock_bh(&rt_hash_lock);
+ write_lock_bh(&rt_hash_table[hash].lock);
while ((rth = *rthp) != NULL) {
if (memcmp(&rth->key, &rt->key, sizeof(rt->key)) == 0) {
/* Put it first */
*rthp = rth->u.rt_next;
- rth->u.rt_next = rt_hash_table[hash];
- rt_hash_table[hash] = rth;
+ rth->u.rt_next = rt_hash_table[hash].chain;
+ rt_hash_table[hash].chain = rth;
rth->u.dst.__use++;
dst_hold(&rth->u.dst);
rth->u.dst.lastuse = now;
- write_unlock_bh(&rt_hash_lock);
+ write_unlock_bh(&rt_hash_table[hash].lock);
rt_drop(rt);
*rp = rth;
*/
if (rt->rt_type == RTN_UNICAST || rt->key.iif == 0) {
if (!arp_bind_neighbour(&rt->u.dst)) {
- write_unlock_bh(&rt_hash_lock);
+ write_unlock_bh(&rt_hash_table[hash].lock);
/* Neighbour tables are full and nothing
can be released. Try to shrink route cache,
}
}
- rt->u.rt_next = rt_hash_table[hash];
+ rt->u.rt_next = rt_hash_table[hash].chain;
#if RT_CACHE_DEBUG >= 2
if (rt->u.rt_next) {
struct rtable * trt;
printk("\n");
}
#endif
- rt_hash_table[hash] = rt;
- write_unlock_bh(&rt_hash_lock);
+ rt_hash_table[hash].chain = rt;
+ write_unlock_bh(&rt_hash_table[hash].lock);
*rp = rt;
return 0;
}
{
struct rtable **rthp;
- write_lock_bh(&rt_hash_lock);
+ write_lock_bh(&rt_hash_table[hash].lock);
ip_rt_put(rt);
- for (rthp = &rt_hash_table[hash]; *rthp; rthp = &(*rthp)->u.rt_next) {
+ for (rthp = &rt_hash_table[hash].chain; *rthp; rthp = &(*rthp)->u.rt_next) {
if (*rthp == rt) {
*rthp = rt->u.rt_next;
rt_free(rt);
break;
}
}
- write_unlock_bh(&rt_hash_lock);
+ write_unlock_bh(&rt_hash_table[hash].lock);
}
void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,
for (k=0; k<2; k++) {
unsigned hash = rt_hash_code(daddr, skeys[i]^(ikeys[k]<<5), tos);
- rthp=&rt_hash_table[hash];
+ rthp=&rt_hash_table[hash].chain;
- read_lock(&rt_hash_lock);
+ read_lock(&rt_hash_table[hash].lock);
while ( (rth = *rthp) != NULL) {
struct rtable *rt;
break;
dst_clone(&rth->u.dst);
- read_unlock(&rt_hash_lock);
+ read_unlock(&rt_hash_table[hash].lock);
rt = dst_alloc(&ipv4_dst_ops);
if (rt == NULL) {
ip_rt_put(rt);
goto do_next;
}
- read_unlock(&rt_hash_lock);
+ read_unlock(&rt_hash_table[hash].lock);
do_next:
;
}
for (i=0; i<2; i++) {
unsigned hash = rt_hash_code(daddr, skeys[i], tos);
- read_lock(&rt_hash_lock);
- for (rth = rt_hash_table[hash]; rth; rth = rth->u.rt_next) {
+ read_lock(&rt_hash_table[hash].lock);
+ for (rth = rt_hash_table[hash].chain; rth; rth = rth->u.rt_next) {
if (rth->key.dst == daddr &&
rth->key.src == skeys[i] &&
rth->rt_dst == daddr &&
}
}
}
- read_unlock(&rt_hash_lock);
+ read_unlock(&rt_hash_table[hash].lock);
}
return est_mtu ? : new_mtu;
}
tos &= IPTOS_TOS_MASK;
hash = rt_hash_code(daddr, saddr^(iif<<5), tos);
- read_lock_bh(&rt_hash_lock);
- for (rth=rt_hash_table[hash]; rth; rth=rth->u.rt_next) {
+ read_lock(&rt_hash_table[hash].lock);
+ for (rth=rt_hash_table[hash].chain; rth; rth=rth->u.rt_next) {
if (rth->key.dst == daddr &&
rth->key.src == saddr &&
rth->key.iif == iif &&
rth->u.dst.lastuse = jiffies;
dst_hold(&rth->u.dst);
rth->u.dst.__use++;
- read_unlock_bh(&rt_hash_lock);
+ read_unlock(&rt_hash_table[hash].lock);
skb->dst = (struct dst_entry*)rth;
return 0;
}
}
- read_unlock_bh(&rt_hash_lock);
+ read_unlock(&rt_hash_table[hash].lock);
/* Multicast recognition logic is moved from route cache to here.
The problem was that too many Ethernet cards have broken/missing
hash = rt_hash_code(daddr, saddr^(oif<<5), tos);
- read_lock_bh(&rt_hash_lock);
- for (rth=rt_hash_table[hash]; rth; rth=rth->u.rt_next) {
+ read_lock_bh(&rt_hash_table[hash].lock);
+ for (rth=rt_hash_table[hash].chain; rth; rth=rth->u.rt_next) {
if (rth->key.dst == daddr &&
rth->key.src == saddr &&
rth->key.iif == 0 &&
rth->u.dst.lastuse = jiffies;
dst_hold(&rth->u.dst);
rth->u.dst.__use++;
- read_unlock_bh(&rt_hash_lock);
+ read_unlock_bh(&rt_hash_table[hash].lock);
*rp = rth;
return 0;
}
}
- read_unlock_bh(&rt_hash_lock);
+ read_unlock_bh(&rt_hash_table[hash].lock);
return ip_route_output_slow(rp, daddr, saddr, tos, oif);
}
return -ENODEV;
skb->protocol = __constant_htons(ETH_P_IP);
skb->dev = dev;
+ local_bh_disable();
err = ip_route_input(skb, dst, src, rtm->rtm_tos, dev);
+ local_bh_enable();
rt = (struct rtable*)skb->dst;
if (!err && rt->u.dst.error)
err = -rt->u.dst.error;
s_h = cb->args[0];
s_idx = idx = cb->args[1];
- for (h=0; h < RT_HASH_DIVISOR; h++) {
+ for (h=0; h <= rt_hash_mask; h++) {
if (h < s_h) continue;
if (h > s_h)
s_idx = 0;
- read_lock_bh(&rt_hash_lock);
- for (rt = rt_hash_table[h], idx = 0; rt; rt = rt->u.rt_next, idx++) {
+ read_lock_bh(&rt_hash_table[h].lock);
+ for (rt = rt_hash_table[h].chain, idx = 0; rt; rt = rt->u.rt_next, idx++) {
if (idx < s_idx)
continue;
skb->dst = dst_clone(&rt->u.dst);
if (rt_fill_info(skb, NETLINK_CB(cb->skb).pid,
cb->nlh->nlmsg_seq, RTM_NEWROUTE, 1) <= 0) {
dst_release(xchg(&skb->dst, NULL));
- read_unlock_bh(&rt_hash_lock);
+ read_unlock_bh(&rt_hash_table[h].lock);
goto done;
}
dst_release(xchg(&skb->dst, NULL));
}
- read_unlock_bh(&rt_hash_lock);
+ read_unlock_bh(&rt_hash_table[h].lock);
}
done:
#endif
#endif
-
void __init ip_rt_init(void)
{
+ int i, order, goal;
+
ipv4_dst_ops.kmem_cachep = kmem_cache_create("ip_dst_cache",
sizeof(struct rtable),
0, SLAB_HWCACHE_ALIGN,
NULL, NULL);
-
+
+ if (!ipv4_dst_ops.kmem_cachep)
+ panic("IP: failed to allocate ip_dst_cache\n");
+
+ goal = num_physpages >> (26 - PAGE_SHIFT);
+
+ for (order = 0; (1UL << order) < goal; order++)
+ /* NOTHING */;
+
+ do {
+ rt_hash_mask = (1UL << order) * PAGE_SIZE /
+ sizeof(struct rt_hash_bucket);
+ while (rt_hash_mask & (rt_hash_mask-1))
+ rt_hash_mask--;
+ rt_hash_table = (struct rt_hash_bucket *)
+ __get_free_pages(GFP_ATOMIC, order);
+ } while (rt_hash_table == NULL && --order > 0);
+
+ if (!rt_hash_table)
+ panic("Failed to allocate IP route cache hash table\n");
+
+ printk("IP: routing cache hash table of %u buckets, %dKbytes\n",
+ rt_hash_mask, (rt_hash_mask*sizeof(struct rt_hash_bucket))/1024);
+
+ for (rt_hash_log=0; (1<<rt_hash_log) != rt_hash_mask; rt_hash_log++)
+ /* NOTHING */;
+
+ rt_hash_mask--;
+ for (i = 0; i <= rt_hash_mask; i++) {
+ rt_hash_table[i].lock = RW_LOCK_UNLOCKED;
+ rt_hash_table[i].chain = NULL;
+ }
+
+ ipv4_dst_ops.gc_thresh = (rt_hash_mask+1);
+ ip_rt_max_size = (rt_hash_mask+1)*16;
+
devinet_init();
ip_fib_init();
+
+ rt_flush_timer.function = rt_run_flush;
rt_periodic_timer.function = rt_check_expire;
+
/* All the timers, started at system startup tend
to synchronize. Perturb it a bit.
*/
*
* The User Datagram Protocol (UDP).
*
- * Version: $Id: udp.c,v 1.75 1999/12/15 22:39:34 davem Exp $
+ * Version: $Id: udp.c,v 1.76 2000/01/05 21:27:51 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
return(0);
}
-#ifndef HAVE_CSUM_COPY_USER
-#undef CONFIG_UDP_DELAY_CSUM
-#endif
-
/*
* This should be easy, if there is something there we
* return it, otherwise we block.
*
* Based on linux/ipv4/udp.c
*
- * $Id: udp.c,v 1.46 1999/12/15 22:40:03 davem Exp $
+ * $Id: udp.c,v 1.47 2000/01/05 21:27:54 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
inet_sock_release(sk);
}
-#ifndef HAVE_CSUM_COPY_USER
-#undef CONFIG_UDP_DELAY_CSUM
-#endif
-
/*
* This should be easy, if there is something there we
* return it, otherwise we block.
* Revision Date: February 9, 1993
*
* Developers:
- * Jay Schulist <Jay.Schulist@spacs.k12.wi.us>
+ * Jay Schulist <jschlst@turbolinux.com>
* Jim Freeman <jfree@caldera.com>
*
* Changes:
* Status: Stable
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun May 31 10:12:43 1998
- * Modified at: Fri Dec 17 22:37:53 1999
+ * Modified at: Sat Dec 25 21:10:23 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.
*
*
********************************************************************/
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/socket.h>
#include <linux/sockios.h>
}
/*
- * Function irda_get_value_confirm (obj_id, value, priv)
+ * Function irda_getvalue_confirm (obj_id, value, priv)
*
* Got answer from remote LM-IAS
*
*/
-static void irda_get_value_confirm(int result, __u16 obj_id,
- struct ias_value *value, void *priv)
+static void irda_getvalue_confirm(int result, __u16 obj_id,
+ struct ias_value *value, void *priv)
{
struct irda_sock *self;
iriap_close(self->iriap);
self->iriap = NULL;
+ self->errno = result;
+
/* Check if request succeeded */
if (result != IAS_SUCCESS) {
IRDA_DEBUG(0, __FUNCTION__ "(), IAS query failed!\n");
- self->errno = result;
-
/* Wake up any processes waiting for result */
wake_up_interruptible(&self->ias_wait);
}
self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
- irda_get_value_confirm);
+ irda_getvalue_confirm);
/* Query remote LM-IAS */
iriap_getvaluebyclass_request(self->iriap, self->saddr, self->daddr,
irias_add_octseq_attrib(
ias_obj,
ias_opt.irda_attrib_name,
- ias_opt.attribute.irda_attrib_octet_seq.OctetSeq,
+ ias_opt.attribute.irda_attrib_octet_seq.octet_seq,
ias_opt.attribute.irda_attrib_octet_seq.len);
break;
case IAS_STRING:
}
/*
- * Function irda_simple_get_value_confirm (obj_id, value, priv)
+ * Function irda_simple_getvalue_confirm (obj_id, value, priv)
*
* Got answer from remote LM-IAS, just copy object to requester...
*
* Note : duplicate from above, but we need our own version that
* doesn't touch the dtsap_sel and save the full value structure...
*/
-static void irda_simple_get_value_confirm(int result, __u16 obj_id,
+static void irda_simple_getvalue_confirm(int result, __u16 obj_id,
struct ias_value *value, void *priv)
{
struct irda_sock *self;
if (result != IAS_SUCCESS) {
IRDA_DEBUG(0, __FUNCTION__ "(), IAS query failed!\n");
- self->errno = result;
+ self->errno = -EHOSTUNREACH;
/* Wake up any processes waiting for result */
wake_up_interruptible(&self->ias_wait);
/* Clone the object (so the requester can free it) */
self->ias_result = kmalloc(sizeof(struct ias_value), GFP_ATOMIC);
memcpy(self->ias_result, value, sizeof(struct ias_value));
+ irias_delete_value(value);
+
+ self->errno = 0;
/* Wake up any processes waiting for result */
wake_up_interruptible(&self->ias_wait);
struct ias_value *ias_value)
{
/* Look at the type */
- switch(ias_value->type) {
+ switch (ias_value->type) {
case IAS_INTEGER:
/* Copy the integer */
ias_opt->attribute.irda_attrib_int = ias_value->t.integer;
/* Set length */
ias_opt->attribute.irda_attrib_octet_seq.len = ias_value->len;
/* Copy over */
- memcpy(ias_opt->attribute.irda_attrib_octet_seq.OctetSeq,
+ memcpy(ias_opt->attribute.irda_attrib_octet_seq.octet_seq,
ias_value->t.oct_seq, ias_value->len);
break;
case IAS_STRING:
default :
return -EINVAL;
}
-
+
/* Copy type over */
ias_opt->irda_attrib_type = ias_value->type;
-
+
return 0;
}
struct irda_ias_set ias_opt; /* IAS get/query params */
struct ias_object * ias_obj; /* Object in IAS */
struct ias_attrib * ias_attr; /* Attribute in IAS object */
- int daddr = 0; /* Destination address for IAS queries */
int val = 0;
int len = 0;
int err;
if (copy_from_user((char *) &ias_opt, (char *)optval, len))
return -EFAULT;
- /* Check the destination address requested */
- daddr = ias_opt.attribute.irda_attrib_int;
- if(self->daddr != DEV_ADDR_ANY) {
- /* If we are connected, we must use the correct
- * destination address (or leave it unspecified) */
- if((daddr != DEV_ADDR_ANY) || (daddr != self->daddr))
- return -EINVAL;
- daddr = self->daddr;
- } else {
- /* If we are not connected, we must specify a valid
- * destination address */
- if(daddr == DEV_ADDR_ANY)
- return -EINVAL;
- }
-
/* Check that we can proceed with IAP */
if (self->iriap) {
WARNING(__FUNCTION__
}
self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
- irda_simple_get_value_confirm);
+ irda_simple_getvalue_confirm);
+
+ /* Treat unexpected signals as disconnect */
+ self->errno = -EHOSTUNREACH;
/* Query remote LM-IAS */
- self->errno = 0;
- iriap_getvaluebyclass_request(self->iriap, self->saddr,
- daddr,
+ iriap_getvaluebyclass_request(self->iriap,
+ self->saddr, self->daddr,
ias_opt.irda_class_name,
ias_opt.irda_attrib_name);
/* Wait for answer */
interruptible_sleep_on(&self->ias_wait);
/* Check what happened */
- if(self->errno)
- return(self->errno);
+ if (self->errno)
+ return (self->errno);
/* Translate from internal to user structure */
err = irda_extract_ias_value(&ias_opt, self->ias_result);
- kfree(self->ias_result); /* Cleanup (need to be *here*) */
- if(err)
+ if (self->ias_result)
+ kfree(self->ias_result);
+ if (err)
return err;
/* Copy reply to the user */
default:
return -ENOPROTOOPT;
}
-
+
return 0;
}
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Jun 6 20:37:34 1999
- * Modified at: Thu Dec 16 21:15:26 1999
+ * Modified at: Tue Dec 21 13:26:41 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1999 Dag Brattli, All Rights Reserved.
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Jun 6 21:00:56 1999
- * Modified at: Thu Dec 16 22:07:37 1999
+ * Modified at: Tue Jan 4 14:12:06 2000
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: serial.c and previous IrCOMM work by Takahide Higuchi
*
- * 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
}
if (self->flags & ASYNC_CALLOUT_ACTIVE) {
- if (self->normal_termios.c_cflag & CLOCAL)
+ if (self->normal_termios.c_cflag & CLOCAL) {
IRDA_DEBUG(1, __FUNCTION__ "(), doing CLOCAL!\n");
do_clocal = 1;
+ }
} else {
- if (tty->termios->c_cflag & CLOCAL)
+ if (tty->termios->c_cflag & CLOCAL) {
IRDA_DEBUG(1, __FUNCTION__ "(), doing CLOCAL!\n");
do_clocal = 1;
+ }
}
/* Wait for carrier detect and the line to become
/* Check if this is a "normal" ircomm device, or an irlpt device */
if (line < 0x10) {
self->service_type = IRCOMM_3_WIRE | IRCOMM_9_WIRE;
+ self->settings.service_type = IRCOMM_9_WIRE; /* Default */
IRDA_DEBUG(2, __FUNCTION__ "(), IrCOMM device\n");
} else {
IRDA_DEBUG(2, __FUNCTION__ "(), IrLPT device\n");
self->service_type = IRCOMM_3_WIRE_RAW;
+ self->settings.service_type = IRCOMM_3_WIRE_RAW; /* Default */
}
ret = ircomm_tty_startup(self);
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Jun 5 17:42:00 1999
- * Modified at: Wed Dec 15 23:32:08 1999
+ * Modified at: Tue Jan 4 14:20:49 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
del_timer(&self->watchdog_timer);
- /*
+ /*
* IrCOMM link is now up, and if we are not using hardware
- * flow-control, then declare the hardware as running. Otherwise
- * the client will have to wait for the CTS to be set.
+ * flow-control, then declare the hardware as running. Otherwise we
+ * will have to wait for the peer device (DCE) to raise the CTS
+ * line.
*/
if (self->flags & ASYNC_CTS_FLOW) {
IRDA_DEBUG(0, __FUNCTION__ "(), waiting for CTS ...\n");
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Thu Jun 10 14:39:09 1999
- * Modified at: Tue Dec 14 18:08:09 1999
+ * Modified at: Wed Jan 5 14:45:43 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
/* CTS flow control flag and modem status interrupts */
if (cflag & CRTSCTS) {
self->flags |= ASYNC_CTS_FLOW;
- /* self->settings.flow_control |= IRCOMM_RTS_CTS_IN; */
- } else
+ self->settings.flow_control |= IRCOMM_RTS_CTS_IN;
+ } else {
self->flags &= ~ASYNC_CTS_FLOW;
-
+ self->settings.flow_control &= ~IRCOMM_RTS_CTS_IN;
+ }
if (cflag & CLOCAL)
self->flags &= ~ASYNC_CHECK_CD;
else
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Oct 9 09:22:27 1999
- * Modified at: Tue Dec 21 21:53:45 1999
+ * Modified at: Wed Jan 5 14:17:16 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
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Thu Aug 21 00:02:07 1997
- * Modified at: Fri Dec 17 15:58:16 1999
+ * Modified at: Sat Dec 25 16:42:42 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
{
struct ias_object *obj;
struct iriap_cb *server;
+ __u8 oct_seq[6];
__u16 hints;
/* Allocate master array */
* Register some default services for IrLMP
*/
hints = irlmp_service_to_hint(S_COMPUTER);
- /*hints |= irlmp_service_to_hint(S_PNP);*/
service_handle = irlmp_register_service(hints);
- /*
- * Register the Device object with LM-IAS
- */
+ /* Register the Device object with LM-IAS */
obj = irias_new_object("Device", IAS_DEVICE_ID);
irias_add_string_attrib(obj, "DeviceName", "Linux");
+
+ oct_seq[0] = 0x01; /* Version 1 */
+ oct_seq[1] = 0x00; /* IAS support bits */
+ oct_seq[2] = 0x00; /* LM-MUX support bits */
+#ifdef CONFIG_IRDA_ULTRA
+ oct_seq[2] |= 0x04; /* Connectionless Data support */
+#endif
+ irias_add_octseq_attrib(obj, "IrLMPSupport", oct_seq, 3);
irias_insert_object(obj);
/*
tmp_be16 = cpu_to_be16(obj_id);
memcpy(fp+n, &tmp_be16, 2); n += 2;
- switch(value->type) {
+ switch (value->type) {
case IAS_STRING:
skb_put(skb, 3 + value->len);
fp[n++] = value->type;
irlmp_data_request(self->lsap, skb);
}
+void iriap_connect_request(struct iriap_cb *self)
+{
+ int ret;
+
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == IAS_MAGIC, return;);
+
+ ret = irlmp_connect_request(self->lsap, LSAP_IAS,
+ self->saddr, self->daddr,
+ NULL, NULL);
+ if (ret < 0) {
+ IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n");
+ self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
+ }
+}
+
/*
* Function iriap_connect_confirm (handle, skb)
*
del_timer(&self->watchdog_timer);
- iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, NULL);
-
- dev_kfree_skb(userdata);
+ iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, userdata);
}
/*
* no to use self anymore after calling confirm
*/
if (self->confirm)
- self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
+ self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
self->priv);
dev_kfree_skb(skb);
break;
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Thu Aug 21 00:02:07 1997
- * Modified at: Fri Dec 17 15:59:13 1999
+ * Modified at: Sat Dec 25 21:09:47 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>,
static void state_s_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
struct sk_buff *skb)
{
- int ret;
-
ASSERT(self != NULL, return;);
ASSERT(self->magic == IAS_MAGIC, return;);
iriap_next_client_state(self, S_CONNECTING);
ASSERT(self->skb == NULL, return;);
self->skb = skb;
- ret = irlmp_connect_request(self->lsap, LSAP_IAS,
- self->saddr, self->daddr,
- NULL, NULL);
+ iriap_connect_request(self);
break;
case IAP_LM_DISCONNECT_INDICATION:
break;
/*
* Jump to S-Call FSM
*/
- iriap_do_call_event(self, IAP_CALL_REQUEST, NULL);
+ iriap_do_call_event(self, IAP_CALL_REQUEST, skb);
/* iriap_call_request(self, 0,0,0); */
iriap_next_client_state(self, S_CALL);
break;
case IAP_CALL_REQUEST:
skb = self->skb;
self->skb = NULL;
-
+
irlmp_data_request(self->lsap, skb);
iriap_next_call_state(self, S_OUTSTANDING);
break;
default:
IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %d\n", event);
+ if (skb)
+ dev_kfree_skb(skb);
break;
}
}
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 31 20:14:37 1997
- * Modified at: Sun Oct 31 19:41:55 1999
+ * Modified at: Sun Dec 26 21:52:24 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
ASSERT(self != NULL, return -1;);
- switch(event) {
+ switch (event) {
case IRLAN_CONNECT_COMPLETE:
/* Send getinfo cmd */
irlan_get_provider_info(self);
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 31 20:14:37 1997
- * Modified at: Thu Dec 16 21:16:14 1999
+ * Modified at: Sun Dec 26 21:53:10 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1997, 1999 Dag Brattli <dagb@cs.uit.no>,
frame[0] = CMD_GET_PROVIDER_INFO;
frame[1] = 0x00; /* Zero parameters */
- /* irttp_data_request(self->client.tsap_ctrl, skb); */
irlan_ctrl_data_request(self, skb);
}
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Thu Oct 15 08:37:58 1998
- * Modified at: Thu Dec 16 21:21:53 1999
+ * Modified at: Thu Nov 4 14:50:52 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
* slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
* Status: Stable
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Mon Aug 4 20:40:53 1997
- * Modified at: Thu Dec 16 22:59:17 1999
+ * Modified at: Tue Dec 14 09:26:44 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved.
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sat Aug 16 00:59:29 1997
- * Modified at: Tue Dec 21 11:27:22 1999
+ * Modified at: Sat Dec 25 21:07:57 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
* Send response. This skb will not be sent out again, and
* will only be used to send out the same info as the cmd
*/
- irlap_send_test_frame(self, info->daddr, skb);
+ irlap_send_test_frame(self, CBROADCAST, info->daddr, skb);
dev_kfree_skb(skb);
break;
case RECV_TEST_RSP:
irlap_start_wd_timer(self, self->wd_timeout);
/* Send response (info will be copied) */
- irlap_send_test_frame(self, info->daddr, skb);
+ irlap_send_test_frame(self, self->caddr, info->daddr, skb);
dev_kfree_skb(skb);
break;
default:
IRDA_DEBUG(1, __FUNCTION__ "(), Unknown event %d, (%s)\n",
event, irlap_event[event]);
-
if (skb)
dev_kfree_skb(skb);
* Status: Stable
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Tue Aug 19 10:27:26 1997
- * Modified at: Tue Dec 21 11:19:19 1999
+ * Modified at: Wed Jan 5 08:59:04 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
text = (char *) &discovery_info[2];
}
/*
- * Terminate string, should be safe since this is where the
+ * Terminate info string, should be safe since this is where the
* FCS bytes resides.
*/
skb->data[skb->len] = '\0';
* Send a test frame response
*
*/
-void irlap_send_test_frame(struct irlap_cb *self, __u32 daddr,
+void irlap_send_test_frame(struct irlap_cb *self, __u8 caddr, __u32 daddr,
struct sk_buff *cmd)
{
struct sk_buff *skb;
if (!skb)
return;
- skb_put(skb, sizeof(struct test_frame));
+ /* Broadcast frames must include saddr and daddr fields */
+ if (caddr == CBROADCAST) {
+ frame = (struct test_frame *)
+ skb_put(skb, sizeof(struct test_frame));
- frame = (struct test_frame *) skb->data;
-
- /* Build header */
- if (self->state == LAP_NDM)
- frame->caddr = CBROADCAST; /* Send response */
- else
- frame->caddr = self->caddr;
+ /* Insert the swapped addresses */
+ frame->saddr = cpu_to_le32(self->saddr);
+ frame->daddr = cpu_to_le32(daddr);
+ } else
+ frame = (struct test_frame *) skb_put(skb, LAP_MAX_HEADER);
+ frame->caddr = caddr;
frame->control = TEST_RSP;
- /* Insert the swapped addresses */
- frame->saddr = cpu_to_le32(self->saddr);
- frame->daddr = cpu_to_le32(daddr);
-
/* Copy info */
info = skb_put(skb, cmd->len);
memcpy(info, cmd->data, cmd->len);
IRDA_DEBUG(2, __FUNCTION__ "()\n");
- if (skb->len < sizeof(struct test_frame)) {
- IRDA_DEBUG(0, __FUNCTION__ "() test frame to short!\n");
- dev_kfree_skb(skb);
- return;
- }
-
frame = (struct test_frame *) skb->data;
+
+ /* Broadcast frames must carry saddr and daddr fields */
+ if (info->caddr == CBROADCAST) {
+ if (skb->len < sizeof(struct test_frame)) {
+ IRDA_DEBUG(0, __FUNCTION__
+ "() test frame to short!\n");
+ dev_kfree_skb(skb);
+ return;
+ }
+
+ /* Read and swap addresses */
+ info->daddr = le32_to_cpu(frame->saddr);
+ info->saddr = le32_to_cpu(frame->daddr);
- /* Read and swap addresses */
- info->daddr = le32_to_cpu(frame->saddr);
- info->saddr = le32_to_cpu(frame->daddr);
-
- /* Make sure frame is addressed to us */
- if ((info->saddr != self->saddr) && (info->saddr != BROADCAST)) {
- dev_kfree_skb(skb);
- return;
+ /* Make sure frame is addressed to us */
+ if ((info->saddr != self->saddr) &&
+ (info->saddr != BROADCAST)) {
+ dev_kfree_skb(skb);
+ return;
+ }
}
if (command)
case DM_RSP:
irlap_do_event(self, RECV_DM_RSP, skb, &info);
break;
- case DISC_CMD: /* And RD_RSP */
+ case DISC_CMD: /* And RD_RSP since they have the same value */
irlap_recv_disc_frame(self, skb, &info, command);
break;
case TEST_CMD:
* Status: Stable.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 17 20:54:32 1997
- * Modified at: Thu Dec 16 22:59:40 1999
+ * Modified at: Wed Jan 5 11:26:03 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
/*
* Function irlmp_init (void)
*
- * Create (allocate) the main IrLMP structure and the pointer array
- * which will contain pointers to each instance of a LSAP.
+ * Create (allocate) the main IrLMP structure
+ *
*/
int __init irlmp_init(void)
{
/* Initialize the irlmp structure. */
- if ( irlmp == NULL) {
- irlmp = kmalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
- if ( irlmp == NULL)
- return -ENOMEM;
- }
- memset( irlmp, 0, sizeof(struct irlmp_cb));
+ irlmp = kmalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
+ if (irlmp == NULL)
+ return -ENOMEM;
+ memset(irlmp, 0, sizeof(struct irlmp_cb));
irlmp->magic = LMP_MAGIC;
+ spin_lock_init(&irlmp->lock);
irlmp->clients = hashbin_new(HB_GLOBAL);
irlmp->services = hashbin_new(HB_GLOBAL);
* device with the given daddr
*/
if (!saddr) {
- discovery = hashbin_find(irlmp->cachelog, daddr, NULL);
- if (discovery)
+ if (daddr != DEV_ADDR_ANY)
+ discovery = hashbin_find(irlmp->cachelog, daddr, NULL);
+ else {
+ IRDA_DEBUG(2, __FUNCTION__ "(), no daddr\n");
+ discovery = (discovery_t *)
+ hashbin_get_first(irlmp->cachelog);
+ }
+
+ if (discovery) {
saddr = discovery->saddr;
+ daddr = discovery->daddr;
+ }
}
lap = hashbin_find(irlmp->links, saddr, NULL);
if (lap == NULL) {
*
********************************************************************/
-#include <linux/config.h>
#include <linux/kernel.h>
#include <net/irda/irda.h>
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Mon Dec 15 13:55:39 1997
- * Modified at: Tue Dec 21 21:39:31 1999
+ * Modified at: Wed Jan 5 15:12:41 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
struct irmanager_event event;
/* Make sure irmanager is running */
- if ( !irda.in_use) {
- printk( KERN_ERR "irmanager is not running!\n");
+ if (!irda.in_use) {
return;
}
/* Make sure irmanager is running */
if (!irda.in_use) {
- printk( KERN_ERR "irmanager is not running!\n");
return;
}
* Status: Stable
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 31 20:14:31 1997
- * Modified at: Thu Dec 16 23:00:03 1999
+ * Modified at: Wed Jan 5 11:31:27 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
return NULL;
}
memset(self, 0, sizeof(struct tsap_cb));
+ spin_lock_init(&self->lock);
init_timer(&self->todo_timer);