Merge with master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git

This commit is contained in:
David Woodhouse 2005-06-20 15:51:24 +01:00
commit df5179854b
311 changed files with 26114 additions and 24393 deletions

View File

@ -8,7 +8,7 @@
DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \
kernel-hacking.xml kernel-locking.xml deviceiobook.xml \
procfs-guide.xml writing_usb_driver.xml scsidrivers.xml \
procfs-guide.xml writing_usb_driver.xml \
sis900.xml kernel-api.xml journal-api.xml lsm.xml usb.xml \
gadget.xml libata.xml mtdnand.xml librs.xml

View File

@ -1,193 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="scsidrivers">
<bookinfo>
<title>SCSI Subsystem Interfaces</title>
<authorgroup>
<author>
<firstname>Douglas</firstname>
<surname>Gilbert</surname>
<affiliation>
<address>
<email>dgilbert@interlog.com</email>
</address>
</affiliation>
</author>
</authorgroup>
<pubdate>2003-08-11</pubdate>
<copyright>
<year>2002</year>
<year>2003</year>
<holder>Douglas Gilbert</holder>
</copyright>
<legalnotice>
<para>
This documentation 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.
</para>
<para>
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.
</para>
<para>
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
</para>
<para>
For more details see the file COPYING in the source
distribution of Linux.
</para>
</legalnotice>
</bookinfo>
<toc></toc>
<chapter id="intro">
<title>Introduction</title>
<para>
This document outlines the interface between the Linux scsi mid level
and lower level drivers. Lower level drivers are variously called HBA
(host bus adapter) drivers, host drivers (HD) or pseudo adapter drivers.
The latter alludes to the fact that a lower level driver may be a
bridge to another IO subsystem (and the "ide-scsi" driver is an example
of this). There can be many lower level drivers active in a running
system, but only one per hardware type. For example, the aic7xxx driver
controls adaptec controllers based on the 7xxx chip series. Most lower
level drivers can control one or more scsi hosts (a.k.a. scsi initiators).
</para>
<para>
This document can been found in an ASCII text file in the linux kernel
source: <filename>Documentation/scsi/scsi_mid_low_api.txt</filename> .
It currently hold a little more information than this document. The
<filename>drivers/scsi/hosts.h</filename> and <filename>
drivers/scsi/scsi.h</filename> headers contain descriptions of members
of important structures for the scsi subsystem.
</para>
</chapter>
<chapter id="driver-struct">
<title>Driver structure</title>
<para>
Traditionally a lower level driver for the scsi subsystem has been
at least two files in the drivers/scsi directory. For example, a
driver called "xyz" has a header file "xyz.h" and a source file
"xyz.c". [Actually there is no good reason why this couldn't all
be in one file.] Some drivers that have been ported to several operating
systems (e.g. aic7xxx which has separate files for generic and
OS-specific code) have more than two files. Such drivers tend to have
their own directory under the drivers/scsi directory.
</para>
<para>
scsi_module.c is normally included at the end of a lower
level driver. For it to work a declaration like this is needed before
it is included:
<programlisting>
static Scsi_Host_Template driver_template = DRIVER_TEMPLATE;
/* DRIVER_TEMPLATE should contain pointers to supported interface
functions. Scsi_Host_Template is defined hosts.h */
#include "scsi_module.c"
</programlisting>
</para>
<para>
The scsi_module.c assumes the name "driver_template" is appropriately
defined. It contains 2 functions:
<orderedlist>
<listitem><para>
init_this_scsi_driver() called during builtin and module driver
initialization: invokes mid level's scsi_register_host()
</para></listitem>
<listitem><para>
exit_this_scsi_driver() called during closedown: invokes
mid level's scsi_unregister_host()
</para></listitem>
</orderedlist>
</para>
<para>
When a new, lower level driver is being added to Linux, the following
files (all found in the drivers/scsi directory) will need some attention:
Makefile, Config.help and Config.in . It is probably best to look at what
an existing lower level driver does in this regard.
</para>
</chapter>
<chapter id="intfunctions">
<title>Interface Functions</title>
!EDocumentation/scsi/scsi_mid_low_api.txt
</chapter>
<chapter id="locks">
<title>Locks</title>
<para>
Each Scsi_Host instance has a spin_lock called Scsi_Host::default_lock
which is initialized in scsi_register() [found in hosts.c]. Within the
same function the Scsi_Host::host_lock pointer is initialized to point
at default_lock with the scsi_assign_lock() function. Thereafter
lock and unlock operations performed by the mid level use the
Scsi_Host::host_lock pointer.
</para>
<para>
Lower level drivers can override the use of Scsi_Host::default_lock by
using scsi_assign_lock(). The earliest opportunity to do this would
be in the detect() function after it has invoked scsi_register(). It
could be replaced by a coarser grain lock (e.g. per driver) or a
lock of equal granularity (i.e. per host). Using finer grain locks
(e.g. per scsi device) may be possible by juggling locks in
queuecommand().
</para>
</chapter>
<chapter id="changes">
<title>Changes since lk 2.4 series</title>
<para>
io_request_lock has been replaced by several finer grained locks. The lock
relevant to lower level drivers is Scsi_Host::host_lock and there is one
per scsi host.
</para>
<para>
The older error handling mechanism has been removed. This means the
lower level interface functions abort() and reset() have been removed.
</para>
<para>
In the 2.4 series the scsi subsystem configuration descriptions were
aggregated with the configuration descriptions from all other Linux
subsystems in the Documentation/Configure.help file. In the 2.5 series,
the scsi subsystem now has its own (much smaller) drivers/scsi/Config.help
file.
</para>
</chapter>
<chapter id="credits">
<title>Credits</title>
<para>
The following people have contributed to this document:
<orderedlist>
<listitem><para>
Mike Anderson <email>andmike@us.ibm.com</email>
</para></listitem>
<listitem><para>
James Bottomley <email>James.Bottomley@steeleye.com</email>
</para></listitem>
<listitem><para>
Patrick Mansfield <email>patmans@us.ibm.com</email>
</para></listitem>
</orderedlist>
</para>
</chapter>
</book>

View File

@ -1,21 +1,21 @@
Generic HDLC layer
Krzysztof Halasa <khc@pm.waw.pl>
January, 2003
Generic HDLC layer currently supports:
- Frame Relay (ANSI, CCITT and no LMI), with ARP support (no InARP).
Normal (routed) and Ethernet-bridged (Ethernet device emulation)
interfaces can share a single PVC.
- raw HDLC - either IP (IPv4) interface or Ethernet device emulation.
- Cisco HDLC,
- PPP (uses syncppp.c),
- X.25 (uses X.25 routines).
1. Frame Relay (ANSI, CCITT, Cisco and no LMI).
- Normal (routed) and Ethernet-bridged (Ethernet device emulation)
interfaces can share a single PVC.
- ARP support (no InARP support in the kernel - there is an
experimental InARP user-space daemon available on:
http://www.kernel.org/pub/linux/utils/net/hdlc/).
2. raw HDLC - either IP (IPv4) interface or Ethernet device emulation.
3. Cisco HDLC.
4. PPP (uses syncppp.c).
5. X.25 (uses X.25 routines).
There are hardware drivers for the following cards:
- C101 by Moxa Technologies Co., Ltd.
- RISCom/N2 by SDL Communications Inc.
- and others, some not in the official kernel.
Generic HDLC is a protocol driver only - it needs a low-level driver
for your particular hardware.
Ethernet device emulation (using HDLC or Frame-Relay PVC) is compatible
with IEEE 802.1Q (VLANs) and 802.1D (Ethernet bridging).
@ -24,7 +24,7 @@ with IEEE 802.1Q (VLANs) and 802.1D (Ethernet bridging).
Make sure the hdlc.o and the hardware driver are loaded. It should
create a number of "hdlc" (hdlc0 etc) network devices, one for each
WAN port. You'll need the "sethdlc" utility, get it from:
http://hq.pm.waw.pl/hdlc/
http://www.kernel.org/pub/linux/utils/net/hdlc/
Compile sethdlc.c utility:
gcc -O2 -Wall -o sethdlc sethdlc.c
@ -52,12 +52,12 @@ Setting interface:
* v35 | rs232 | x21 | t1 | e1 - sets physical interface for a given port
if the card has software-selectable interfaces
loopback - activate hardware loopback (for testing only)
* clock ext - external clock (uses DTE RX and TX clock)
* clock int - internal clock (provides clock signal on DCE clock output)
* clock txint - TX internal, RX external (provides TX clock on DCE output)
* clock txfromrx - TX clock derived from RX clock (TX clock on DCE output)
* rate - sets clock rate in bps (not required for external clock or
for txfromrx)
* clock ext - both RX clock and TX clock external
* clock int - both RX clock and TX clock internal
* clock txint - RX clock external, TX clock internal
* clock txfromrx - RX clock external, TX clock derived from RX clock
* rate - sets clock rate in bps (for "int" or "txint" clock only)
Setting protocol:
@ -79,7 +79,7 @@ Setting protocol:
* x25 - sets X.25 mode
* fr - Frame Relay mode
lmi ansi / ccitt / none - LMI (link management) type
lmi ansi / ccitt / cisco / none - LMI (link management) type
dce - Frame Relay DCE (network) side LMI instead of default DTE (user).
It has nothing to do with clocks!
t391 - link integrity verification polling timer (in seconds) - user
@ -119,13 +119,14 @@ or
If you have a problem with N2 or C101 card, you can issue the "private"
command to see port's packet descriptor rings (in kernel logs):
If you have a problem with N2, C101 or PLX200SYN card, you can issue the
"private" command to see port's packet descriptor rings (in kernel logs):
sethdlc hdlc0 private
The hardware driver has to be build with CONFIG_HDLC_DEBUG_RINGS.
The hardware driver has to be build with #define DEBUG_RINGS.
Attaching this info to bug reports would be helpful. Anyway, let me know
if you have problems using this.
For patches and other info look at http://hq.pm.waw.pl/hdlc/
For patches and other info look at:
<http://www.kernel.org/pub/linux/utils/net/hdlc/>.

View File

@ -47,7 +47,6 @@ ni52 <------------------ Buggy ------------------>
ni65 YES YES YES Software(#)
seeq NO NO NO N/A
sgiseek <------------------ Buggy ------------------>
sk_g16 NO NO YES N/A
smc-ultra YES YES YES Hardware
sunlance YES YES YES Hardware
tulip YES YES YES Hardware

View File

@ -284,9 +284,6 @@ ppp.c:
seeq8005.c: *Not modularized*
(Probes ports: 0x300, 0x320, 0x340, 0x360)
sk_g16.c: *Not modularized*
(Probes ports: 0x100, 0x180, 0x208, 0x220m 0x288, 0x320, 0x328, 0x390)
skeleton.c: *Skeleton*
slhc.c:

View File

@ -1,3 +1,69 @@
Release Date : Mon Mar 07 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
Current Version : 2.20.4.6 (scsi module), 2.20.2.6 (cmm module)
Older Version : 2.20.4.5 (scsi module), 2.20.2.5 (cmm module)
1. Added IOCTL backward compatibility.
Convert megaraid_mm driver to new compat_ioctl entry points.
I don't have easy access to hardware, so only compile tested.
- Signed-off-by:Andi Kleen <ak@muc.de>
2. megaraid_mbox fix: wrong order of arguments in memset()
That, BTW, shows why cross-builds are useful-the only indication of
problem had been a new warning showing up in sparse output on alpha
build (number of exceeding 256 got truncated).
- Signed-off-by: Al Viro
<viro@parcelfarce.linux.theplanet.co.uk>
3. Convert pci_module_init to pci_register_driver
Convert from pci_module_init to pci_register_driver
(from:http://kerneljanitors.org/TODO)
- Signed-off-by: Domen Puncer <domen@coderock.org>
4. Use the pre defined DMA mask constants from dma-mapping.h
Use the DMA_{64,32}BIT_MASK constants from dma-mapping.h when calling
pci_set_dma_mask() or pci_set_consistend_dma_mask(). See
http://marc.theaimsgroup.com/?t=108001993000001&r=1&w=2 for more
details.
Signed-off-by: Tobias Klauser <tklauser@nuerscht.ch>
Signed-off-by: Domen Puncer <domen@coderock.org>
5. Remove SSID checking for Dobson, Lindsay, and Verde based products.
Checking the SSVID/SSID for controllers which have Dobson, Lindsay,
and Verde is unnecessary because device ID has been assigned by LSI
and it is unique value. So, all controllers with these IOPs have to be
supported by the driver regardless SSVID/SSID.
6. Date Thu, 27 Jan 2005 04:31:09 +0100
From Herbert Poetzl <>
Subject RFC: assert_spin_locked() for 2.6
Greetings!
overcautious programming will kill your kernel ;)
ever thought about checking a spin_lock or even
asserting that it must be held (maybe just for
spinlock debugging?) ...
there are several checks present in the kernel
where somebody does a variation on the following:
BUG_ON(!spin_is_locked(&some_lock));
so what's wrong about that? nothing, unless you
compile the code with CONFIG_DEBUG_SPINLOCK but
without CONFIG_SMP ... in which case the BUG()
will kill your kernel ...
maybe it's not advised to make such assertions,
but here is a solution which works for me ...
(compile tested for sh, x86_64 and x86, boot/run
tested for x86 only)
best,
Herbert
- Herbert Poetzl <herbert@13thfloor.at>, Thu, 27 Jan 2005
Release Date : Thu Feb 03 12:27:22 EST 2005 - Seokmann Ju <sju@lsil.com>
Current Version : 2.20.4.5 (scsi module), 2.20.2.5 (cmm module)
Older Version : 2.20.4.4 (scsi module), 2.20.2.4 (cmm module)

View File

@ -0,0 +1,180 @@
README for the SCSI media changer driver
========================================
This is a driver for SCSI Medium Changer devices, which are listed
with "Type: Medium Changer" in /proc/scsi/scsi.
This is for *real* Jukeboxes. It is *not* supported to work with
common small CD-ROM changers, neither one-lun-per-slot SCSI changers
nor IDE drives.
Userland tools available from here:
http://linux.bytesex.org/misc/changer.html
General Information
-------------------
First some words about how changers work: A changer has 2 (possibly
more) SCSI ID's. One for the changer device which controls the robot,
and one for the device which actually reads and writes the data. The
later may be anything, a MOD, a CD-ROM, a tape or whatever. For the
changer device this is a "don't care", he *only* shuffles around the
media, nothing else.
The SCSI changer model is complex, compared to - for example - IDE-CD
changers. But it allows to handle nearly all possible cases. It knows
4 different types of changer elements:
media transport - this one shuffles around the media, i.e. the
transport arm. Also known as "picker".
storage - a slot which can hold a media.
import/export - the same as above, but is accessable from outside,
i.e. there the operator (you !) can use this to
fill in and remove media from the changer.
Sometimes named "mailslot".
data transfer - this is the device which reads/writes, i.e. the
CD-ROM / Tape / whatever drive.
None of these is limited to one: A huge Jukebox could have slots for
123 CD-ROM's, 5 CD-ROM readers (and therefore 6 SCSI ID's: the changer
and each CD-ROM) and 2 transport arms. No problem to handle.
How it is implemented
---------------------
I implemented the driver as character device driver with a NetBSD-like
ioctl interface. Just grabbed NetBSD's header file and one of the
other linux SCSI device drivers as starting point. The interface
should be source code compatible with NetBSD. So if there is any
software (anybody knows ???) which supports a BSDish changer driver,
it should work with this driver too.
Over time a few more ioctls where added, volume tag support for example
wasn't covered by the NetBSD ioctl API.
Current State
-------------
Support for more than one transport arm is not implemented yet (and
nobody asked for it so far...).
I test and use the driver myself with a 35 slot cdrom jukebox from
Grundig. I got some reports telling it works ok with tape autoloaders
(Exabyte, HP and DEC). Some People use this driver with amanda. It
works fine with small (11 slots) and a huge (4 MOs, 88 slots)
magneto-optical Jukebox. Probably with lots of other changers too, most
(but not all :-) people mail me only if it does *not* work...
I don't have any device lists, neither black-list nor white-list. Thus
it is quite useless to ask me whenever a specific device is supported or
not. In theory every changer device which supports the SCSI-2 media
changer command set should work out-of-the-box with this driver. If it
doesn't, it is a bug. Either within the driver or within the firmware
of the changer device.
Using it
--------
This is a character device with major number is 86, so use
"mknod /dev/sch0 c 86 0" to create the special file for the driver.
If the module finds the changer, it prints some messages about the
device [ try "dmesg" if you don't see anything ] and should show up in
/proc/devices. If not.... some changers use ID ? / LUN 0 for the
device and ID ? / LUN 1 for the robot mechanism. But Linux does *not*
look for LUN's other than 0 as default, becauce there are to many
broken devices. So you can try:
1) echo "scsi add-single-device 0 0 ID 1" > /proc/scsi/scsi
(replace ID with the SCSI-ID of the device)
2) boot the kernel with "max_scsi_luns=1" on the command line
(append="max_scsi_luns=1" in lilo.conf should do the trick)
Trouble?
--------
If you insmod the driver with "insmod debug=1", it will be verbose and
prints a lot of stuff to the syslog. Compiling the kernel with
CONFIG_SCSI_CONSTANTS=y improves the quality of the error messages alot
because the kernel will translate the error codes into human-readable
strings then.
You can display these messages with the dmesg command (or check the
logfiles). If you email me some question becauce of a problem with the
driver, please include these messages.
Insmod options
--------------
debug=0/1
Enable debug messages (see above, default: 0).
verbose=0/1
Be verbose (default: 1).
init=0/1
Send INITIALIZE ELEMENT STATUS command to the changer
at insmod time (default: 1).
timeout_init=<seconds>
timeout for the INITIALIZE ELEMENT STATUS command
(default: 3600).
timeout_move=<seconds>
timeout for all other commands (default: 120).
dt_id=<id1>,<id2>,...
dt_lun=<lun1>,<lun2>,...
These two allow to specify the SCSI ID and LUN for the data
transfer elements. You likely don't need this as the jukebox
should provide this information. But some devices don't ...
vendor_firsts=
vendor_counts=
vendor_labels=
These insmod options can be used to tell the driver that there
are some vendor-specific element types. Grundig for example
does this. Some jukeboxes have a printer to label fresh burned
CDs, which is addressed as element 0xc000 (type 5). To tell the
driver about this vendor-specific element, use this:
$ insmod ch \
vendor_firsts=0xc000 \
vendor_counts=1 \
vendor_labels=printer
All three insmod options accept up to four comma-separated
values, this way you can configure the element types 5-8.
You likely need the SCSI specs for the device in question to
find the correct values as they are not covered by the SCSI-2
standard.
Credits
-------
I wrote this driver using the famous mailing-patches-around-the-world
method. With (more or less) help from:
Daniel Moehwald <moehwald@hdg.de>
Dane Jasper <dane@sonic.net>
R. Scott Bailey <sbailey@dsddi.eds.com>
Jonathan Corbet <corbet@lwn.net>
Special thanks go to
Martin Kuehne <martin.kuehne@bnbt.de>
for a old, second-hand (but full functional) cdrom jukebox which I use
to develop/test driver and tools now.
Have fun,
Gerd
--
Gerd Knorr <kraxel@bytesex.org>

View File

@ -936,8 +936,7 @@ Details:
*
* Returns SUCCESS if command aborted else FAILED
*
* Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
* and assumed to be held on return.
* Locks: None held
*
* Calling context: kernel thread
*
@ -955,8 +954,7 @@ Details:
*
* Returns SUCCESS if command aborted else FAILED
*
* Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
* and assumed to be held on return.
* Locks: None held
*
* Calling context: kernel thread
*
@ -974,8 +972,7 @@ Details:
*
* Returns SUCCESS if command aborted else FAILED
*
* Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
* and assumed to be held on return.
* Locks: None held
*
* Calling context: kernel thread
*
@ -993,8 +990,7 @@ Details:
*
* Returns SUCCESS if command aborted else FAILED
*
* Locks: struct Scsi_Host::host_lock held (with irqsave) on entry
* and assumed to be held on return.
* Locks: None held
*
* Calling context: kernel thread
*

View File

@ -736,6 +736,11 @@ M: tori@unhappy.mine.nu
L: linux-kernel@vger.kernel.org
S: Maintained
DOCBOOK FOR DOCUMENTATION
P: Martin Waitz
M: tali@admingilde.org
S: Maintained
DOUBLETALK DRIVER
P: James R. Van Zandt
M: jrv@vanzandt.mv.com

View File

@ -23,49 +23,92 @@
#include "entry-header.S"
/*
* Interrupt handling. Preserves r7, r8, r9
*/
.macro irq_handler
1: get_irqnr_and_base r0, r6, r5, lr
movne r1, sp
@
@ routine called with r0 = irq number, r1 = struct pt_regs *
@
adrne lr, 1b
bne asm_do_IRQ
#ifdef CONFIG_SMP
/*
* XXX
*
* this macro assumes that irqstat (r6) and base (r5) are
* preserved from get_irqnr_and_base above
*/
test_for_ipi r0, r6, r5, lr
movne r0, sp
adrne lr, 1b
bne do_IPI
#endif
.endm
/*
* Invalid mode handlers
*/
.macro inv_entry, sym, reason
sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
stmia sp, {r0 - lr} @ Save XXX r0 - lr
ldr r4, .LC\sym
.macro inv_entry, reason
sub sp, sp, #S_FRAME_SIZE
stmib sp, {r1 - lr}
mov r1, #\reason
.endm
__pabt_invalid:
inv_entry abt, BAD_PREFETCH
b 1f
inv_entry BAD_PREFETCH
b common_invalid
__dabt_invalid:
inv_entry abt, BAD_DATA
b 1f
inv_entry BAD_DATA
b common_invalid
__irq_invalid:
inv_entry irq, BAD_IRQ
b 1f
inv_entry BAD_IRQ
b common_invalid
__und_invalid:
inv_entry und, BAD_UNDEFINSTR
inv_entry BAD_UNDEFINSTR
@
@ XXX fall through to common_invalid
@
@
@ common_invalid - generic code for failed exception (re-entrant version of handlers)
@
common_invalid:
zero_fp
ldmia r0, {r4 - r6}
add r0, sp, #S_PC @ here for interlock avoidance
mov r7, #-1 @ "" "" "" ""
str r4, [sp] @ save preserved r0
stmia r0, {r5 - r7} @ lr_<exception>,
@ cpsr_<exception>, "old_r0"
1: zero_fp
ldmia r4, {r5 - r7} @ Get XXX pc, cpsr, old_r0
add r4, sp, #S_PC
stmia r4, {r5 - r7} @ Save XXX pc, cpsr, old_r0
mov r0, sp
and r2, r6, #31 @ int mode
and r2, r6, #0x1f
b bad_mode
/*
* SVC mode handlers
*/
.macro svc_entry, sym
.macro svc_entry
sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ save r0 - r12
ldr r2, .LC\sym
add r0, sp, #S_FRAME_SIZE
ldmia r2, {r2 - r4} @ get pc, cpsr
add r5, sp, #S_SP
stmib sp, {r1 - r12}
ldmia r0, {r1 - r3}
add r5, sp, #S_SP @ here for interlock avoidance
mov r4, #-1 @ "" "" "" ""
add r0, sp, #S_FRAME_SIZE @ "" "" "" ""
str r1, [sp] @ save the "real" r0 copied
@ from the exception stack
mov r1, lr
@
@ -82,7 +125,7 @@ __und_invalid:
.align 5
__dabt_svc:
svc_entry abt
svc_entry
@
@ get ready to re-enable interrupts if appropriate
@ -129,28 +172,24 @@ __dabt_svc:
.align 5
__irq_svc:
svc_entry irq
svc_entry
#ifdef CONFIG_PREEMPT
get_thread_info r8
ldr r9, [r8, #TI_PREEMPT] @ get preempt count
add r7, r9, #1 @ increment it
str r7, [r8, #TI_PREEMPT]
get_thread_info tsk
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
add r7, r8, #1 @ increment it
str r7, [tsk, #TI_PREEMPT]
#endif
1: get_irqnr_and_base r0, r6, r5, lr
movne r1, sp
@
@ routine called with r0 = irq number, r1 = struct pt_regs *
@
adrne lr, 1b
bne asm_do_IRQ
irq_handler
#ifdef CONFIG_PREEMPT
ldr r0, [r8, #TI_FLAGS] @ get flags
ldr r0, [tsk, #TI_FLAGS] @ get flags
tst r0, #_TIF_NEED_RESCHED
blne svc_preempt
preempt_return:
ldr r0, [r8, #TI_PREEMPT] @ read preempt value
ldr r0, [tsk, #TI_PREEMPT] @ read preempt value
str r8, [tsk, #TI_PREEMPT] @ restore preempt count
teq r0, r7
str r9, [r8, #TI_PREEMPT] @ restore preempt count
strne r0, [r0, -r0] @ bug()
#endif
ldr r0, [sp, #S_PSR] @ irqs are already disabled
@ -161,7 +200,7 @@ preempt_return:
#ifdef CONFIG_PREEMPT
svc_preempt:
teq r9, #0 @ was preempt count = 0
teq r8, #0 @ was preempt count = 0
ldreq r6, .LCirq_stat
movne pc, lr @ no
ldr r0, [r6, #4] @ local_irq_count
@ -169,9 +208,9 @@ svc_preempt:
adds r0, r0, r1
movne pc, lr
mov r7, #0 @ preempt_schedule_irq
str r7, [r8, #TI_PREEMPT] @ expects preempt_count == 0
str r7, [tsk, #TI_PREEMPT] @ expects preempt_count == 0
1: bl preempt_schedule_irq @ irq en/disable is done inside
ldr r0, [r8, #TI_FLAGS] @ get new tasks TI_FLAGS
ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS
tst r0, #_TIF_NEED_RESCHED
beq preempt_return @ go again
b 1b
@ -179,7 +218,7 @@ svc_preempt:
.align 5
__und_svc:
svc_entry und
svc_entry
@
@ call emulation code, which returns using r9 if it has emulated
@ -209,7 +248,7 @@ __und_svc:
.align 5
__pabt_svc:
svc_entry abt
svc_entry
@
@ re-enable interrupts if appropriate
@ -242,12 +281,8 @@ __pabt_svc:
ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
.align 5
.LCirq:
.word __temp_irq
.LCund:
.word __temp_und
.LCabt:
.word __temp_abt
.LCcralign:
.word cr_alignment
#ifdef MULTI_ABORT
.LCprocfns:
.word processor
@ -262,12 +297,16 @@ __pabt_svc:
/*
* User mode handlers
*/
.macro usr_entry, sym
sub sp, sp, #S_FRAME_SIZE @ Allocate frame size in one go
stmia sp, {r0 - r12} @ save r0 - r12
ldr r7, .LC\sym
add r5, sp, #S_PC
ldmia r7, {r2 - r4} @ Get USR pc, cpsr
.macro usr_entry
sub sp, sp, #S_FRAME_SIZE
stmib sp, {r1 - r12}
ldmia r0, {r1 - r3}
add r0, sp, #S_PC @ here for interlock avoidance
mov r4, #-1 @ "" "" "" ""
str r1, [sp] @ save the "real" r0 copied
@ from the exception stack
#if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG)
@ make sure our user space atomic helper is aborted
@ -284,13 +323,13 @@ __pabt_svc:
@
@ Also, separately save sp_usr and lr_usr
@
stmia r5, {r2 - r4}
stmdb r5, {sp, lr}^
stmia r0, {r2 - r4}
stmdb r0, {sp, lr}^
@
@ Enable the alignment trap while in kernel mode
@
alignment_trap r7, r0, __temp_\sym
alignment_trap r0
@
@ Clear FP to mark the first stack frame
@ -300,7 +339,7 @@ __pabt_svc:
.align 5
__dabt_usr:
usr_entry abt
usr_entry
@
@ Call the processor-specific abort handler:
@ -329,30 +368,23 @@ __dabt_usr:
.align 5
__irq_usr:
usr_entry irq
usr_entry
#ifdef CONFIG_PREEMPT
get_thread_info r8
ldr r9, [r8, #TI_PREEMPT] @ get preempt count
add r7, r9, #1 @ increment it
str r7, [r8, #TI_PREEMPT]
#endif
1: get_irqnr_and_base r0, r6, r5, lr
movne r1, sp
adrne lr, 1b
@
@ routine called with r0 = irq number, r1 = struct pt_regs *
@
bne asm_do_IRQ
#ifdef CONFIG_PREEMPT
ldr r0, [r8, #TI_PREEMPT]
teq r0, r7
str r9, [r8, #TI_PREEMPT]
strne r0, [r0, -r0]
mov tsk, r8
#else
get_thread_info tsk
#ifdef CONFIG_PREEMPT
ldr r8, [tsk, #TI_PREEMPT] @ get preempt count
add r7, r8, #1 @ increment it
str r7, [tsk, #TI_PREEMPT]
#endif
irq_handler
#ifdef CONFIG_PREEMPT
ldr r0, [tsk, #TI_PREEMPT]
str r8, [tsk, #TI_PREEMPT]
teq r0, r7
strne r0, [r0, -r0]
#endif
mov why, #0
b ret_to_user
@ -360,7 +392,7 @@ __irq_usr:
.align 5
__und_usr:
usr_entry und
usr_entry
tst r3, #PSR_T_BIT @ Thumb mode?
bne fpundefinstr @ ignore FP
@ -476,7 +508,7 @@ fpundefinstr:
.align 5
__pabt_usr:
usr_entry abt
usr_entry
enable_irq @ Enable interrupts
mov r0, r2 @ address (pc)
@ -741,29 +773,41 @@ __kuser_helper_end:
*
* Common stub entry macro:
* Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
*
* SP points to a minimal amount of processor-private memory, the address
* of which is copied into r0 for the mode specific abort handler.
*/
.macro vector_stub, name, sym, correction=0
.macro vector_stub, name, correction=0
.align 5
vector_\name:
ldr r13, .LCs\sym
.if \correction
sub lr, lr, #\correction
.endif
str lr, [r13] @ save lr_IRQ
mrs lr, spsr
str lr, [r13, #4] @ save spsr_IRQ
@
@ now branch to the relevant MODE handling routine
@
mrs r13, cpsr
bic r13, r13, #MODE_MASK
orr r13, r13, #SVC_MODE
msr spsr_cxsf, r13 @ switch to SVC_32 mode
and lr, lr, #15
@
@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
@ (parent CPSR)
@
stmia sp, {r0, lr} @ save r0, lr
mrs lr, spsr
str lr, [sp, #8] @ save spsr
@
@ Prepare for SVC32 mode. IRQs remain disabled.
@
mrs r0, cpsr
bic r0, r0, #MODE_MASK
orr r0, r0, #SVC_MODE
msr spsr_cxsf, r0
@
@ the branch table must immediately follow this code
@
mov r0, sp
and lr, lr, #0x0f
ldr lr, [pc, lr, lsl #2]
movs pc, lr @ Changes mode and branches
movs pc, lr @ branch to handler in SVC mode
.endm
.globl __stubs_start
@ -771,7 +815,7 @@ __stubs_start:
/*
* Interrupt dispatcher
*/
vector_stub irq, irq, 4
vector_stub irq, 4
.long __irq_usr @ 0 (USR_26 / USR_32)
.long __irq_invalid @ 1 (FIQ_26 / FIQ_32)
@ -794,7 +838,7 @@ __stubs_start:
* Data abort dispatcher
* Enter in ABT mode, spsr = USR CPSR, lr = USR PC
*/
vector_stub dabt, abt, 8
vector_stub dabt, 8
.long __dabt_usr @ 0 (USR_26 / USR_32)
.long __dabt_invalid @ 1 (FIQ_26 / FIQ_32)
@ -817,7 +861,7 @@ __stubs_start:
* Prefetch abort dispatcher
* Enter in ABT mode, spsr = USR CPSR, lr = USR PC
*/
vector_stub pabt, abt, 4
vector_stub pabt, 4
.long __pabt_usr @ 0 (USR_26 / USR_32)
.long __pabt_invalid @ 1 (FIQ_26 / FIQ_32)
@ -840,7 +884,7 @@ __stubs_start:
* Undef instr entry dispatcher
* Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC
*/
vector_stub und, und
vector_stub und
.long __und_usr @ 0 (USR_26 / USR_32)
.long __und_invalid @ 1 (FIQ_26 / FIQ_32)
@ -894,13 +938,6 @@ vector_addrexcptn:
.LCvswi:
.word vector_swi
.LCsirq:
.word __temp_irq
.LCsund:
.word __temp_und
.LCsabt:
.word __temp_abt
.globl __stubs_end
__stubs_end:
@ -922,23 +959,6 @@ __vectors_end:
.data
/*
* Do not reorder these, and do not insert extra data between...
*/
__temp_irq:
.word 0 @ saved lr_irq
.word 0 @ saved spsr_irq
.word -1 @ old_r0
__temp_und:
.word 0 @ Saved lr_und
.word 0 @ Saved spsr_und
.word -1 @ old_r0
__temp_abt:
.word 0 @ Saved lr_abt
.word 0 @ Saved spsr_abt
.word -1 @ old_r0
.globl cr_alignment
.globl cr_no_alignment
cr_alignment:

View File

@ -59,11 +59,10 @@
mov \rd, \rd, lsl #13
.endm
.macro alignment_trap, rbase, rtemp, sym
.macro alignment_trap, rtemp
#ifdef CONFIG_ALIGNMENT_TRAP
#define OFF_CR_ALIGNMENT(x) cr_alignment - x
ldr \rtemp, [\rbase, #OFF_CR_ALIGNMENT(\sym)]
ldr \rtemp, .LCcralign
ldr \rtemp, [\rtemp]
mcr p15, 0, \rtemp, c1, c0
#endif
.endm

View File

@ -2,6 +2,8 @@
* linux/arch/arm/kernel/head.S
*
* Copyright (C) 1994-2002 Russell King
* Copyright (c) 2003 ARM Limited
* 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 version 2 as
@ -165,6 +167,48 @@ __mmap_switched:
stmia r6, {r0, r4} @ Save control register values
b start_kernel
#if defined(CONFIG_SMP)
.type secondary_startup, #function
ENTRY(secondary_startup)
/*
* Common entry point for secondary CPUs.
*
* Ensure that we're in SVC mode, and IRQs are disabled. Lookup
* the processor type - there is no need to check the machine type
* as it has already been validated by the primary processor.
*/
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | MODE_SVC
bl __lookup_processor_type
movs r10, r5 @ invalid processor?
moveq r0, #'p' @ yes, error 'p'
beq __error
/*
* Use the page tables supplied from __cpu_up.
*/
adr r4, __secondary_data
ldmia r4, {r5, r6, r13} @ address to jump to after
sub r4, r4, r5 @ mmu has been enabled
ldr r4, [r6, r4] @ get secondary_data.pgdir
adr lr, __enable_mmu @ return address
add pc, r10, #12 @ initialise processor
@ (return control reg)
/*
* r6 = &secondary_data
*/
ENTRY(__secondary_switched)
ldr sp, [r6, #4] @ get secondary_data.stack
mov fp, #0
b secondary_start_kernel
.type __secondary_data, %object
__secondary_data:
.long .
.long secondary_data
.long __secondary_switched
#endif /* defined(CONFIG_SMP) */
/*

View File

@ -92,6 +92,14 @@ struct cpu_user_fns cpu_user;
struct cpu_cache_fns cpu_cache;
#endif
struct stack {
u32 irq[3];
u32 abt[3];
u32 und[3];
} ____cacheline_aligned;
static struct stack stacks[NR_CPUS];
char elf_platform[ELF_PLATFORM_SIZE];
EXPORT_SYMBOL(elf_platform);
@ -307,8 +315,6 @@ static void __init setup_processor(void)
cpu_name, processor_id, (int)processor_id & 15,
proc_arch[cpu_architecture()]);
dump_cpu_info(smp_processor_id());
sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
elf_hwcap = list->elf_hwcap;
@ -316,6 +322,46 @@ static void __init setup_processor(void)
cpu_proc_init();
}
/*
* cpu_init - initialise one CPU.
*
* cpu_init dumps the cache information, initialises SMP specific
* information, and sets up the per-CPU stacks.
*/
void cpu_init(void)
{
unsigned int cpu = smp_processor_id();
struct stack *stk = &stacks[cpu];
if (cpu >= NR_CPUS) {
printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
BUG();
}
dump_cpu_info(cpu);
/*
* setup stacks for re-entrant exception handlers
*/
__asm__ (
"msr cpsr_c, %1\n\t"
"add sp, %0, %2\n\t"
"msr cpsr_c, %3\n\t"
"add sp, %0, %4\n\t"
"msr cpsr_c, %5\n\t"
"add sp, %0, %6\n\t"
"msr cpsr_c, %7"
:
: "r" (stk),
"I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
"I" (offsetof(struct stack, irq[0])),
"I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
"I" (offsetof(struct stack, abt[0])),
"I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
"I" (offsetof(struct stack, und[0])),
"I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE));
}
static struct machine_desc * __init setup_machine(unsigned int nr)
{
struct machine_desc *list;
@ -715,6 +761,8 @@ void __init setup_arch(char **cmdline_p)
paging_init(&meminfo, mdesc);
request_standard_resources(&meminfo, mdesc);
cpu_init();
/*
* Set up various architecture-specific pointers
*/

View File

@ -24,6 +24,9 @@
#include <asm/atomic.h>
#include <asm/cacheflush.h>
#include <asm/cpu.h>
#include <asm/mmu_context.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
#include <asm/processor.h>
#include <asm/tlbflush.h>
#include <asm/ptrace.h>
@ -36,6 +39,13 @@
cpumask_t cpu_present_mask;
cpumask_t cpu_online_map;
/*
* as from 2.5, kernels no longer have an init_tasks structure
* so we need some other way of telling a new secondary core
* where to place its SVC stack
*/
struct secondary_data secondary_data;
/*
* structures for inter-processor calls
* - A collection of single bit ipi messages.
@ -71,6 +81,8 @@ static DEFINE_SPINLOCK(smp_call_function_lock);
int __init __cpu_up(unsigned int cpu)
{
struct task_struct *idle;
pgd_t *pgd;
pmd_t *pmd;
int ret;
/*
@ -83,10 +95,55 @@ int __init __cpu_up(unsigned int cpu)
return PTR_ERR(idle);
}
/*
* Allocate initial page tables to allow the new CPU to
* enable the MMU safely. This essentially means a set
* of our "standard" page tables, with the addition of
* a 1:1 mapping for the physical address of the kernel.
*/
pgd = pgd_alloc(&init_mm);
pmd = pmd_offset(pgd, PHYS_OFFSET);
*pmd = __pmd((PHYS_OFFSET & PGDIR_MASK) |
PMD_TYPE_SECT | PMD_SECT_AP_WRITE);
/*
* We need to tell the secondary core where to find
* its stack and the page tables.
*/
secondary_data.stack = (void *)idle->thread_info + THREAD_SIZE - 8;
secondary_data.pgdir = virt_to_phys(pgd);
wmb();
/*
* Now bring the CPU into our world.
*/
ret = boot_secondary(cpu, idle);
if (ret == 0) {
unsigned long timeout;
/*
* CPU was successfully started, wait for it
* to come online or time out.
*/
timeout = jiffies + HZ;
while (time_before(jiffies, timeout)) {
if (cpu_online(cpu))
break;
udelay(10);
barrier();
}
if (!cpu_online(cpu))
ret = -EIO;
}
secondary_data.stack = 0;
secondary_data.pgdir = 0;
*pmd_offset(pgd, PHYS_OFFSET) = __pmd(0);
pgd_free(pgd);
if (ret) {
printk(KERN_CRIT "cpu_up: processor %d failed to boot\n", cpu);
/*
@ -97,6 +154,56 @@ int __init __cpu_up(unsigned int cpu)
return ret;
}
/*
* This is the secondary CPU boot entry. We're using this CPUs
* idle thread stack, but a set of temporary page tables.
*/
asmlinkage void __init secondary_start_kernel(void)
{
struct mm_struct *mm = &init_mm;
unsigned int cpu = smp_processor_id();
printk("CPU%u: Booted secondary processor\n", cpu);
/*
* All kernel threads share the same mm context; grab a
* reference and switch to it.
*/
atomic_inc(&mm->mm_users);
atomic_inc(&mm->mm_count);
current->active_mm = mm;
cpu_set(cpu, mm->cpu_vm_mask);
cpu_switch_mm(mm->pgd, mm);
enter_lazy_tlb(mm, current);
cpu_init();
/*
* Give the platform a chance to do its own initialisation.
*/
platform_secondary_init(cpu);
/*
* Enable local interrupts.
*/
local_irq_enable();
local_fiq_enable();
calibrate_delay();
smp_store_cpu_info(cpu);
/*
* OK, now it's safe to let the boot CPU continue
*/
cpu_set(cpu, cpu_online_map);
/*
* OK, it's off to the idle thread for us
*/
cpu_idle();
}
/*
* Called by both boot and secondaries to move global data into
* per-processor storage.

View File

@ -12,3 +12,4 @@ obj-$(CONFIG_LEDS) += leds.o
obj-$(CONFIG_PCI) += pci_v3.o pci.o
obj-$(CONFIG_CPU_FREQ_INTEGRATOR) += cpu.o
obj-$(CONFIG_INTEGRATOR_IMPD1) += impd1.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o

View File

@ -14,6 +14,7 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <linux/smp.h>
#include <asm/hardware.h>
#include <asm/irq.h>
@ -221,7 +222,24 @@ integrator_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
*/
timer1->TimerClear = 1;
timer_tick(regs);
/*
* the clock tick routines are only processed on the
* primary CPU
*/
if (hard_smp_processor_id() == 0) {
nmi_tick();
timer_tick(regs);
#ifdef CONFIG_SMP
smp_send_timer();
#endif
}
#ifdef CONFIG_SMP
/*
* this is the ARM equivalent of the APIC timer interrupt
*/
update_process_times(user_mode(regs));
#endif /* CONFIG_SMP */
write_sequnlock(&xtime_lock);

View File

@ -0,0 +1,37 @@
/*
* linux/arch/arm/mach-integrator/headsmp.S
*
* Copyright (c) 2003 ARM Limited
* 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 version 2 as
* published by the Free Software Foundation.
*/
#include <linux/linkage.h>
#include <linux/init.h>
__INIT
/*
* Integrator specific entry point for secondary CPUs. This provides
* a "holding pen" into which all secondary cores are held until we're
* ready for them to initialise.
*/
ENTRY(integrator_secondary_startup)
adr r4, 1f
ldmia r4, {r5, r6}
sub r4, r4, r5
ldr r6, [r6, r4]
pen: ldr r7, [r6]
cmp r7, r0
bne pen
/*
* we've been released from the holding pen: secondary_stack
* should now contain the SVC stack for this core
*/
b secondary_startup
1: .long .
.long phys_pen_release

View File

@ -22,6 +22,8 @@
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/smp.h>
#include <linux/spinlock.h>
#include <asm/hardware.h>
#include <asm/io.h>
@ -85,4 +87,4 @@ static int __init leds_init(void)
return 0;
}
__initcall(leds_init);
core_initcall(leds_init);

View File

@ -0,0 +1,192 @@
/*
* linux/arch/arm/mach-cintegrator/platsmp.c
*
* Copyright (C) 2002 ARM Ltd.
* 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 version 2 as
* published by the Free Software Foundation.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <asm/atomic.h>
#include <asm/delay.h>
#include <asm/mmu_context.h>
#include <asm/procinfo.h>
#include <asm/ptrace.h>
#include <asm/smp.h>
extern void integrator_secondary_startup(void);
/*
* control for which core is the next to come out of the secondary
* boot "holding pen"
*/
volatile int __initdata pen_release = -1;
unsigned long __initdata phys_pen_release = 0;
static DEFINE_SPINLOCK(boot_lock);
void __init platform_secondary_init(unsigned int cpu)
{
/*
* the primary core may have used a "cross call" soft interrupt
* to get this processor out of WFI in the BootMonitor - make
* sure that we are no longer being sent this soft interrupt
*/
smp_cross_call_done(cpumask_of_cpu(cpu));
/*
* if any interrupts are already enabled for the primary
* core (e.g. timer irq), then they will not have been enabled
* for us: do so
*/
secondary_scan_irqs();
/*
* let the primary processor know we're out of the
* pen, then head off into the C entry point
*/
pen_release = -1;
/*
* Synchronise with the boot thread.
*/
spin_lock(&boot_lock);
spin_unlock(&boot_lock);
}
int __init boot_secondary(unsigned int cpu, struct task_struct *idle)
{
unsigned long timeout;
/*
* set synchronisation state between this boot processor
* and the secondary one
*/
spin_lock(&boot_lock);
/*
* The secondary processor is waiting to be released from
* the holding pen - release it, then wait for it to flag
* that it has been released by resetting pen_release.
*
* Note that "pen_release" is the hardware CPU ID, whereas
* "cpu" is Linux's internal ID.
*/
pen_release = cpu;
/*
* XXX
*
* This is a later addition to the booting protocol: the
* bootMonitor now puts secondary cores into WFI, so
* poke_milo() no longer gets the cores moving; we need
* to send a soft interrupt to wake the secondary core.
* Use smp_cross_call() for this, since there's little
* point duplicating the code here
*/
smp_cross_call(cpumask_of_cpu(cpu));
timeout = jiffies + (1 * HZ);
while (time_before(jiffies, timeout)) {
if (pen_release == -1)
break;
udelay(10);
}
/*
* now the secondary core is starting up let it run its
* calibrations, then wait for it to finish
*/
spin_unlock(&boot_lock);
return pen_release != -1 ? -ENOSYS : 0;
}
static void __init poke_milo(void)
{
extern void secondary_startup(void);
/* nobody is to be released from the pen yet */
pen_release = -1;
phys_pen_release = virt_to_phys(&pen_release);
/*
* write the address of secondary startup into the system-wide
* flags register, then clear the bottom two bits, which is what
* BootMonitor is waiting for
*/
#if 1
#define CINTEGRATOR_HDR_FLAGSS_OFFSET 0x30
__raw_writel(virt_to_phys(integrator_secondary_startup),
(IO_ADDRESS(INTEGRATOR_HDR_BASE) +
CINTEGRATOR_HDR_FLAGSS_OFFSET));
#define CINTEGRATOR_HDR_FLAGSC_OFFSET 0x34
__raw_writel(3,
(IO_ADDRESS(INTEGRATOR_HDR_BASE) +
CINTEGRATOR_HDR_FLAGSC_OFFSET));
#endif
mb();
}
void __init smp_prepare_cpus(unsigned int max_cpus)
{
unsigned int ncores = get_core_count();
unsigned int cpu = smp_processor_id();
int i;
/* sanity check */
if (ncores == 0) {
printk(KERN_ERR
"Integrator/CP: strange CM count of 0? Default to 1\n");
ncores = 1;
}
if (ncores > NR_CPUS) {
printk(KERN_WARNING
"Integrator/CP: no. of cores (%d) greater than configured "
"maximum of %d - clipping\n",
ncores, NR_CPUS);
ncores = NR_CPUS;
}
/*
* start with some more config for the Boot CPU, now that
* the world is a bit more alive (which was not the case
* when smp_prepare_boot_cpu() was called)
*/
smp_store_cpu_info(cpu);
/*
* are we trying to boot more cores than exist?
*/
if (max_cpus > ncores)
max_cpus = ncores;
/*
* Initialise the present mask - this tells us which CPUs should
* be present.
*/
for (i = 0; i < max_cpus; i++) {
cpu_set(i, cpu_present_mask);
}
/*
* Do we need any more CPUs? If so, then let them know where
* to start. Note that, on modern versions of MILO, the "poke"
* doesn't actually do anything until each individual core is
* sent a soft interrupt to get it out of WFI
*/
if (max_cpus > 1)
poke_milo();
}

View File

@ -133,6 +133,8 @@ static int pxa_pm_enter(suspend_state_t state)
/* *** go zzz *** */
pxa_cpu_pm_enter(state);
cpu_init();
/* after sleeping, validate the checksum */
checksum = 0;
for (i = 0; i < SLEEP_SAVE_SIZE - 1; i++)

View File

@ -88,6 +88,8 @@ static int sa11x0_pm_enter(suspend_state_t state)
/* go zzz */
sa1100_cpu_suspend();
cpu_init();
/*
* Ensure not to come back here if it wasn't intended
*/

View File

@ -41,6 +41,7 @@
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/dma-mapping.h>
#include <linux/blkdev.h>
#include <linux/genhd.h>
#include <linux/completion.h>
@ -126,8 +127,6 @@ static struct board_type products[] = {
#define MAX_CTLR_ORIG 8
#define CCISS_DMA_MASK 0xFFFFFFFF /* 32 bit DMA */
static ctlr_info_t *hba[MAX_CTLR];
static void do_cciss_request(request_queue_t *q);
@ -2393,11 +2392,6 @@ static int cciss_pci_init(ctlr_info_t *c, struct pci_dev *pdev)
printk(KERN_ERR "cciss: Unable to Enable PCI device\n");
return( -1);
}
if (pci_set_dma_mask(pdev, CCISS_DMA_MASK ) != 0)
{
printk(KERN_ERR "cciss: Unable to set DMA mask\n");
return(-1);
}
subsystem_vendor_id = pdev->subsystem_vendor;
subsystem_device_id = pdev->subsystem_device;
@ -2747,9 +2741,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
hba[i]->pdev = pdev;
/* configure PCI DMA stuff */
if (!pci_set_dma_mask(pdev, 0xffffffffffffffffULL))
if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK))
printk("cciss: using DAC cycles\n");
else if (!pci_set_dma_mask(pdev, 0xffffffff))
else if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK))
printk("cciss: not using DAC cycles\n");
else {
printk("cciss: no suitable DMA available\n");

View File

@ -285,6 +285,13 @@ void elv_requeue_request(request_queue_t *q, struct request *rq)
rq = rq->end_io_data;
}
/*
* the request is prepped and may have some resources allocated.
* allowing unprepped requests to pass this one may cause resource
* deadlock. turn on softbarrier.
*/
rq->flags |= REQ_SOFTBARRIER;
/*
* if iosched has an explicit requeue hook, then use that. otherwise
* just put the request at the front of the queue
@ -381,6 +388,12 @@ struct request *elv_next_request(request_queue_t *q)
if (ret == BLKPREP_OK) {
break;
} else if (ret == BLKPREP_DEFER) {
/*
* the request may have been (partially) prepped.
* we need to keep this request in the front to
* avoid resource deadlock. turn on softbarrier.
*/
rq->flags |= REQ_SOFTBARRIER;
rq = NULL;
break;
} else if (ret == BLKPREP_KILL) {

View File

@ -2038,7 +2038,6 @@ EXPORT_SYMBOL(blk_requeue_request);
* @rq: request to be inserted
* @at_head: insert request at head or tail of queue
* @data: private data
* @reinsert: true if request it a reinsertion of previously processed one
*
* Description:
* Many block devices need to execute commands asynchronously, so they don't
@ -2053,8 +2052,9 @@ EXPORT_SYMBOL(blk_requeue_request);
* host that is unable to accept a particular command.
*/
void blk_insert_request(request_queue_t *q, struct request *rq,
int at_head, void *data, int reinsert)
int at_head, void *data)
{
int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
unsigned long flags;
/*
@ -2071,20 +2071,12 @@ void blk_insert_request(request_queue_t *q, struct request *rq,
/*
* If command is tagged, release the tag
*/
if (reinsert)
blk_requeue_request(q, rq);
else {
int where = ELEVATOR_INSERT_BACK;
if (blk_rq_tagged(rq))
blk_queue_end_tag(q, rq);
if (at_head)
where = ELEVATOR_INSERT_FRONT;
drive_stat_acct(rq, rq->nr_sectors, 1);
__elv_add_request(q, rq, where, 0);
if (blk_rq_tagged(rq))
blk_queue_end_tag(q, rq);
drive_stat_acct(rq, rq->nr_sectors, 1);
__elv_add_request(q, rq, where, 0);
}
if (blk_queue_plugged(q))
__generic_unplug_device(q);
else

View File

@ -723,7 +723,7 @@ static int pd_special_command(struct pd_unit *disk,
rq.ref_count = 1;
rq.waiting = &wait;
rq.end_io = blk_end_sync_rq;
blk_insert_request(disk->gd->queue, &rq, 0, func, 0);
blk_insert_request(disk->gd->queue, &rq, 0, func);
wait_for_completion(&wait);
rq.waiting = NULL;
if (rq.errors)

View File

@ -614,7 +614,7 @@ static int carm_array_info (struct carm_host *host, unsigned int array_idx)
spin_unlock_irq(&host->lock);
DPRINTK("blk_insert_request, tag == %u\n", idx);
blk_insert_request(host->oob_q, crq->rq, 1, crq, 0);
blk_insert_request(host->oob_q, crq->rq, 1, crq);
return 0;
@ -653,7 +653,7 @@ static int carm_send_special (struct carm_host *host, carm_sspc_t func)
crq->msg_bucket = (u32) rc;
DPRINTK("blk_insert_request, tag == %u\n", idx);
blk_insert_request(host->oob_q, crq->rq, 1, crq, 0);
blk_insert_request(host->oob_q, crq->rq, 1, crq);
return 0;
}

View File

@ -2867,6 +2867,10 @@ void unblank_screen(void)
*/
static void blank_screen_t(unsigned long dummy)
{
if (unlikely(!keventd_up())) {
mod_timer(&console_timer, jiffies + blankinterval);
return;
}
blank_timer_expired = 1;
schedule_work(&console_work);
}

View File

@ -767,10 +767,8 @@ static void fcp_scsi_done (Scsi_Cmnd *SCpnt)
{
unsigned long flags;
spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
if (FCP_CMND(SCpnt)->done)
FCP_CMND(SCpnt)->done(SCpnt);
spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
}
static int fcp_scsi_queue_it(fc_channel *fc, Scsi_Cmnd *SCpnt, fcp_cmnd *fcmd, int prepare)
@ -912,9 +910,7 @@ int fcp_scsi_abort(Scsi_Cmnd *SCpnt)
unsigned long flags;
SCpnt->result = DID_ABORT;
spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
fcmd->done(SCpnt);
spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
printk("FC: soft abort\n");
return SUCCESS;
} else {
@ -987,7 +983,10 @@ int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
fc->rst_pkt->request->rq_status = RQ_SCSI_BUSY;
fc->rst_pkt->done = fcp_scsi_reset_done;
spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
fcp_scsi_queue_it(fc, fc->rst_pkt, fcmd, 0);
spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
down(&sem);
@ -1006,13 +1005,7 @@ int fcp_scsi_dev_reset(Scsi_Cmnd *SCpnt)
return SUCCESS;
}
int fcp_scsi_bus_reset(Scsi_Cmnd *SCpnt)
{
printk ("FC: bus reset!\n");
return FAILED;
}
int fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
static int __fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
{
fc_channel *fc = FC_SCMND(SCpnt);
fcp_cmnd *fcmd = FCP_CMND(SCpnt);
@ -1033,6 +1026,17 @@ int fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
else return FAILED;
}
int fcp_scsi_host_reset(Scsi_Cmnd *SCpnt)
{
int rc;
spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
rc = __fcp_scsi_host_reset(SCpnt);
spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
return rc;
}
static int fcp_els_queue_it(fc_channel *fc, fcp_cmnd *fcmd)
{
long i;

View File

@ -27,7 +27,6 @@ EXPORT_SYMBOL(fc_do_prli);
EXPORT_SYMBOL(fcp_scsi_queuecommand);
EXPORT_SYMBOL(fcp_scsi_abort);
EXPORT_SYMBOL(fcp_scsi_dev_reset);
EXPORT_SYMBOL(fcp_scsi_bus_reset);
EXPORT_SYMBOL(fcp_scsi_host_reset);
#endif /* CONFIG_MODULES */

View File

@ -158,7 +158,6 @@ int fc_do_prli(fc_channel *, unsigned char);
int fcp_scsi_queuecommand(Scsi_Cmnd *, void (* done)(Scsi_Cmnd *));
int fcp_scsi_abort(Scsi_Cmnd *);
int fcp_scsi_dev_reset(Scsi_Cmnd *);
int fcp_scsi_bus_reset(Scsi_Cmnd *);
int fcp_scsi_host_reset(Scsi_Cmnd *);
#endif /* !(_FCP_SCSI_H) */

View File

@ -1071,7 +1071,7 @@ static int sbp2_handle_physdma_read(struct hpsb_host *host, int nodeid, quadlet_
static __inline__ int sbp2_command_conversion_device_type(u8 device_type)
{
return (((device_type == TYPE_DISK) ||
(device_type == TYPE_SDAD) ||
(device_type == TYPE_RBC) ||
(device_type == TYPE_ROM)) ? 1:0);
}
@ -2112,102 +2112,6 @@ static int sbp2_send_command(struct scsi_id_instance_data *scsi_id,
*/
static void sbp2_check_sbp2_command(struct scsi_id_instance_data *scsi_id, unchar *cmd)
{
unchar new_cmd[16];
u8 device_type = SBP2_DEVICE_TYPE (scsi_id->sbp2_device_type_and_lun);
SBP2_DEBUG("sbp2_check_sbp2_command");
switch (*cmd) {
case READ_6:
if (sbp2_command_conversion_device_type(device_type)) {
SBP2_DEBUG("Convert READ_6 to READ_10");
/*
* Need to turn read_6 into read_10
*/
new_cmd[0] = 0x28;
new_cmd[1] = (cmd[1] & 0xe0);
new_cmd[2] = 0x0;
new_cmd[3] = (cmd[1] & 0x1f);
new_cmd[4] = cmd[2];
new_cmd[5] = cmd[3];
new_cmd[6] = 0x0;
new_cmd[7] = 0x0;
new_cmd[8] = cmd[4];
new_cmd[9] = cmd[5];
memcpy(cmd, new_cmd, 10);
}
break;
case WRITE_6:
if (sbp2_command_conversion_device_type(device_type)) {
SBP2_DEBUG("Convert WRITE_6 to WRITE_10");
/*
* Need to turn write_6 into write_10
*/
new_cmd[0] = 0x2a;
new_cmd[1] = (cmd[1] & 0xe0);
new_cmd[2] = 0x0;
new_cmd[3] = (cmd[1] & 0x1f);
new_cmd[4] = cmd[2];
new_cmd[5] = cmd[3];
new_cmd[6] = 0x0;
new_cmd[7] = 0x0;
new_cmd[8] = cmd[4];
new_cmd[9] = cmd[5];
memcpy(cmd, new_cmd, 10);
}
break;
case MODE_SENSE:
if (sbp2_command_conversion_device_type(device_type)) {
SBP2_DEBUG("Convert MODE_SENSE_6 to MODE_SENSE_10");
/*
* Need to turn mode_sense_6 into mode_sense_10
*/
new_cmd[0] = 0x5a;
new_cmd[1] = cmd[1];
new_cmd[2] = cmd[2];
new_cmd[3] = 0x0;
new_cmd[4] = 0x0;
new_cmd[5] = 0x0;
new_cmd[6] = 0x0;
new_cmd[7] = 0x0;
new_cmd[8] = cmd[4];
new_cmd[9] = cmd[5];
memcpy(cmd, new_cmd, 10);
}
break;
case MODE_SELECT:
/*
* TODO. Probably need to change mode select to 10 byte version
*/
default:
break;
}
return;
}
/*
@ -2248,7 +2152,6 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
struct scsi_cmnd *SCpnt)
{
u8 *scsi_buf = SCpnt->request_buffer;
u8 device_type = SBP2_DEVICE_TYPE (scsi_id->sbp2_device_type_and_lun);
SBP2_DEBUG("sbp2_check_sbp2_response");
@ -2272,14 +2175,6 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
scsi_buf[4] = 36 - 5;
}
/*
* Check for Simple Direct Access Device and change it to TYPE_DISK
*/
if ((scsi_buf[0] & 0x1f) == TYPE_SDAD) {
SBP2_DEBUG("Changing TYPE_SDAD to TYPE_DISK");
scsi_buf[0] &= 0xe0;
}
/*
* Fix ansi revision and response data format
*/
@ -2288,27 +2183,6 @@ static void sbp2_check_sbp2_response(struct scsi_id_instance_data *scsi_id,
break;
case MODE_SENSE:
if (sbp2_command_conversion_device_type(device_type)) {
SBP2_DEBUG("Modify mode sense response (10 byte version)");
scsi_buf[0] = scsi_buf[1]; /* Mode data length */
scsi_buf[1] = scsi_buf[2]; /* Medium type */
scsi_buf[2] = scsi_buf[3]; /* Device specific parameter */
scsi_buf[3] = scsi_buf[7]; /* Block descriptor length */
memcpy(scsi_buf + 4, scsi_buf + 8, scsi_buf[0]);
}
break;
case MODE_SELECT:
/*
* TODO. Probably need to change mode select to 10 byte version
*/
default:
break;
}
@ -2580,8 +2454,6 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
u32 scsi_status, struct scsi_cmnd *SCpnt,
void (*done)(struct scsi_cmnd *))
{
unsigned long flags;
SBP2_DEBUG("sbp2scsi_complete_command");
/*
@ -2680,18 +2552,15 @@ static void sbp2scsi_complete_command(struct scsi_id_instance_data *scsi_id,
/*
* Tell scsi stack that we're done with this command
*/
spin_lock_irqsave(scsi_id->scsi_host->host_lock,flags);
done (SCpnt);
spin_unlock_irqrestore(scsi_id->scsi_host->host_lock,flags);
return;
}
static int sbp2scsi_slave_configure (struct scsi_device *sdev)
{
blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
sdev->use_10_for_rw = 1;
sdev->use_10_for_ms = 1;
return 0;
}
@ -2747,7 +2616,7 @@ static int sbp2scsi_abort(struct scsi_cmnd *SCpnt)
/*
* Called by scsi stack when something has really gone wrong.
*/
static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
static int __sbp2scsi_reset(struct scsi_cmnd *SCpnt)
{
struct scsi_id_instance_data *scsi_id =
(struct scsi_id_instance_data *)SCpnt->device->host->hostdata[0];
@ -2762,6 +2631,18 @@ static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
return(SUCCESS);
}
static int sbp2scsi_reset(struct scsi_cmnd *SCpnt)
{
unsigned long flags;
int rc;
spin_lock_irqsave(SCpnt->device->host->host_lock, flags);
rc = __sbp2scsi_reset(SCpnt);
spin_unlock_irqrestore(SCpnt->device->host->host_lock, flags);
return rc;
}
static const char *sbp2scsi_info (struct Scsi_Host *host)
{
return "SCSI emulation for IEEE-1394 SBP-2 Devices";

View File

@ -266,10 +266,6 @@ struct sbp2_status_block {
#define SBP2_MAX_UDS_PER_NODE 16 /* Maximum scsi devices per node */
#define SBP2_MAX_SECTORS 255 /* Max sectors supported */
#ifndef TYPE_SDAD
#define TYPE_SDAD 0x0e /* simplified direct access device */
#endif
/*
* SCSI direction table...
* (now used as a back-up in case the direction passed down from above is "unknown")

View File

@ -2,34 +2,54 @@
menu "Fusion MPT device support"
config FUSION
tristate "Fusion MPT (base + ScsiHost) drivers"
depends on PCI && SCSI
---help---
LSI Logic Fusion(TM) Message Passing Technology (MPT) device support
provides high performance SCSI host initiator, and LAN [1] interface
services to a host system. The Fusion architecture is capable of
duplexing these protocols on high-speed Fibre Channel
(up to 2 GHz x 2 ports = 4 GHz) and parallel SCSI (up to Ultra-320)
physical medium.
bool
default n
[1] LAN is not supported on parallel SCSI medium.
config FUSION_SPI
tristate "Fusion MPT ScsiHost drivers for SPI"
depends on PCI && SCSI
select FUSION
---help---
SCSI HOST support for a parallel SCSI host adapters.
List of supported controllers:
LSI53C1020
LSI53C1020A
LSI53C1030
LSI53C1035
config FUSION_FC
tristate "Fusion MPT ScsiHost drivers for FC"
depends on PCI && SCSI
select FUSION
---help---
SCSI HOST support for a Fiber Channel host adapters.
List of supported controllers:
LSIFC909
LSIFC919
LSIFC919X
LSIFC929
LSIFC929X
LSIFC929XL
config FUSION_MAX_SGE
int "Maximum number of scatter gather entries"
int "Maximum number of scatter gather entries (16 - 128)"
depends on FUSION
default "40"
default "128"
range 16 128
help
This option allows you to specify the maximum number of scatter-
gather entries per I/O. The driver defaults to 40, a reasonable number
for most systems. However, the user may increase this up to 128.
Increasing this parameter will require significantly more memory
on a per controller instance. Increasing the parameter is not
necessary (or recommended) unless the user will be running
large I/O's via the raw interface.
gather entries per I/O. The driver default is 128, which matches
SCSI_MAX_PHYS_SEGMENTS. However, it may decreased down to 16.
Decreasing this parameter will reduce memory requirements
on a per controller instance.
config FUSION_CTL
tristate "Fusion MPT misc device (ioctl) driver"
depends on FUSION
depends on FUSION_SPI || FUSION_FC
---help---
The Fusion MPT misc device driver provides specialized control
of MPT adapters via system ioctl calls. Use of ioctl calls to
@ -48,7 +68,7 @@ config FUSION_CTL
config FUSION_LAN
tristate "Fusion MPT LAN driver"
depends on FUSION && NET_FC
depends on FUSION_FC && NET_FC
---help---
This module supports LAN IP traffic over Fibre Channel port(s)
on Fusion MPT compatible hardware (LSIFC9xx chips).

View File

@ -1,52 +1,38 @@
#
# Makefile for the LSI Logic Fusion MPT (Message Passing Technology) drivers.
#
# Note! If you want to turn on various debug defines for an extended period of
# time but don't want them lingering around in the Makefile when you pass it on
# to someone else, use the MPT_CFLAGS env variable (thanks Steve). -nromer
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-{ LSI_LOGIC
# Architecture-specific...
# # intel
#EXTRA_CFLAGS += -g
# # sparc64
#EXTRA_CFLAGS += -gstabs+
EXTRA_CFLAGS += ${MPT_CFLAGS}
# Fusion MPT drivers; recognized debug defines...
# MPT general:
#EXTRA_CFLAGS += -DMPT_DEBUG_SCSI
#EXTRA_CFLAGS += -DMPT_DEBUG
#EXTRA_CFLAGS += -DMPT_DEBUG_MSG_FRAME
#EXTRA_CFLAGS += -DMPT_DEBUG_SG
#EXTRA_CFLAGS += -DMPT_DEBUG_EVENTS
#EXTRA_CFLAGS += -DMPT_DEBUG_INIT
#EXTRA_CFLAGS += -DMPT_DEBUG_EXIT
#EXTRA_CFLAGS += -DMPT_DEBUG_FAIL
#
# driver/module specifics...
#
# For mptbase:
#CFLAGS_mptbase.o += -DMPT_DEBUG_HANDSHAKE
#CFLAGS_mptbase.o += -DMPT_DEBUG_CONFIG
#CFLAGS_mptbase.o += -DMPT_DEBUG_DL
#CFLAGS_mptbase.o += -DMPT_DEBUG_IRQ
#CFLAGS_mptbase.o += -DMPT_DEBUG_RESET
#
# For mptscsih:
#CFLAGS_mptscsih.o += -DMPT_DEBUG_SCANDV
#CFLAGS_mptscsih.o += -DMPT_DEBUG_RESET
#CFLAGS_mptscsih.o += -DMPT_DEBUG_NEH
#CFLAGS_mptscsih.o += -DMPT_DEBUG_DV
#CFLAGS_mptscsih.o += -DMPT_DEBUG_NEGO
#CFLAGS_mptscsih.o += -DMPT_DEBUG_TM
#CFLAGS_mptscsih.o += -DMPT_DEBUG_SCSI
#CFLAGS_mptscsih.o += -DMPT_DEBUG_REPLY
#
# For mptctl:
#CFLAGS_mptctl.o += -DMPT_DEBUG_IOCTL
#
# For mptlan:
#CFLAGS_mptlan.o += -DMPT_LAN_IO_DEBUG
#
# For isense:
# EXP...
##mptscsih-objs := scsihost.o scsiherr.o
#=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
obj-$(CONFIG_FUSION) += mptbase.o mptscsih.o
obj-$(CONFIG_FUSION_SPI) += mptbase.o mptscsih.o mptspi.o
obj-$(CONFIG_FUSION_FC) += mptbase.o mptscsih.o mptfc.o
obj-$(CONFIG_FUSION_CTL) += mptctl.o
obj-$(CONFIG_FUSION_LAN) += mptlan.o

View File

@ -1,12 +1,12 @@
/*
* Copyright (c) 2000-2003 LSI Logic Corporation.
* Copyright (c) 2000-2005 LSI Logic Corporation.
*
*
* Name: mpi.h
* Title: MPI Message independent structures and definitions
* Creation Date: July 27, 2000
*
* mpi.h Version: 01.05.xx
* mpi.h Version: 01.05.07
*
* Version History
* ---------------
@ -52,6 +52,25 @@
* obsoleted define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX.
* 04-01-03 01.02.09 New IOCStatus code: MPI_IOCSTATUS_FC_EXCHANGE_CANCELED
* 06-26-03 01.02.10 Bumped MPI_HEADER_VERSION_UNIT value.
* 01-16-04 01.02.11 Added define for MPI_IOCLOGINFO_TYPE_SHIFT.
* 04-29-04 01.02.12 Added function codes for MPI_FUNCTION_DIAG_BUFFER_POST
* and MPI_FUNCTION_DIAG_RELEASE.
* Added MPI_IOCSTATUS_DIAGNOSTIC_RELEASED define.
* Bumped MPI_HEADER_VERSION_UNIT value.
* 05-11-04 01.03.01 Bumped MPI_VERSION_MINOR for MPI v1.3.
* Added codes for Inband.
* 08-19-04 01.05.01 Added defines for Host Buffer Access Control doorbell.
* Added define for offset of High Priority Request Queue.
* Added new function codes and new IOCStatus codes.
* Added a IOCLogInfo type of SAS.
* 12-07-04 01.05.02 Bumped MPI_HEADER_VERSION_UNIT.
* 12-09-04 01.05.03 Bumped MPI_HEADER_VERSION_UNIT.
* 01-15-05 01.05.04 Bumped MPI_HEADER_VERSION_UNIT.
* 02-09-05 01.05.05 Bumped MPI_HEADER_VERSION_UNIT.
* 02-22-05 01.05.06 Bumped MPI_HEADER_VERSION_UNIT.
* 03-11-05 01.05.07 Removed function codes for SCSI IO 32 and
* TargetAssistExtended requests.
* Removed EEDP IOCStatus codes.
* --------------------------------------------------------------------------
*/
@ -82,7 +101,7 @@
/* Note: The major versions of 0xe0 through 0xff are reserved */
/* versioning for this MPI header set */
#define MPI_HEADER_VERSION_UNIT (0x00)
#define MPI_HEADER_VERSION_UNIT (0x09)
#define MPI_HEADER_VERSION_DEV (0x00)
#define MPI_HEADER_VERSION_UNIT_MASK (0xFF00)
#define MPI_HEADER_VERSION_UNIT_SHIFT (8)
@ -122,7 +141,11 @@
*
*****************************************************************************/
/* S y s t e m D o o r b e l l */
/*
* Defines for working with the System Doorbell register.
* Values for doorbell function codes are included in the section that defines
* all the function codes (further on in this file).
*/
#define MPI_DOORBELL_OFFSET (0x00000000)
#define MPI_DOORBELL_ACTIVE (0x08000000) /* DoorbellUsed */
#define MPI_DOORBELL_USED (MPI_DOORBELL_ACTIVE)
@ -134,6 +157,13 @@
#define MPI_DOORBELL_ADD_DWORDS_MASK (0x00FF0000)
#define MPI_DOORBELL_ADD_DWORDS_SHIFT (16)
#define MPI_DOORBELL_DATA_MASK (0x0000FFFF)
#define MPI_DOORBELL_FUNCTION_SPECIFIC_MASK (0x0000FFFF)
/* values for Host Buffer Access Control doorbell function */
#define MPI_DB_HPBAC_VALUE_MASK (0x0000F000)
#define MPI_DB_HPBAC_ENABLE_ACCESS (0x01)
#define MPI_DB_HPBAC_DISABLE_ACCESS (0x02)
#define MPI_DB_HPBAC_FREE_BUFFER (0x03)
#define MPI_WRITE_SEQUENCE_OFFSET (0x00000004)
@ -257,16 +287,18 @@
#define MPI_FUNCTION_SMP_PASSTHROUGH (0x1A)
#define MPI_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B)
#define MPI_FUNCTION_SATA_PASSTHROUGH (0x1C)
#define MPI_DIAG_BUFFER_POST (0x1D)
#define MPI_DIAG_RELEASE (0x1E)
#define MPI_FUNCTION_SCSI_IO_32 (0x1F)
#define MPI_FUNCTION_DIAG_BUFFER_POST (0x1D)
#define MPI_FUNCTION_DIAG_RELEASE (0x1E)
#define MPI_FUNCTION_LAN_SEND (0x20)
#define MPI_FUNCTION_LAN_RECEIVE (0x21)
#define MPI_FUNCTION_LAN_RESET (0x22)
#define MPI_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24)
#define MPI_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25)
#define MPI_FUNCTION_INBAND_BUFFER_POST (0x28)
#define MPI_FUNCTION_INBAND_SEND (0x29)
#define MPI_FUNCTION_INBAND_RSP (0x2A)
@ -276,6 +308,7 @@
#define MPI_FUNCTION_IO_UNIT_RESET (0x41)
#define MPI_FUNCTION_HANDSHAKE (0x42)
#define MPI_FUNCTION_REPLY_FRAME_REMOVAL (0x43)
#define MPI_FUNCTION_HOST_PAGEBUF_ACCESS_CONTROL (0x44)
/* standard version format */
@ -328,8 +361,8 @@ typedef struct _SGE_SIMPLE_UNION
U32 Address32;
U64 Address64;
}u;
} SGESimpleUnion_t, MPI_POINTER pSGESimpleUnion_t,
SGE_SIMPLE_UNION, MPI_POINTER PTR_SGE_SIMPLE_UNION;
} SGE_SIMPLE_UNION, MPI_POINTER PTR_SGE_SIMPLE_UNION,
SGESimpleUnion_t, MPI_POINTER pSGESimpleUnion_t;
/****************************************************************************/
/* Chain element structures */
@ -648,27 +681,21 @@ typedef struct _MSG_DEFAULT_REPLY
#define MPI_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C)
/****************************************************************************/
/* For use by SCSI Initiator and SCSI Target end-to-end data protection */
/****************************************************************************/
#define MPI_IOCSTATUS_EEDP_CRC_ERROR (0x004D)
#define MPI_IOCSTATUS_EEDP_LBA_TAG_ERROR (0x004E)
#define MPI_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F)
/****************************************************************************/
/* SCSI (SPI & FCP) target values */
/* SCSI Target values */
/****************************************************************************/
#define MPI_IOCSTATUS_TARGET_PRIORITY_IO (0x0060)
#define MPI_IOCSTATUS_TARGET_INVALID_PORT (0x0061)
#define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX (0x0062) /* obsolete */
#define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX (0x0062) /* obsolete name */
#define MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062)
#define MPI_IOCSTATUS_TARGET_ABORTED (0x0063)
#define MPI_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064)
#define MPI_IOCSTATUS_TARGET_NO_CONNECTION (0x0065)
#define MPI_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A)
#define MPI_IOCSTATUS_TARGET_STS_DATA_NOT_SENT (0x006B)
#define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D)
#define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E)
#define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F)
/****************************************************************************/
/* Additional FCP target values (obsolete) */
@ -707,6 +734,7 @@ typedef struct _MSG_DEFAULT_REPLY
/****************************************************************************/
#define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090)
#define MPI_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091)
/****************************************************************************/
/* Inband values */

File diff suppressed because it is too large Load Diff

View File

@ -1,12 +1,12 @@
/*
* Copyright (c) 2000-2003 LSI Logic Corporation.
* Copyright (c) 2000-2004 LSI Logic Corporation.
*
*
* Name: mpi_fc.h
* Title: MPI Fibre Channel messages and structures
* Creation Date: June 12, 2000
*
* mpi_fc.h Version: 01.05.xx
* mpi_fc.h Version: 01.05.01
*
* Version History
* ---------------
@ -36,6 +36,9 @@
* 09-28-01 01.02.02 Change name of reserved field in
* MSG_LINK_SERVICE_RSP_REPLY.
* 05-31-02 01.02.03 Adding AliasIndex to FC Direct Access requests.
* 01-16-04 01.02.04 Added define for MPI_FC_PRIM_SEND_FLAGS_ML_RESET_LINK.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Original release for MPI v1.5.
* --------------------------------------------------------------------------
*/

View File

@ -3,25 +3,28 @@
MPI Header File Change History
==============================
Copyright (c) 2000-2001 LSI Logic Corporation.
Copyright (c) 2000-2005 LSI Logic Corporation.
---------------------------------------
Header Set Release Version: 01.01.10
Header Set Release Date: 04-09-01
Header Set Release Version: 01.05.09
Header Set Release Date: 03-11-05
---------------------------------------
Filename Current version Prior version
---------- --------------- -------------
mpi.h 01.01.07 01.01.06
mpi_ioc.h 01.01.07 01.01.06
mpi_cnfg.h 01.01.11 01.01.10
mpi_init.h 01.01.05 01.01.04
mpi_targ.h 01.01.04 01.01.04
mpi_fc.h 01.01.07 01.01.06
mpi_lan.h 01.01.03 01.01.03
mpi_raid.h 01.01.02 01.01.02
mpi_type.h 01.01.02 01.01.02
mpi_history.txt 01.01.09 01.01.09
mpi.h 01.05.07 01.05.06
mpi_ioc.h 01.05.08 01.05.07
mpi_cnfg.h 01.05.08 01.05.07
mpi_init.h 01.05.04 01.05.03
mpi_targ.h 01.05.04 01.05.03
mpi_fc.h 01.05.01 01.05.01
mpi_lan.h 01.05.01 01.05.01
mpi_raid.h 01.05.02 01.05.02
mpi_tool.h 01.05.03 01.05.03
mpi_inb.h 01.05.01 01.05.01
mpi_sas.h 01.05.01 01.05.01
mpi_type.h 01.05.01 01.05.01
mpi_history.txt 01.05.09 01.05.08
* Date Version Description
@ -53,6 +56,38 @@ mpi.h
* Added function codes for RAID.
* 04-09-01 01.01.07 Added alternate define for MPI_DOORBELL_ACTIVE,
* MPI_DOORBELL_USED, to better match the spec.
* 08-08-01 01.02.01 Original release for v1.2 work.
* Changed MPI_VERSION_MINOR from 0x01 to 0x02.
* Added define MPI_FUNCTION_TOOLBOX.
* 09-28-01 01.02.02 New function code MPI_SCSI_ENCLOSURE_PROCESSOR.
* 11-01-01 01.02.03 Changed name to MPI_FUNCTION_SCSI_ENCLOSURE_PROCESSOR.
* 03-14-02 01.02.04 Added MPI_HEADER_VERSION_ defines.
* 05-31-02 01.02.05 Bumped MPI_HEADER_VERSION_UNIT.
* 07-12-02 01.02.06 Added define for MPI_FUNCTION_MAILBOX.
* 09-16-02 01.02.07 Bumped value for MPI_HEADER_VERSION_UNIT.
* 11-15-02 01.02.08 Added define MPI_IOCSTATUS_TARGET_INVALID_IO_INDEX and
* obsoleted define MPI_IOCSTATUS_TARGET_INVALID_IOCINDEX.
* 04-01-03 01.02.09 New IOCStatus code: MPI_IOCSTATUS_FC_EXCHANGE_CANCELED
* 06-26-03 01.02.10 Bumped MPI_HEADER_VERSION_UNIT value.
* 01-16-04 01.02.11 Added define for MPI_IOCLOGINFO_TYPE_SHIFT.
* 04-29-04 01.02.12 Added function codes for MPI_FUNCTION_DIAG_BUFFER_POST
* and MPI_FUNCTION_DIAG_RELEASE.
* Added MPI_IOCSTATUS_DIAGNOSTIC_RELEASED define.
* Bumped MPI_HEADER_VERSION_UNIT value.
* 05-11-04 01.03.01 Bumped MPI_VERSION_MINOR for MPI v1.3.
* Added codes for Inband.
* 08-19-04 01.05.01 Added defines for Host Buffer Access Control doorbell.
* Added define for offset of High Priority Request Queue.
* Added new function codes and new IOCStatus codes.
* Added a IOCLogInfo type of SAS.
* 12-07-04 01.05.02 Bumped MPI_HEADER_VERSION_UNIT.
* 12-09-04 01.05.03 Bumped MPI_HEADER_VERSION_UNIT.
* 01-15-05 01.05.04 Bumped MPI_HEADER_VERSION_UNIT.
* 02-09-05 01.05.05 Bumped MPI_HEADER_VERSION_UNIT.
* 02-22-05 01.05.06 Bumped MPI_HEADER_VERSION_UNIT.
* 03-11-05 01.05.07 Removed function codes for SCSI IO 32 and
* TargetAssistExtended requests.
* Removed EEDP IOCStatus codes.
* --------------------------------------------------------------------------
mpi_ioc.h
@ -81,6 +116,49 @@ mpi_ioc.h
* 03-27-01 01.01.06 Added defines for ProductId field of MPI_FW_HEADER.
* Added structure offset comments.
* 04-09-01 01.01.07 Added structure EVENT_DATA_EVENT_CHANGE.
* 08-08-01 01.02.01 Original release for v1.2 work.
* New format for FWVersion and ProductId in
* MSG_IOC_FACTS_REPLY and MPI_FW_HEADER.
* 08-31-01 01.02.02 Addded event MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE and
* related structure and defines.
* Added event MPI_EVENT_ON_BUS_TIMER_EXPIRED.
* Added MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE.
* Replaced a reserved field in MSG_IOC_FACTS_REPLY with
* IOCExceptions and changed DataImageSize to reserved.
* Added MPI_FW_DOWNLOAD_ITYPE_NVSTORE_DATA and
* MPI_FW_UPLOAD_ITYPE_NVDATA.
* 09-28-01 01.02.03 Modified Event Data for Integrated RAID.
* 11-01-01 01.02.04 Added defines for MPI_EXT_IMAGE_HEADER ImageType field.
* 03-14-02 01.02.05 Added HeaderVersion field to MSG_IOC_FACTS_REPLY.
* 05-31-02 01.02.06 Added define for
* MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID.
* Added AliasIndex to EVENT_DATA_LOGOUT structure.
* 04-01-03 01.02.07 Added defines for MPI_FW_HEADER_SIGNATURE_.
* 06-26-03 01.02.08 Added new values to the product family defines.
* 04-29-04 01.02.09 Added IOCCapabilities field to MSG_IOC_FACTS_REPLY and
* added related defines.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Added four new fields to MSG_IOC_INIT.
* Added three new fields to MSG_IOC_FACTS_REPLY.
* Defined four new bits for the IOCCapabilities field of
* the IOCFacts reply.
* Added two new PortTypes for the PortFacts reply.
* Added six new events along with their EventData
* structures.
* Added a new MsgFlag to the FwDownload request to
* indicate last segment.
* Defined a new image type of boot loader.
* Added FW family codes for SAS product families.
* 10-05-04 01.05.02 Added ReplyFifoHostSignalingAddr field to
* MSG_IOC_FACTS_REPLY.
* 12-07-04 01.05.03 Added more defines for SAS Discovery Error event.
* 12-09-04 01.05.04 Added Unsupported device to SAS Device event.
* 01-15-05 01.05.05 Added event data for SAS SES Event.
* 02-09-05 01.05.06 Added MPI_FW_UPLOAD_ITYPE_FW_BACKUP define.
* 02-22-05 01.05.07 Added Host Page Buffer Persistent flag to IOC Facts
* Reply and IOC Init Request.
* 03-11-05 01.05.08 Added family code for 1068E family.
* Removed IOCFacts Reply EEDP Capability bit.
* --------------------------------------------------------------------------
mpi_cnfg.h
@ -142,6 +220,166 @@ mpi_cnfg.h
* Added IO Unit Page 3.
* Modified defines for Scsi Port Page 2.
* Modified RAID Volume Pages.
* 08-08-01 01.02.01 Original release for v1.2 work.
* Added SepID and SepBus to RVP2 IMPhysicalDisk struct.
* Added defines for the SEP bits in RVP2 VolumeSettings.
* Modified the DeviceSettings field in RVP2 to use the
* proper structure.
* Added defines for SES, SAF-TE, and cross channel for
* IOCPage2 CapabilitiesFlags.
* Removed define for MPI_IOUNITPAGE2_FLAGS_RAID_DISABLE.
* Removed define for
* MPI_SCSIPORTPAGE2_PORT_FLAGS_PARITY_ENABLE.
* Added define for MPI_CONFIG_PAGEATTR_RO_PERSISTENT.
* 08-29-01 01.02.02 Fixed value for MPI_MANUFACTPAGE_DEVID_53C1035.
* Added defines for MPI_FCPORTPAGE1_FLAGS_HARD_ALPA_ONLY
* and MPI_FCPORTPAGE1_FLAGS_IMMEDIATE_ERROR_REPLY.
* Removed MPI_SCSIPORTPAGE0_CAP_PACING_TRANSFERS,
* MPI_SCSIDEVPAGE0_NP_PACING_TRANSFERS, and
* MPI_SCSIDEVPAGE1_RP_PACING_TRANSFERS, and
* MPI_SCSIDEVPAGE1_CONF_PPR_ALLOWED.
* Added defines for MPI_SCSIDEVPAGE1_CONF_WDTR_DISALLOWED
* and MPI_SCSIDEVPAGE1_CONF_SDTR_DISALLOWED.
* Added OnBusTimerValue to CONFIG_PAGE_SCSI_PORT_1.
* Added rejected bits to SCSI Device Page 0 Information.
* Increased size of ALPA array in FC Port Page 2 by one
* and removed a one byte reserved field.
* 09-28-01 01.02.03 Swapped NegWireSpeedLow and NegWireSpeedLow in
* CONFIG_PAGE_LAN_1 to match preferred 64-bit ordering.
* Added structures for Manufacturing Page 4, IO Unit
* Page 3, IOC Page 3, IOC Page 4, RAID Volume Page 0, and
* RAID PhysDisk Page 0.
* 10-04-01 01.02.04 Added define for MPI_CONFIG_PAGETYPE_RAID_PHYSDISK.
* Modified some of the new defines to make them 32
* character unique.
* Modified how variable length pages (arrays) are defined.
* Added generic defines for hot spare pools and RAID
* volume types.
* 11-01-01 01.02.05 Added define for MPI_IOUNITPAGE1_DISABLE_IR.
* 03-14-02 01.02.06 Added PCISlotNum field to CONFIG_PAGE_IOC_1 along with
* related define, and bumped the page version define.
* 05-31-02 01.02.07 Added a Flags field to CONFIG_PAGE_IOC_2_RAID_VOL in a
* reserved byte and added a define.
* Added define for
* MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE.
* Added new config page: CONFIG_PAGE_IOC_5.
* Added MaxAliases, MaxHardAliases, and NumCurrentAliases
* fields to CONFIG_PAGE_FC_PORT_0.
* Added AltConnector and NumRequestedAliases fields to
* CONFIG_PAGE_FC_PORT_1.
* Added new config page: CONFIG_PAGE_FC_PORT_10.
* 07-12-02 01.02.08 Added more MPI_MANUFACTPAGE_DEVID_ defines.
* Added additional MPI_SCSIDEVPAGE0_NP_ defines.
* Added more MPI_SCSIDEVPAGE1_RP_ defines.
* Added define for
* MPI_SCSIDEVPAGE1_CONF_EXTENDED_PARAMS_ENABLE.
* Added new config page: CONFIG_PAGE_SCSI_DEVICE_3.
* Modified MPI_FCPORTPAGE5_FLAGS_ defines.
* 09-16-02 01.02.09 Added MPI_SCSIDEVPAGE1_CONF_FORCE_PPR_MSG define.
* 11-15-02 01.02.10 Added ConnectedID defines for CONFIG_PAGE_SCSI_PORT_0.
* Added more Flags defines for CONFIG_PAGE_FC_PORT_1.
* Added more Flags defines for CONFIG_PAGE_FC_DEVICE_0.
* 04-01-03 01.02.11 Added RR_TOV field and additional Flags defines for
* CONFIG_PAGE_FC_PORT_1.
* Added define MPI_FCPORTPAGE5_FLAGS_DISABLE to disable
* an alias.
* Added more device id defines.
* 06-26-03 01.02.12 Added MPI_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID define.
* Added TargetConfig and IDConfig fields to
* CONFIG_PAGE_SCSI_PORT_1.
* Added more PortFlags defines for CONFIG_PAGE_SCSI_PORT_2
* to control DV.
* Added more Flags defines for CONFIG_PAGE_FC_PORT_1.
* In CONFIG_PAGE_FC_DEVICE_0, replaced Reserved1 field
* with ADISCHardALPA.
* Added MPI_FC_DEVICE_PAGE0_PROT_FCP_RETRY define.
* 01-16-04 01.02.13 Added InitiatorDeviceTimeout and InitiatorIoPendTimeout
* fields and related defines to CONFIG_PAGE_FC_PORT_1.
* Added define for
* MPI_FCPORTPAGE1_FLAGS_SOFT_ALPA_FALLBACK.
* Added new fields to the substructures of
* CONFIG_PAGE_FC_PORT_10.
* 04-29-04 01.02.14 Added define for IDP bit for CONFIG_PAGE_SCSI_PORT_0,
* CONFIG_PAGE_SCSI_DEVICE_0, and
* CONFIG_PAGE_SCSI_DEVICE_1. Also bumped Page Version for
* these pages.
* 05-11-04 01.03.01 Added structure for CONFIG_PAGE_INBAND_0.
* 08-19-04 01.05.01 Modified MSG_CONFIG request to support extended config
* pages.
* Added a new structure for extended config page header.
* Added new extended config pages types and structures for
* SAS IO Unit, SAS Expander, SAS Device, and SAS PHY.
* Replaced a reserved byte in CONFIG_PAGE_MANUFACTURING_4
* to add a Flags field.
* Two new Manufacturing config pages (5 and 6).
* Two new bits defined for IO Unit Page 1 Flags field.
* Modified CONFIG_PAGE_IO_UNIT_2 to add three new fields
* to specify the BIOS boot device.
* Four new Flags bits defined for IO Unit Page 2.
* Added IO Unit Page 4.
* Added EEDP Flags settings to IOC Page 1.
* Added new BIOS Page 1 config page.
* 10-05-04 01.05.02 Added define for
* MPI_IOCPAGE1_INITIATOR_CONTEXT_REPLY_DISABLE.
* Added new Flags field to CONFIG_PAGE_MANUFACTURING_5 and
* associated defines.
* Added more defines for SAS IO Unit Page 0
* DiscoveryStatus field.
* Added define for MPI_SAS_IOUNIT0_DS_SUBTRACTIVE_LINK
* and MPI_SAS_IOUNIT0_DS_TABLE_LINK.
* Added defines for Physical Mapping Modes to SAS IO Unit
* Page 2.
* Added define for
* MPI_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH.
* 10-27-04 01.05.03 Added defines for new SAS PHY page addressing mode.
* Added defines for MaxTargetSpinUp to BIOS Page 1.
* Added 5 new ControlFlags defines for SAS IO Unit
* Page 1.
* Added MaxNumPhysicalMappedIDs field to SAS IO Unit
* Page 2.
* Added AccessStatus field to SAS Device Page 0 and added
* new Flags bits for supported SATA features.
* 12-07-04 01.05.04 Added config page structures for BIOS Page 2, RAID
* Volume Page 1, and RAID Physical Disk Page 1.
* Replaced IO Unit Page 1 BootTargetID,BootBus, and
* BootAdapterNum with reserved field.
* Added DataScrubRate and ResyncRate to RAID Volume
* Page 0.
* Added MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT
* define.
* 12-09-04 01.05.05 Added Target Mode Large CDB Enable to FC Port Page 1
* Flags field.
* Added Auto Port Config flag define for SAS IOUNIT
* Page 1 ControlFlags.
* Added Disabled bad Phy define to Expander Page 1
* Discovery Info field.
* Added SAS/SATA device support to SAS IOUnit Page 1
* ControlFlags.
* Added Unsupported device to SAS Dev Page 0 Flags field
* Added disable use SATA Hash Address for SAS IOUNIT
* page 1 in ControlFields.
* 01-15-05 01.05.06 Added defaults for data scrub rate and resync rate to
* Manufacturing Page 4.
* Added new defines for BIOS Page 1 IOCSettings field.
* Added ExtDiskIdentifier field to RAID Physical Disk
* Page 0.
* Added new defines for SAS IO Unit Page 1 ControlFlags
* and to SAS Device Page 0 Flags to control SATA devices.
* Added defines and structures for the new Log Page 0, a
* new type of configuration page.
* 02-09-05 01.05.07 Added InactiveStatus field to RAID Volume Page 0.
* Added WWID field to RAID Volume Page 1.
* Added PhysicalPort field to SAS Expander pages 0 and 1.
* 03-11-05 01.05.08 Removed the EEDP flags from IOC Page 1.
* Added Enclosure/Slot boot device format to BIOS Page 2.
* New status value for RAID Volume Page 0 VolumeStatus
* (VolumeState subfield).
* New value for RAID Physical Page 0 InactiveStatus.
* Added Inactive Volume Member flag RAID Physical Disk
* Page 0 PhysDiskStatus field.
* New physical mapping mode in SAS IO Unit Page 2.
* Added CONFIG_PAGE_SAS_ENCLOSURE_0.
* Added Slot and Enclosure fields to SAS Device Page 0.
* --------------------------------------------------------------------------
mpi_init.h
@ -154,6 +392,32 @@ mpi_init.h
* 02-20-01 01.01.03 Started using MPI_POINTER.
* 03-27-01 01.01.04 Added structure offset comments.
* 04-10-01 01.01.05 Added new MsgFlag for MSG_SCSI_TASK_MGMT.
* 08-08-01 01.02.01 Original release for v1.2 work.
* 08-29-01 01.02.02 Added MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET.
* Added MPI_SCSI_STATE_QUEUE_TAG_REJECTED for
* MSG_SCSI_IO_REPLY.
* 09-28-01 01.02.03 Added structures and defines for SCSI Enclosure
* Processor messages.
* 10-04-01 01.02.04 Added defines for SEP request Action field.
* 05-31-02 01.02.05 Added MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR define
* for SCSI IO requests.
* 11-15-02 01.02.06 Added special extended SCSI Status defines for FCP.
* 06-26-03 01.02.07 Added MPI_SCSI_STATUS_FCPEXT_UNASSIGNED define.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Added MsgFlags defines for EEDP to SCSI IO request.
* Added new word to MSG_SCSI_IO_REPLY to add TaskTag field
* and a reserved U16.
* Added new MSG_SCSI_IO32_REQUEST structure.
* Added a TaskType of Clear Task Set to SCSI
* Task Management request.
* 12-07-04 01.05.02 Added support for Task Management Query Task.
* 01-15-05 01.05.03 Modified SCSI Enclosure Processor Request to support
* WWID addressing.
* 03-11-05 01.05.04 Removed EEDP flags from SCSI IO Request.
* Removed SCSI IO 32 Request.
* Modified SCSI Enclosure Processor Request and Reply to
* support Enclosure/Slot addressing rather than WWID
* addressing.
* --------------------------------------------------------------------------
mpi_targ.h
@ -170,6 +434,33 @@ mpi_targ.h
* Added structures for MPI_TARGET_SCSI_SPI_CMD_BUFFER and
* MPI_TARGET_FCP_CMD_BUFFER.
* 03-27-01 01.01.04 Added structure offset comments.
* 08-08-01 01.02.01 Original release for v1.2 work.
* 09-28-01 01.02.02 Added structure for MPI_TARGET_SCSI_SPI_STATUS_IU.
* Added PriorityReason field to some replies and
* defined more PriorityReason codes.
* Added some defines for to support previous version
* of MPI.
* 10-04-01 01.02.03 Added PriorityReason to MSG_TARGET_ERROR_REPLY.
* 11-01-01 01.02.04 Added define for TARGET_STATUS_SEND_FLAGS_HIGH_PRIORITY.
* 03-14-02 01.02.05 Modified MPI_TARGET_FCP_RSP_BUFFER to get the proper
* byte ordering.
* 05-31-02 01.02.06 Modified TARGET_MODE_REPLY_ALIAS_MASK to only include
* one bit.
* Added AliasIndex field to MPI_TARGET_FCP_CMD_BUFFER.
* 09-16-02 01.02.07 Added flags for confirmed completion.
* Added PRIORITY_REASON_TARGET_BUSY.
* 11-15-02 01.02.08 Added AliasID field to MPI_TARGET_SCSI_SPI_CMD_BUFFER.
* 04-01-03 01.02.09 Added OptionalOxid field to MPI_TARGET_FCP_CMD_BUFFER.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Added new request message structures for
* MSG_TARGET_CMD_BUF_POST_BASE_REQUEST,
* MSG_TARGET_CMD_BUF_POST_LIST_REQUEST, and
* MSG_TARGET_ASSIST_EXT_REQUEST.
* Added new structures for SAS SSP Command buffer, SSP
* Task buffer, and SSP Status IU.
* 10-05-04 01.05.02 MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY added.
* 02-22-05 01.05.03 Changed a comment.
* 03-11-05 01.05.04 Removed TargetAssistExtended Request.
* --------------------------------------------------------------------------
mpi_fc.h
@ -192,6 +483,13 @@ mpi_fc.h
* Added MPI_FC_PRIM_SEND_FLAGS_RESET_LINK define.
* Added structure offset comments.
* 04-09-01 01.01.07 Added RspLength field to MSG_LINK_SERVICE_RSP_REQUEST.
* 08-08-01 01.02.01 Original release for v1.2 work.
* 09-28-01 01.02.02 Change name of reserved field in
* MSG_LINK_SERVICE_RSP_REPLY.
* 05-31-02 01.02.03 Adding AliasIndex to FC Direct Access requests.
* 01-16-04 01.02.04 Added define for MPI_FC_PRIM_SEND_FLAGS_ML_RESET_LINK.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Original release for MPI v1.5.
* --------------------------------------------------------------------------
mpi_lan.h
@ -209,11 +507,56 @@ mpi_lan.h
* 11-02-00 01.01.01 Original release for post 1.0 work
* 02-20-01 01.01.02 Started using MPI_POINTER.
* 03-27-01 01.01.03 Added structure offset comments.
* 08-08-01 01.02.01 Original release for v1.2 work.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Original release for MPI v1.5.
* --------------------------------------------------------------------------
mpi_raid.h
* 02-27-01 01.01.01 Original release for this file.
* 03-27-01 01.01.02 Added structure offset comments.
* 08-08-01 01.02.01 Original release for v1.2 work.
* 08-29-01 01.02.02 Added DIAG_DATA_UPLOAD_HEADER and related defines.
* 09-28-01 01.02.02 Major rework for MPI v1.2 Integrated RAID changes.
* 10-04-01 01.02.03 Added ActionData defines for
* MPI_RAID_ACTION_DELETE_VOLUME action.
* 11-01-01 01.02.04 Added define for MPI_RAID_ACTION_ADATA_DO_NOT_SYNC.
* 03-14-02 01.02.05 Added define for MPI_RAID_ACTION_ADATA_LOW_LEVEL_INIT.
* 05-07-02 01.02.06 Added define for MPI_RAID_ACTION_ACTIVATE_VOLUME,
* MPI_RAID_ACTION_INACTIVATE_VOLUME, and
* MPI_RAID_ACTION_ADATA_INACTIVATE_ALL.
* 07-12-02 01.02.07 Added structures for Mailbox request and reply.
* 11-15-02 01.02.08 Added missing MsgContext field to MSG_MAILBOX_REQUEST.
* 04-01-03 01.02.09 New action data option flag for
* MPI_RAID_ACTION_DELETE_VOLUME.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Original release for MPI v1.5.
* 01-15-05 01.05.02 Added defines for the two new RAID Actions for
* _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE.
* --------------------------------------------------------------------------
mpi_tool.h
* 08-08-01 01.02.01 Original release.
* 08-29-01 01.02.02 Added DIAG_DATA_UPLOAD_HEADER and related defines.
* 01-16-04 01.02.03 Added defines and structures for new tools
*. MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL and
* MPI_TOOLBOX_FC_MANAGEMENT_TOOL.
* 04-29-04 01.02.04 Added message structures for Diagnostic Buffer Post and
* Diagnostic Release requests and replies.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Original release for MPI v1.5.
* 10-06-04 01.05.02 Added define for MPI_DIAG_BUF_TYPE_COUNT.
* 02-09-05 01.05.03 Added frame size option to FC management tool.
* Added Beacon tool to the Toolbox.
* --------------------------------------------------------------------------
mpi_inb.h
* 05-11-04 01.03.01 Original release.
* 08-19-04 01.05.01 Original release for MPI v1.5.
* --------------------------------------------------------------------------
mpi_sas.h
* 08-19-04 01.05.01 Original release.
* --------------------------------------------------------------------------
mpi_type.h
@ -221,21 +564,83 @@ mpi_type.h
* 06-06-00 01.00.01 Update version number for 1.0 release.
* 11-02-00 01.01.01 Original release for post 1.0 work
* 02-20-01 01.01.02 Added define and ifdef for MPI_POINTER.
* 08-08-01 01.02.01 Original release for v1.2 work.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Original release for MPI v1.5.
* --------------------------------------------------------------------------
mpi_history.txt Parts list history
Filename 01.01.10
Filename 01.05.09
---------- --------
mpi.h 01.01.07
mpi_ioc.h 01.01.07
mpi_cnfg.h 01.01.11
mpi_init.h 01.01.05
mpi_targ.h 01.01.04
mpi_fc.h 01.01.07
mpi_lan.h 01.01.03
mpi_raid.h 01.01.02
mpi_type.h 01.01.02
mpi.h 01.05.07
mpi_ioc.h 01.05.08
mpi_cnfg.h 01.05.08
mpi_init.h 01.05.04
mpi_targ.h 01.05.04
mpi_fc.h 01.05.01
mpi_lan.h 01.05.01
mpi_raid.h 01.05.02
mpi_tool.h 01.05.03
mpi_inb.h 01.05.01
mpi_sas.h 01.05.01
mpi_type.h 01.05.01
Filename 01.05.08 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03
---------- -------- -------- -------- -------- -------- --------
mpi.h 01.05.06 01.05.05 01.05.04 01.05.03 01.05.02 01.05.01
mpi_ioc.h 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03 01.05.02
mpi_cnfg.h 01.05.07 01.05.07 01.05.06 01.05.05 01.05.04 01.05.03
mpi_init.h 01.05.03 01.05.03 01.05.03 01.05.02 01.05.02 01.05.01
mpi_targ.h 01.05.03 01.05.02 01.05.02 01.05.02 01.05.02 01.05.02
mpi_fc.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
mpi_lan.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
mpi_raid.h 01.05.02 01.05.02 01.05.02 01.05.01 01.05.01 01.05.01
mpi_tool.h 01.05.03 01.05.03 01.05.02 01.05.02 01.05.02 01.05.02
mpi_inb.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
mpi_sas.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
mpi_type.h 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01 01.05.01
Filename 01.05.02 01.05.01 01.03.01 01.02.14 01.02.13 01.02.12
---------- -------- -------- -------- -------- -------- --------
mpi.h 01.05.01 01.05.01 01.03.01 01.02.12 01.02.11 01.02.10
mpi_ioc.h 01.05.02 01.05.01 01.03.01 01.02.09 01.02.08 01.02.08
mpi_cnfg.h 01.05.02 01.05.01 01.03.01 01.02.14 01.02.13 01.02.12
mpi_init.h 01.05.01 01.05.01 01.03.01 01.02.07 01.02.07 01.02.07
mpi_targ.h 01.05.02 01.05.01 01.03.01 01.02.09 01.02.09 01.02.09
mpi_fc.h 01.05.01 01.05.01 01.03.01 01.02.04 01.02.04 01.02.03
mpi_lan.h 01.05.01 01.05.01 01.03.01 01.02.01 01.02.01 01.02.01
mpi_raid.h 01.05.01 01.05.01 01.03.01 01.02.09 01.02.09 01.02.09
mpi_tool.h 01.05.02 01.05.01 01.03.01 01.02.01 01.02.01 01.02.01
mpi_inb.h 01.05.01 01.05.01 01.03.01
mpi_sas.h 01.05.01 01.05.01
mpi_type.h 01.05.01 01.05.01 01.03.01 01.02.04 01.02.03 01.02.02
Filename 01.02.11 01.02.10 01.02.09 01.02.08 01.02.07 01.02.06
---------- -------- -------- -------- -------- -------- --------
mpi.h 01.02.09 01.02.08 01.02.07 01.02.06 01.02.05 01.02.04
mpi_ioc.h 01.02.07 01.02.06 01.02.06 01.02.06 01.02.06 01.02.05
mpi_cnfg.h 01.02.11 01.02.10 01.02.09 01.02.08 01.02.07 01.02.06
mpi_init.h 01.02.06 01.02.06 01.02.05 01.02.05 01.02.05 01.02.04
mpi_targ.h 01.02.09 01.02.08 01.02.07 01.02.06 01.02.06 01.02.05
mpi_fc.h 01.02.03 01.02.03 01.02.03 01.02.03 01.02.03 01.02.02
mpi_lan.h 01.02.01 01.02.01 01.02.01 01.02.01 01.02.01 01.02.01
mpi_raid.h 01.02.09 01.02.08 01.02.07 01.02.07 01.02.06 01.02.05
mpi_tool.h 01.02.01 01.02.01 01.02.01 01.02.01 01.02.01 01.02.01
mpi_type.h 01.02.02 01.02.02 01.02.02 01.02.02 01.02.02 01.02.02
Filename 01.02.05 01.02.04 01.02.03 01.02.02 01.02.01 01.01.10
---------- -------- -------- -------- -------- -------- --------
mpi.h 01.02.03 01.02.02 01.02.02 01.02.01 01.02.01 01.01.07
mpi_ioc.h 01.02.04 01.02.03 01.02.03 01.02.02 01.02.01 01.01.07
mpi_cnfg.h 01.02.05 01.02.04 01.02.03 01.02.02 01.02.01 01.01.11
mpi_init.h 01.02.04 01.02.04 01.02.03 01.02.02 01.02.01 01.01.05
mpi_targ.h 01.02.04 01.02.03 01.02.02 01.02.01 01.02.01 01.01.04
mpi_fc.h 01.02.02 01.02.02 01.02.02 01.02.01 01.02.01 01.01.07
mpi_lan.h 01.02.01 01.02.01 01.02.01 01.02.01 01.02.01 01.01.03
mpi_raid.h 01.02.04 01.02.03 01.02.02 01.02.01 01.02.01 01.01.02
mpi_tool.h 01.02.02 01.02.02 01.02.02 01.02.02 01.02.01
mpi_type.h 01.02.02 01.02.02 01.02.02 01.02.02 01.02.01 01.01.02
Filename 01.01.09 01.01.08 01.01.07 01.01.06 01.01.05 01.01.04
---------- -------- -------- -------- -------- -------- --------

View File

@ -1,19 +1,20 @@
/*
* Copyright (c) 2003 LSI Logic Corporation.
* Copyright (c) 2003-2004 LSI Logic Corporation.
*
*
* Name: mpi_inb.h
* Title: MPI Inband structures and definitions
* Creation Date: September 30, 2003
*
* mpi_inb.h Version: 01.03.xx
* mpi_inb.h Version: 01.05.01
*
* Version History
* ---------------
*
* Date Version Description
* -------- -------- ------------------------------------------------------
* ??-??-?? 01.03.01 Original release.
* 05-11-04 01.03.01 Original release.
* 08-19-04 01.05.01 Original release for MPI v1.5.
* --------------------------------------------------------------------------
*/

View File

@ -1,12 +1,12 @@
/*
* Copyright (c) 2000-2003 LSI Logic Corporation.
* Copyright (c) 2000-2005 LSI Logic Corporation.
*
*
* Name: mpi_init.h
* Title: MPI initiator mode messages and structures
* Creation Date: June 8, 2000
*
* mpi_init.h Version: 01.05.xx
* mpi_init.h Version: 01.05.04
*
* Version History
* ---------------
@ -33,6 +33,21 @@
* for SCSI IO requests.
* 11-15-02 01.02.06 Added special extended SCSI Status defines for FCP.
* 06-26-03 01.02.07 Added MPI_SCSI_STATUS_FCPEXT_UNASSIGNED define.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Added MsgFlags defines for EEDP to SCSI IO request.
* Added new word to MSG_SCSI_IO_REPLY to add TaskTag field
* and a reserved U16.
* Added new MSG_SCSI_IO32_REQUEST structure.
* Added a TaskType of Clear Task Set to SCSI
* Task Management request.
* 12-07-04 01.05.02 Added support for Task Management Query Task.
* 01-15-05 01.05.03 Modified SCSI Enclosure Processor Request to support
* WWID addressing.
* 03-11-05 01.05.04 Removed EEDP flags from SCSI IO Request.
* Removed SCSI IO 32 Request.
* Modified SCSI Enclosure Processor Request and Reply to
* support Enclosure/Slot addressing rather than WWID
* addressing.
* --------------------------------------------------------------------------
*/
@ -76,20 +91,12 @@ typedef struct _MSG_SCSI_IO_REQUEST
#define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH (0x01)
#define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_32 (0x00)
#define MPI_SCSIIO_MSGFLGS_SENSE_WIDTH_64 (0x01)
#define MPI_SCSIIO_MSGFLGS_SENSE_LOCATION (0x02)
#define MPI_SCSIIO_MSGFLGS_SENSE_LOC_HOST (0x00)
#define MPI_SCSIIO_MSGFLGS_SENSE_LOC_IOC (0x02)
#define MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR (0x04)
#define MPI_SCSIIO_MSGFLGS_EEDP_TYPE_MASK (0xE0)
#define MPI_SCSIIO_MSGFLGS_EEDP_NONE (0x00)
#define MPI_SCSIIO_MSGFLGS_EEDP_RDPROTECT_T10 (0x20)
#define MPI_SCSIIO_MSGFLGS_EEDP_VRPROTECT_T10 (0x40)
#define MPI_SCSIIO_MSGFLGS_EEDP_WRPROTECT_T10 (0x60)
#define MPI_SCSIIO_MSGFLGS_EEDP_520_READ_MODE1 (0x20)
#define MPI_SCSIIO_MSGFLGS_EEDP_520_WRITE_MODE1 (0x40)
#define MPI_SCSIIO_MSGFLGS_EEDP_8_9_READ_MODE1 (0x60)
#define MPI_SCSIIO_MSGFLGS_EEDP_8_9_WRITE_MODE1 (0x80)
#define MPI_SCSIIO_MSGFLGS_CMD_DETERMINES_DATA_DIR (0x04)
/* SCSI IO LUN fields */
@ -148,6 +155,8 @@ typedef struct _MSG_SCSI_IO_REPLY
U32 TransferCount; /* 14h */
U32 SenseCount; /* 18h */
U32 ResponseInfo; /* 1Ch */
U16 TaskTag; /* 20h */
U16 Reserved1; /* 22h */
} MSG_SCSI_IO_REPLY, MPI_POINTER PTR_MSG_SCSI_IO_REPLY,
SCSIIOReply_t, MPI_POINTER pSCSIIOReply_t;
@ -190,32 +199,7 @@ typedef struct _MSG_SCSI_IO_REPLY
#define MPI_SCSI_RSP_INFO_TASK_MGMT_FAILED (0x05000000)
#define MPI_SCSI_RSP_INFO_SPI_LQ_INVALID_TYPE (0x06000000)
/****************************************************************************/
/* SCSI IO 32 Request message structure */
/****************************************************************************/
typedef struct _MSG_SCSI_IO32_REQUEST
{
U8 TargetID; /* 00h */
U8 Bus; /* 01h */
U8 ChainOffset; /* 02h */
U8 Function; /* 03h */
U8 CDBLength; /* 04h */
U8 SenseBufferLength; /* 05h */
U8 Reserved; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
U8 LUN[8]; /* 0Ch */
U32 Control; /* 14h */
U8 CDB[32]; /* 18h */
U32 DataLength; /* 38h */
U32 SenseBufferLowAddr; /* 3Ch */
SGE_IO_UNION SGL; /* 40h */
} MSG_SCSI_IO32_REQUEST, MPI_POINTER PTR_MSG_SCSI_IO32_REQUEST,
SCSIIO32Request_t, MPI_POINTER pSCSIIO32Request_t;
/* SCSI IO 32 uses the same defines as above for SCSI IO */
#define MPI_SCSI_TASKTAG_UNKNOWN (0xFFFF)
/****************************************************************************/
@ -247,6 +231,7 @@ typedef struct _MSG_SCSI_TASK_MGMT
#define MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS (0x04)
#define MPI_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05)
#define MPI_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06)
#define MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07)
/* MsgFlags bits */
#define MPI_SCSITASKMGMT_MSGFLAGS_TARGET_RESET_OPTION (0x00)
@ -260,7 +245,7 @@ typedef struct _MSG_SCSI_TASK_MGMT_REPLY
U8 Bus; /* 01h */
U8 MsgLength; /* 02h */
U8 Function; /* 03h */
U8 Reserved; /* 04h */
U8 ResponseCode; /* 04h */
U8 TaskType; /* 05h */
U8 Reserved1; /* 06h */
U8 MsgFlags; /* 07h */
@ -272,6 +257,15 @@ typedef struct _MSG_SCSI_TASK_MGMT_REPLY
} MSG_SCSI_TASK_MGMT_REPLY, MPI_POINTER PTR_MSG_SCSI_TASK_MGMT_REPLY,
SCSITaskMgmtReply_t, MPI_POINTER pSCSITaskMgmtReply_t;
/* ResponseCode values */
#define MPI_SCSITASKMGMT_RSP_TM_COMPLETE (0x00)
#define MPI_SCSITASKMGMT_RSP_INVALID_FRAME (0x02)
#define MPI_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED (0x04)
#define MPI_SCSITASKMGMT_RSP_TM_FAILED (0x05)
#define MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED (0x08)
#define MPI_SCSITASKMGMT_RSP_TM_INVALID_LUN (0x09)
#define MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC (0x80)
/****************************************************************************/
/* SCSI Enclosure Processor messages */
@ -284,11 +278,16 @@ typedef struct _MSG_SEP_REQUEST
U8 ChainOffset; /* 02h */
U8 Function; /* 03h */
U8 Action; /* 04h */
U8 Reserved1; /* 05h */
U8 Reserved2; /* 06h */
U8 Flags; /* 05h */
U8 Reserved1; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
U32 SlotStatus; /* 0Ch */
U32 Reserved2; /* 10h */
U32 Reserved3; /* 14h */
U32 Reserved4; /* 18h */
U16 Slot; /* 1Ch */
U16 EnclosureHandle; /* 1Eh */
} MSG_SEP_REQUEST, MPI_POINTER PTR_MSG_SEP_REQUEST,
SEPRequest_t, MPI_POINTER pSEPRequest_t;
@ -296,6 +295,10 @@ typedef struct _MSG_SEP_REQUEST
#define MPI_SEP_REQ_ACTION_WRITE_STATUS (0x00)
#define MPI_SEP_REQ_ACTION_READ_STATUS (0x01)
/* Flags defines */
#define MPI_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS (0x01)
#define MPI_SEP_REQ_FLAGS_BUS_TARGETID_ADDRESS (0x00)
/* SlotStatus bits for MSG_SEP_REQUEST */
#define MPI_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001)
#define MPI_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002)
@ -332,6 +335,9 @@ typedef struct _MSG_SEP_REPLY
U16 IOCStatus; /* 0Eh */
U32 IOCLogInfo; /* 10h */
U32 SlotStatus; /* 14h */
U32 Reserved4; /* 18h */
U16 Slot; /* 1Ch */
U16 EnclosureHandle; /* 1Eh */
} MSG_SEP_REPLY, MPI_POINTER PTR_MSG_SEP_REPLY,
SEPReply_t, MPI_POINTER pSEPReply_t;

View File

@ -1,12 +1,12 @@
/*
* Copyright (c) 2000-2003 LSI Logic Corporation.
* Copyright (c) 2000-2005 LSI Logic Corporation.
*
*
* Name: mpi_ioc.h
* Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
* Creation Date: August 11, 2000
*
* mpi_ioc.h Version: 01.05.xx
* mpi_ioc.h Version: 01.05.08
*
* Version History
* ---------------
@ -57,6 +57,30 @@
* Added AliasIndex to EVENT_DATA_LOGOUT structure.
* 04-01-03 01.02.07 Added defines for MPI_FW_HEADER_SIGNATURE_.
* 06-26-03 01.02.08 Added new values to the product family defines.
* 04-29-04 01.02.09 Added IOCCapabilities field to MSG_IOC_FACTS_REPLY and
* added related defines.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Added four new fields to MSG_IOC_INIT.
* Added three new fields to MSG_IOC_FACTS_REPLY.
* Defined four new bits for the IOCCapabilities field of
* the IOCFacts reply.
* Added two new PortTypes for the PortFacts reply.
* Added six new events along with their EventData
* structures.
* Added a new MsgFlag to the FwDownload request to
* indicate last segment.
* Defined a new image type of boot loader.
* Added FW family codes for SAS product families.
* 10-05-04 01.05.02 Added ReplyFifoHostSignalingAddr field to
* MSG_IOC_FACTS_REPLY.
* 12-07-04 01.05.03 Added more defines for SAS Discovery Error event.
* 12-09-04 01.05.04 Added Unsupported device to SAS Device event.
* 01-15-05 01.05.05 Added event data for SAS SES Event.
* 02-09-05 01.05.06 Added MPI_FW_UPLOAD_ITYPE_FW_BACKUP define.
* 02-22-05 01.05.07 Added Host Page Buffer Persistent flag to IOC Facts
* Reply and IOC Init Request.
* 03-11-05 01.05.08 Added family code for 1068E family.
* Removed IOCFacts Reply EEDP Capability bit.
* --------------------------------------------------------------------------
*/
@ -90,20 +114,37 @@ typedef struct _MSG_IOC_INIT
U32 HostMfaHighAddr; /* 10h */
U32 SenseBufferHighAddr; /* 14h */
U32 ReplyFifoHostSignalingAddr; /* 18h */
SGE_SIMPLE_UNION HostPageBufferSGE; /* 1Ch */
U16 MsgVersion; /* 28h */
U16 HeaderVersion; /* 2Ah */
} MSG_IOC_INIT, MPI_POINTER PTR_MSG_IOC_INIT,
IOCInit_t, MPI_POINTER pIOCInit_t;
/* WhoInit values */
#define MPI_WHOINIT_NO_ONE (0x00)
#define MPI_WHOINIT_SYSTEM_BIOS (0x01)
#define MPI_WHOINIT_ROM_BIOS (0x02)
#define MPI_WHOINIT_PCI_PEER (0x03)
#define MPI_WHOINIT_HOST_DRIVER (0x04)
#define MPI_WHOINIT_MANUFACTURER (0x05)
#define MPI_WHOINIT_NO_ONE (0x00)
#define MPI_WHOINIT_SYSTEM_BIOS (0x01)
#define MPI_WHOINIT_ROM_BIOS (0x02)
#define MPI_WHOINIT_PCI_PEER (0x03)
#define MPI_WHOINIT_HOST_DRIVER (0x04)
#define MPI_WHOINIT_MANUFACTURER (0x05)
/* Flags values */
#define MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE (0x01)
#define MPI_IOCINIT_FLAGS_REPLY_FIFO_HOST_SIGNAL (0x02)
#define MPI_IOCINIT_FLAGS_HOST_PAGE_BUFFER_PERSISTENT (0x04)
#define MPI_IOCINIT_FLAGS_REPLY_FIFO_HOST_SIGNAL (0x02)
#define MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE (0x01)
/* MsgVersion */
#define MPI_IOCINIT_MSGVERSION_MAJOR_MASK (0xFF00)
#define MPI_IOCINIT_MSGVERSION_MAJOR_SHIFT (8)
#define MPI_IOCINIT_MSGVERSION_MINOR_MASK (0x00FF)
#define MPI_IOCINIT_MSGVERSION_MINOR_SHIFT (0)
/* HeaderVersion */
#define MPI_IOCINIT_HEADERVERSION_UNIT_MASK (0xFF00)
#define MPI_IOCINIT_HEADERVERSION_UNIT_SHIFT (8)
#define MPI_IOCINIT_HEADERVERSION_DEV_MASK (0x00FF)
#define MPI_IOCINIT_HEADERVERSION_DEV_SHIFT (0)
typedef struct _MSG_IOC_INIT_REPLY
{
@ -187,32 +228,39 @@ typedef struct _MSG_IOC_FACTS_REPLY
MPI_FW_VERSION FWVersion; /* 38h */
U16 HighPriorityQueueDepth; /* 3Ch */
U16 Reserved2; /* 3Eh */
SGE_SIMPLE_UNION HostPageBufferSGE; /* 40h */
U32 ReplyFifoHostSignalingAddr; /* 4Ch */
} MSG_IOC_FACTS_REPLY, MPI_POINTER PTR_MSG_IOC_FACTS_REPLY,
IOCFactsReply_t, MPI_POINTER pIOCFactsReply_t;
#define MPI_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00)
#define MPI_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF)
#define MPI_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00)
#define MPI_IOCFACTS_MSGVERSION_MAJOR_SHIFT (8)
#define MPI_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF)
#define MPI_IOCFACTS_MSGVERSION_MINOR_SHIFT (0)
#define MPI_IOCFACTS_HEADERVERSION_UNIT_MASK (0xFF00)
#define MPI_IOCFACTS_HEADERVERSION_DEV_MASK (0x00FF)
#define MPI_IOCFACTS_HDRVERSION_UNIT_MASK (0xFF00)
#define MPI_IOCFACTS_HDRVERSION_UNIT_SHIFT (8)
#define MPI_IOCFACTS_HDRVERSION_DEV_MASK (0x00FF)
#define MPI_IOCFACTS_HDRVERSION_DEV_SHIFT (0)
#define MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001)
#define MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002)
#define MPI_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004)
#define MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL (0x0008)
#define MPI_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001)
#define MPI_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002)
#define MPI_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004)
#define MPI_IOCFACTS_EXCEPT_PERSISTENT_TABLE_FULL (0x0008)
#define MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT (0x01)
#define MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT (0x01)
#define MPI_IOCFACTS_FLAGS_REPLY_FIFO_HOST_SIGNAL (0x02)
#define MPI_IOCFACTS_FLAGS_HOST_PAGE_BUFFER_PERSISTENT (0x04)
#define MPI_IOCFACTS_EVENTSTATE_DISABLED (0x00)
#define MPI_IOCFACTS_EVENTSTATE_ENABLED (0x01)
#define MPI_IOCFACTS_EVENTSTATE_DISABLED (0x00)
#define MPI_IOCFACTS_EVENTSTATE_ENABLED (0x01)
#define MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q (0x00000001)
#define MPI_IOCFACTS_CAPABILITY_REPLY_HOST_SIGNAL (0x00000002)
#define MPI_IOCFACTS_CAPABILITY_QUEUE_FULL_HANDLING (0x00000004)
#define MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008)
#define MPI_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010)
#define MPI_IOCFACTS_CAPABILITY_EXTENDED_BUFFER (0x00000020)
#define MPI_IOCFACTS_CAPABILITY_EEDP (0x00000040)
#define MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q (0x00000001)
#define MPI_IOCFACTS_CAPABILITY_REPLY_HOST_SIGNAL (0x00000002)
#define MPI_IOCFACTS_CAPABILITY_QUEUE_FULL_HANDLING (0x00000004)
#define MPI_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008)
#define MPI_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010)
#define MPI_IOCFACTS_CAPABILITY_EXTENDED_BUFFER (0x00000020)
@ -408,6 +456,8 @@ typedef struct _MSG_EVENT_ACK_REPLY
#define MPI_EVENT_SAS_DEVICE_STATUS_CHANGE (0x0000000F)
#define MPI_EVENT_SAS_SES (0x00000010)
#define MPI_EVENT_PERSISTENT_TABLE_FULL (0x00000011)
#define MPI_EVENT_SAS_PHY_LINK_STATUS (0x00000012)
#define MPI_EVENT_SAS_DISCOVERY_ERROR (0x00000013)
/* AckRequired field values */
@ -467,6 +517,10 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
U8 ASCQ; /* 05h */
U16 DevHandle; /* 06h */
U32 DeviceInfo; /* 08h */
U16 ParentDevHandle; /* 0Ch */
U8 PhyNum; /* 0Eh */
U8 Reserved1; /* 0Fh */
U64 SASAddress; /* 10h */
} EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
MPI_POINTER PTR_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
MpiEventDataSasDeviceStatusChange_t,
@ -477,6 +531,8 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
#define MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING (0x04)
#define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05)
#define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED (0x06)
#define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07)
/* SCSI Event data for Queue Full event */
@ -488,6 +544,35 @@ typedef struct _EVENT_DATA_QUEUE_FULL
} EVENT_DATA_QUEUE_FULL, MPI_POINTER PTR_EVENT_DATA_QUEUE_FULL,
EventDataQueueFull_t, MPI_POINTER pEventDataQueueFull_t;
/* MPI Integrated RAID Event data */
typedef struct _EVENT_DATA_RAID
{
U8 VolumeID; /* 00h */
U8 VolumeBus; /* 01h */
U8 ReasonCode; /* 02h */
U8 PhysDiskNum; /* 03h */
U8 ASC; /* 04h */
U8 ASCQ; /* 05h */
U16 Reserved; /* 06h */
U32 SettingsStatus; /* 08h */
} EVENT_DATA_RAID, MPI_POINTER PTR_EVENT_DATA_RAID,
MpiEventDataRaid_t, MPI_POINTER pMpiEventDataRaid_t;
/* MPI Integrated RAID Event data ReasonCode values */
#define MPI_EVENT_RAID_RC_VOLUME_CREATED (0x00)
#define MPI_EVENT_RAID_RC_VOLUME_DELETED (0x01)
#define MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED (0x02)
#define MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED (0x03)
#define MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED (0x04)
#define MPI_EVENT_RAID_RC_PHYSDISK_CREATED (0x05)
#define MPI_EVENT_RAID_RC_PHYSDISK_DELETED (0x06)
#define MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED (0x07)
#define MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED (0x08)
#define MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED (0x09)
#define MPI_EVENT_RAID_RC_SMART_DATA (0x0A)
#define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B)
/* MPI Link Status Change Event data */
typedef struct _EVENT_DATA_LINK_STATUS
@ -535,35 +620,63 @@ typedef struct _EVENT_DATA_LOGOUT
#define MPI_EVENT_LOGOUT_ALL_ALIASES (0xFF)
/* SAS SES Event data */
/* MPI Integrated RAID Event data */
typedef struct _EVENT_DATA_RAID
typedef struct _EVENT_DATA_SAS_SES
{
U8 VolumeID; /* 00h */
U8 VolumeBus; /* 01h */
U8 ReasonCode; /* 02h */
U8 PhysDiskNum; /* 03h */
U8 ASC; /* 04h */
U8 ASCQ; /* 05h */
U16 Reserved; /* 06h */
U32 SettingsStatus; /* 08h */
} EVENT_DATA_RAID, MPI_POINTER PTR_EVENT_DATA_RAID,
MpiEventDataRaid_t, MPI_POINTER pMpiEventDataRaid_t;
U8 PhyNum; /* 00h */
U8 Port; /* 01h */
U8 PortWidth; /* 02h */
U8 Reserved1; /* 04h */
} EVENT_DATA_SAS_SES, MPI_POINTER PTR_EVENT_DATA_SAS_SES,
MpiEventDataSasSes_t, MPI_POINTER pMpiEventDataSasSes_t;
/* MPI Integrated RAID Event data ReasonCode values */
#define MPI_EVENT_RAID_RC_VOLUME_CREATED (0x00)
#define MPI_EVENT_RAID_RC_VOLUME_DELETED (0x01)
#define MPI_EVENT_RAID_RC_VOLUME_SETTINGS_CHANGED (0x02)
#define MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED (0x03)
#define MPI_EVENT_RAID_RC_VOLUME_PHYSDISK_CHANGED (0x04)
#define MPI_EVENT_RAID_RC_PHYSDISK_CREATED (0x05)
#define MPI_EVENT_RAID_RC_PHYSDISK_DELETED (0x06)
#define MPI_EVENT_RAID_RC_PHYSDISK_SETTINGS_CHANGED (0x07)
#define MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED (0x08)
#define MPI_EVENT_RAID_RC_DOMAIN_VAL_NEEDED (0x09)
#define MPI_EVENT_RAID_RC_SMART_DATA (0x0A)
#define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED (0x0B)
/* SAS Phy Link Status Event data */
typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS
{
U8 PhyNum; /* 00h */
U8 LinkRates; /* 01h */
U16 DevHandle; /* 02h */
U64 SASAddress; /* 04h */
} EVENT_DATA_SAS_PHY_LINK_STATUS, MPI_POINTER PTR_EVENT_DATA_SAS_PHY_LINK_STATUS,
MpiEventDataSasPhyLinkStatus_t, MPI_POINTER pMpiEventDataSasPhyLinkStatus_t;
/* defines for the LinkRates field of the SAS PHY Link Status event */
#define MPI_EVENT_SAS_PLS_LR_CURRENT_MASK (0xF0)
#define MPI_EVENT_SAS_PLS_LR_CURRENT_SHIFT (4)
#define MPI_EVENT_SAS_PLS_LR_PREVIOUS_MASK (0x0F)
#define MPI_EVENT_SAS_PLS_LR_PREVIOUS_SHIFT (0)
#define MPI_EVENT_SAS_PLS_LR_RATE_UNKNOWN (0x00)
#define MPI_EVENT_SAS_PLS_LR_RATE_PHY_DISABLED (0x01)
#define MPI_EVENT_SAS_PLS_LR_RATE_FAILED_SPEED_NEGOTIATION (0x02)
#define MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE (0x03)
#define MPI_EVENT_SAS_PLS_LR_RATE_1_5 (0x08)
#define MPI_EVENT_SAS_PLS_LR_RATE_3_0 (0x09)
/* SAS Discovery Errror Event data */
typedef struct _EVENT_DATA_DISCOVERY_ERROR
{
U32 DiscoveryStatus; /* 00h */
U8 Port; /* 04h */
U8 Reserved1; /* 05h */
U16 Reserved2; /* 06h */
} EVENT_DATA_DISCOVERY_ERROR, MPI_POINTER PTR_EVENT_DATA_DISCOVERY_ERROR,
EventDataDiscoveryError_t, MPI_POINTER pEventDataDiscoveryError_t;
#define MPI_EVENT_DSCVRY_ERR_DS_LOOP_DETECTED (0x00000001)
#define MPI_EVENT_DSCVRY_ERR_DS_UNADDRESSABLE_DEVICE (0x00000002)
#define MPI_EVENT_DSCVRY_ERR_DS_MULTIPLE_PORTS (0x00000004)
#define MPI_EVENT_DSCVRY_ERR_DS_EXPANDER_ERR (0x00000008)
#define MPI_EVENT_DSCVRY_ERR_DS_SMP_TIMEOUT (0x00000010)
#define MPI_EVENT_DSCVRY_ERR_DS_OUT_ROUTE_ENTRIES (0x00000020)
#define MPI_EVENT_DSCVRY_ERR_DS_INDEX_NOT_EXIST (0x00000040)
#define MPI_EVENT_DSCVRY_ERR_DS_SMP_FUNCTION_FAILED (0x00000080)
#define MPI_EVENT_DSCVRY_ERR_DS_SMP_CRC_ERROR (0x00000100)
#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_SUBTRACTIVE (0x00000200)
#define MPI_EVENT_DSCVRY_ERR_DS_TABLE_TO_TABLE (0x00000400)
#define MPI_EVENT_DSCVRY_ERR_DS_MULTPL_PATHS (0x00000800)
/*****************************************************************************
@ -589,11 +702,13 @@ typedef struct _MSG_FW_DOWNLOAD
} MSG_FW_DOWNLOAD, MPI_POINTER PTR_MSG_FW_DOWNLOAD,
FWDownload_t, MPI_POINTER pFWDownload_t;
#define MPI_FW_DOWNLOAD_ITYPE_RESERVED (0x00)
#define MPI_FW_DOWNLOAD_ITYPE_FW (0x01)
#define MPI_FW_DOWNLOAD_ITYPE_BIOS (0x02)
#define MPI_FW_DOWNLOAD_ITYPE_NVDATA (0x03)
#define MPI_FW_DOWNLOAD_ITYPE_BOOTLOADER (0x04)
#define MPI_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT (0x01)
#define MPI_FW_DOWNLOAD_ITYPE_RESERVED (0x00)
#define MPI_FW_DOWNLOAD_ITYPE_FW (0x01)
#define MPI_FW_DOWNLOAD_ITYPE_BIOS (0x02)
#define MPI_FW_DOWNLOAD_ITYPE_NVDATA (0x03)
#define MPI_FW_DOWNLOAD_ITYPE_BOOTLOADER (0x04)
typedef struct _FWDownloadTCSGE
@ -647,6 +762,7 @@ typedef struct _MSG_FW_UPLOAD
#define MPI_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02)
#define MPI_FW_UPLOAD_ITYPE_NVDATA (0x03)
#define MPI_FW_UPLOAD_ITYPE_BOOTLOADER (0x04)
#define MPI_FW_UPLOAD_ITYPE_FW_BACKUP (0x05)
typedef struct _FWUploadTCSGE
{
@ -723,6 +839,7 @@ typedef struct _MPI_FW_HEADER
#define MPI_FW_HEADER_PID_PROD_IM_SCSI (0x0400)
#define MPI_FW_HEADER_PID_PROD_IS_SCSI (0x0500)
#define MPI_FW_HEADER_PID_PROD_CTX_SCSI (0x0600)
#define MPI_FW_HEADER_PID_PROD_IR_SCSI (0x0700)
#define MPI_FW_HEADER_PID_FAMILY_MASK (0x00FF)
/* SCSI */
@ -740,13 +857,16 @@ typedef struct _MPI_FW_HEADER
#define MPI_FW_HEADER_PID_FAMILY_1020TA0_SCSI (0x000C)
/* Fibre Channel */
#define MPI_FW_HEADER_PID_FAMILY_909_FC (0x0000)
#define MPI_FW_HEADER_PID_FAMILY_919_FC (0x0001)
#define MPI_FW_HEADER_PID_FAMILY_919X_FC (0x0002)
#define MPI_FW_HEADER_PID_FAMILY_919XL_FC (0x0003)
#define MPI_FW_HEADER_PID_FAMILY_949_FC (0x0004)
#define MPI_FW_HEADER_PID_FAMILY_919_FC (0x0001) /* 919 and 929 */
#define MPI_FW_HEADER_PID_FAMILY_919X_FC (0x0002) /* 919X and 929X */
#define MPI_FW_HEADER_PID_FAMILY_919XL_FC (0x0003) /* 919XL and 929XL */
#define MPI_FW_HEADER_PID_FAMILY_939X_FC (0x0004) /* 939X and 949X */
#define MPI_FW_HEADER_PID_FAMILY_959_FC (0x0005)
/* SAS */
#define MPI_FW_HEADER_PID_FAMILY_1064_SAS (0x0001)
#define MPI_FW_HEADER_PID_FAMILY_1068_SAS (0x0002)
#define MPI_FW_HEADER_PID_FAMILY_1078_SAS (0x0003)
#define MPI_FW_HEADER_PID_FAMILY_106xE_SAS (0x0004) /* 1068E, 1066E, and 1064E */
typedef struct _MPI_EXT_IMAGE_HEADER
{

View File

@ -1,12 +1,12 @@
/*
* Copyright (c) 2000-2003 LSI Logic Corporation.
* Copyright (c) 2000-2004 LSI Logic Corporation.
*
*
* Name: mpi_lan.h
* Title: MPI LAN messages and structures
* Creation Date: June 30, 2000
*
* mpi_lan.h Version: 01.05.xx
* mpi_lan.h Version: 01.05.01
*
* Version History
* ---------------
@ -28,6 +28,8 @@
* 02-20-01 01.01.02 Started using MPI_POINTER.
* 03-27-01 01.01.03 Added structure offset comments.
* 08-08-01 01.02.01 Original release for v1.2 work.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Original release for MPI v1.5.
* --------------------------------------------------------------------------
*/

View File

@ -1,12 +1,12 @@
/*
* Copyright (c) 2001-2003 LSI Logic Corporation.
* Copyright (c) 2001-2005 LSI Logic Corporation.
*
*
* Name: mpi_raid.h
* Title: MPI RAID message and structures
* Creation Date: February 27, 2001
*
* mpi_raid.h Version: 01.05.xx
* mpi_raid.h Version: 01.05.02
*
* Version History
* ---------------
@ -28,6 +28,10 @@
* 11-15-02 01.02.08 Added missing MsgContext field to MSG_MAILBOX_REQUEST.
* 04-01-03 01.02.09 New action data option flag for
* MPI_RAID_ACTION_DELETE_VOLUME.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Original release for MPI v1.5.
* 01-15-05 01.05.02 Added defines for the two new RAID Actions for
* _SET_RESYNC_RATE and _SET_DATA_SCRUB_RATE.
* --------------------------------------------------------------------------
*/
@ -84,6 +88,8 @@ typedef struct _MSG_RAID_ACTION
#define MPI_RAID_ACTION_REPLACE_PHYSDISK (0x10)
#define MPI_RAID_ACTION_ACTIVATE_VOLUME (0x11)
#define MPI_RAID_ACTION_INACTIVATE_VOLUME (0x12)
#define MPI_RAID_ACTION_SET_RESYNC_RATE (0x13)
#define MPI_RAID_ACTION_SET_DATA_SCRUB_RATE (0x14)
/* ActionDataWord defines for use with MPI_RAID_ACTION_CREATE_VOLUME action */
#define MPI_RAID_ACTION_ADATA_DO_NOT_SYNC (0x00000001)
@ -99,6 +105,13 @@ typedef struct _MSG_RAID_ACTION
/* ActionDataWord defines for use with MPI_RAID_ACTION_ACTIVATE_VOLUME action */
#define MPI_RAID_ACTION_ADATA_INACTIVATE_ALL (0x00000001)
/* ActionDataWord defines for use with MPI_RAID_ACTION_SET_RESYNC_RATE action */
#define MPI_RAID_ACTION_ADATA_RESYNC_RATE_MASK (0x000000FF)
/* ActionDataWord defines for use with MPI_RAID_ACTION_SET_DATA_SCRUB_RATE action */
#define MPI_RAID_ACTION_ADATA_DATA_SCRUB_RATE_MASK (0x000000FF)
/* RAID Action reply message */

View File

@ -1,83 +1,29 @@
/*
* Copyright (c) 2003 LSI Logic Corporation.
* Copyright (c) 2004 LSI Logic Corporation.
*
*
* Name: mpi_sas.h
* Title: MPI Serial Attached SCSI structures and definitions
* Creation Date: April 23, 2003
* Creation Date: August 19, 2004
*
* mpi_sas.h Version: 01.05.xx
* mpi_sas.h Version: 01.05.01
*
* Version History
* ---------------
*
* Date Version Description
* -------- -------- ------------------------------------------------------
* xx-yy-zz 01.05.01 Original release.
* 08-19-04 01.05.01 Original release.
* --------------------------------------------------------------------------
*/
#ifndef MPI_SAS_H
#define MPI_SAS_H
/*****************************************************************************
*
* S e r i a l A t t a c h e d S C S I M e s s a g e s
*
*****************************************************************************/
/****************************************************************************/
/* Serial Management Protocol Passthrough Request */
/****************************************************************************/
typedef struct _MSG_SMP_PASSTHROUGH_REQUEST
{
U8 PassthroughFlags; /* 00h */
U8 PhysicalPort; /* 01h */
U8 ChainOffset; /* 02h */
U8 Function; /* 03h */
U16 RequestDataLength; /* 04h */
U8 ConnectionRate; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
U32 Reserved1; /* 0Ch */
U64 SASAddress; /* 10h */
U32 Reserved2; /* 18h */
U32 Reserved3; /* 1Ch */
SGE_SIMPLE_UNION SGL; /* 20h */
} MSG_SMP_PASSTHROUGH_REQUEST, MPI_POINTER PTR_MSG_SMP_PASSTHROUGH_REQUEST,
SmpPassthroughRequest_t, MPI_POINTER pSmpPassthroughRequest_t;
#define MPI_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80)
#define MPI_SMP_PT_REQ_CONNECT_RATE_NEGOTIATED (0x00)
#define MPI_SMP_PT_REQ_CONNECT_RATE_1_5 (0x08)
#define MPI_SMP_PT_REQ_CONNECT_RATE_3_0 (0x09)
/* Serial Management Protocol Passthrough Reply */
typedef struct _MSG_SMP_PASSTHROUGH_REPLY
{
U8 PassthroughFlags; /* 00h */
U8 PhysicalPort; /* 01h */
U8 MsgLength; /* 02h */
U8 Function; /* 03h */
U16 ResponseDataLength; /* 04h */
U8 Reserved1; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
U8 Reserved2; /* 0Ch */
U8 SASStatus; /* 0Dh */
U16 IOCStatus; /* 0Eh */
U32 IOCLogInfo; /* 10h */
U32 Reserved3; /* 14h */
U8 ResponseData[4]; /* 18h */
} MSG_SMP_PASSTHROUGH_REPLY, MPI_POINTER PTR_MSG_SMP_PASSTHROUGH_REPLY,
SmpPassthroughReply_t, MPI_POINTER pSmpPassthroughReply_t;
#define MPI_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE (0x80)
/* values for the SASStatus field */
/*
* Values for SASStatus.
*/
#define MPI_SASSTATUS_SUCCESS (0x00)
#define MPI_SASSTATUS_UNKNOWN_ERROR (0x01)
#define MPI_SASSTATUS_INVALID_FRAME (0x02)
@ -124,6 +70,131 @@ typedef struct _MSG_SMP_PASSTHROUGH_REPLY
#define MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER (0x00000003)
/*****************************************************************************
*
* S e r i a l A t t a c h e d S C S I M e s s a g e s
*
*****************************************************************************/
/****************************************************************************/
/* Serial Management Protocol Passthrough Request */
/****************************************************************************/
typedef struct _MSG_SMP_PASSTHROUGH_REQUEST
{
U8 PassthroughFlags; /* 00h */
U8 PhysicalPort; /* 01h */
U8 ChainOffset; /* 02h */
U8 Function; /* 03h */
U16 RequestDataLength; /* 04h */
U8 ConnectionRate; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
U32 Reserved1; /* 0Ch */
U64 SASAddress; /* 10h */
U32 Reserved2; /* 18h */
U32 Reserved3; /* 1Ch */
SGE_SIMPLE_UNION SGL; /* 20h */
} MSG_SMP_PASSTHROUGH_REQUEST, MPI_POINTER PTR_MSG_SMP_PASSTHROUGH_REQUEST,
SmpPassthroughRequest_t, MPI_POINTER pSmpPassthroughRequest_t;
/* values for PassthroughFlags field */
#define MPI_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80)
/* values for ConnectionRate field */
#define MPI_SMP_PT_REQ_CONNECT_RATE_NEGOTIATED (0x00)
#define MPI_SMP_PT_REQ_CONNECT_RATE_1_5 (0x08)
#define MPI_SMP_PT_REQ_CONNECT_RATE_3_0 (0x09)
/* Serial Management Protocol Passthrough Reply */
typedef struct _MSG_SMP_PASSTHROUGH_REPLY
{
U8 PassthroughFlags; /* 00h */
U8 PhysicalPort; /* 01h */
U8 MsgLength; /* 02h */
U8 Function; /* 03h */
U16 ResponseDataLength; /* 04h */
U8 Reserved1; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
U8 Reserved2; /* 0Ch */
U8 SASStatus; /* 0Dh */
U16 IOCStatus; /* 0Eh */
U32 IOCLogInfo; /* 10h */
U32 Reserved3; /* 14h */
U8 ResponseData[4]; /* 18h */
} MSG_SMP_PASSTHROUGH_REPLY, MPI_POINTER PTR_MSG_SMP_PASSTHROUGH_REPLY,
SmpPassthroughReply_t, MPI_POINTER pSmpPassthroughReply_t;
#define MPI_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE (0x80)
/****************************************************************************/
/* SATA Passthrough Request */
/****************************************************************************/
typedef struct _MSG_SATA_PASSTHROUGH_REQUEST
{
U8 TargetID; /* 00h */
U8 Bus; /* 01h */
U8 ChainOffset; /* 02h */
U8 Function; /* 03h */
U16 PassthroughFlags; /* 04h */
U8 ConnectionRate; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
U32 Reserved1; /* 0Ch */
U32 Reserved2; /* 10h */
U32 Reserved3; /* 14h */
U32 DataLength; /* 18h */
U8 CommandFIS[20]; /* 1Ch */
SGE_SIMPLE_UNION SGL; /* 30h */
} MSG_SATA_PASSTHROUGH_REQUEST, MPI_POINTER PTR_MSG_SATA_PASSTHROUGH_REQUEST,
SataPassthroughRequest_t, MPI_POINTER pSataPassthroughRequest_t;
/* values for PassthroughFlags field */
#define MPI_SATA_PT_REQ_PT_FLAGS_RESET_DEVICE (0x0200)
#define MPI_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100)
#define MPI_SATA_PT_REQ_PT_FLAGS_DMA_QUEUED (0x0080)
#define MPI_SATA_PT_REQ_PT_FLAGS_PACKET_COMMAND (0x0040)
#define MPI_SATA_PT_REQ_PT_FLAGS_DMA (0x0020)
#define MPI_SATA_PT_REQ_PT_FLAGS_PIO (0x0010)
#define MPI_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004)
#define MPI_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002)
#define MPI_SATA_PT_REQ_PT_FLAGS_READ (0x0001)
/* values for ConnectionRate field */
#define MPI_SATA_PT_REQ_CONNECT_RATE_NEGOTIATED (0x00)
#define MPI_SATA_PT_REQ_CONNECT_RATE_1_5 (0x08)
#define MPI_SATA_PT_REQ_CONNECT_RATE_3_0 (0x09)
/* SATA Passthrough Reply */
typedef struct _MSG_SATA_PASSTHROUGH_REPLY
{
U8 TargetID; /* 00h */
U8 Bus; /* 01h */
U8 MsgLength; /* 02h */
U8 Function; /* 03h */
U16 PassthroughFlags; /* 04h */
U8 Reserved1; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
U8 Reserved2; /* 0Ch */
U8 SASStatus; /* 0Dh */
U16 IOCStatus; /* 0Eh */
U32 IOCLogInfo; /* 10h */
U8 StatusFIS[20]; /* 14h */
U32 StatusControlRegisters; /* 28h */
U32 TransferCount; /* 2Ch */
} MSG_SATA_PASSTHROUGH_REPLY, MPI_POINTER PTR_MSG_SATA_PASSTHROUGH_REPLY,
SataPassthroughReply_t, MPI_POINTER pSataPassthroughReply_t;
/****************************************************************************/
/* SAS IO Unit Control Request */
/****************************************************************************/
@ -148,15 +219,13 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST
} MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST,
SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t;
/* values for the ... field */
/* values for the Operation field */
#define MPI_SAS_OP_CLEAR_NOT_PRESENT (0x01)
#define MPI_SAS_OP_CLEAR_ALL (0x02)
#define MPI_SAS_OP_MAP (0x03)
#define MPI_SAS_OP_MOVE (0x04)
#define MPI_SAS_OP_CLEAR (0x05)
#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)
#define MPI_SAS_OP_PHY_LINK_RESET (0x06)
#define MPI_SAS_OP_PHY_HARD_RESET (0x07)
#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)
#define MPI_SAS_OP_MAP_CURRENT (0x09)
/* SAS IO Unit Control Reply */

View File

@ -1,12 +1,12 @@
/*
* Copyright (c) 2000-2003 LSI Logic Corporation.
* Copyright (c) 2000-2004 LSI Logic Corporation.
*
*
* Name: mpi_targ.h
* Title: MPI Target mode messages and structures
* Creation Date: June 22, 2000
*
* mpi_targ.h Version: 01.05.xx
* mpi_targ.h Version: 01.05.04
*
* Version History
* ---------------
@ -43,6 +43,16 @@
* Added PRIORITY_REASON_TARGET_BUSY.
* 11-15-02 01.02.08 Added AliasID field to MPI_TARGET_SCSI_SPI_CMD_BUFFER.
* 04-01-03 01.02.09 Added OptionalOxid field to MPI_TARGET_FCP_CMD_BUFFER.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Added new request message structures for
* MSG_TARGET_CMD_BUF_POST_BASE_REQUEST,
* MSG_TARGET_CMD_BUF_POST_LIST_REQUEST, and
* MSG_TARGET_ASSIST_EXT_REQUEST.
* Added new structures for SAS SSP Command buffer, SSP
* Task buffer, and SSP Status IU.
* 10-05-04 01.05.02 MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY added.
* 02-22-05 01.05.03 Changed a comment.
* 03-11-05 01.05.04 Removed TargetAssistExtended Request.
* --------------------------------------------------------------------------
*/
@ -133,18 +143,6 @@ typedef struct _MSG_PRIORITY_CMD_RECEIVED_REPLY
} MSG_PRIORITY_CMD_RECEIVED_REPLY, MPI_POINTER PTR_MSG_PRIORITY_CMD_RECEIVED_REPLY,
PriorityCommandReceivedReply_t, MPI_POINTER pPriorityCommandReceivedReply_t;
#define PRIORITY_REASON_NO_DISCONNECT (0x00)
#define PRIORITY_REASON_SCSI_TASK_MANAGEMENT (0x01)
#define PRIORITY_REASON_CMD_PARITY_ERR (0x02)
#define PRIORITY_REASON_MSG_OUT_PARITY_ERR (0x03)
#define PRIORITY_REASON_LQ_CRC_ERR (0x04)
#define PRIORITY_REASON_CMD_CRC_ERR (0x05)
#define PRIORITY_REASON_PROTOCOL_ERR (0x06)
#define PRIORITY_REASON_DATA_OUT_PARITY_ERR (0x07)
#define PRIORITY_REASON_DATA_OUT_CRC_ERR (0x08)
#define PRIORITY_REASON_TARGET_BUSY (0x09)
#define PRIORITY_REASON_UNKNOWN (0xFF)
typedef struct _MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY
{
@ -164,6 +162,89 @@ typedef struct _MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY
MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_ERROR_REPLY,
TargetCmdBufferPostErrorReply_t, MPI_POINTER pTargetCmdBufferPostErrorReply_t;
#define PRIORITY_REASON_NO_DISCONNECT (0x00)
#define PRIORITY_REASON_SCSI_TASK_MANAGEMENT (0x01)
#define PRIORITY_REASON_CMD_PARITY_ERR (0x02)
#define PRIORITY_REASON_MSG_OUT_PARITY_ERR (0x03)
#define PRIORITY_REASON_LQ_CRC_ERR (0x04)
#define PRIORITY_REASON_CMD_CRC_ERR (0x05)
#define PRIORITY_REASON_PROTOCOL_ERR (0x06)
#define PRIORITY_REASON_DATA_OUT_PARITY_ERR (0x07)
#define PRIORITY_REASON_DATA_OUT_CRC_ERR (0x08)
#define PRIORITY_REASON_TARGET_BUSY (0x09)
#define PRIORITY_REASON_UNKNOWN (0xFF)
/****************************************************************************/
/* Target Command Buffer Post Base Request */
/****************************************************************************/
typedef struct _MSG_TARGET_CMD_BUF_POST_BASE_REQUEST
{
U8 BufferPostFlags; /* 00h */
U8 PortNumber; /* 01h */
U8 ChainOffset; /* 02h */
U8 Function; /* 03h */
U16 TotalCmdBuffers; /* 04h */
U8 Reserved; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
U32 Reserved1; /* 0Ch */
U16 CmdBufferLength; /* 10h */
U16 NextCmdBufferOffset; /* 12h */
U32 BaseAddressLow; /* 14h */
U32 BaseAddressHigh; /* 18h */
} MSG_TARGET_CMD_BUF_POST_BASE_REQUEST,
MPI_POINTER PTR__MSG_TARGET_CMD_BUF_POST_BASE_REQUEST,
TargetCmdBufferPostBaseRequest_t,
MPI_POINTER pTargetCmdBufferPostBaseRequest_t;
#define CMD_BUFFER_POST_BASE_FLAGS_AUTO_POST_ALL (0x01)
typedef struct _MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY
{
U16 Reserved; /* 00h */
U8 MsgLength; /* 02h */
U8 Function; /* 03h */
U16 Reserved1; /* 04h */
U8 Reserved2; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
U16 Reserved3; /* 0Ch */
U16 IOCStatus; /* 0Eh */
U32 IOCLogInfo; /* 10h */
} MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY,
MPI_POINTER PTR_MSG_TARGET_CMD_BUFFER_POST_BASE_LIST_REPLY,
TargetCmdBufferPostBaseListReply_t,
MPI_POINTER pTargetCmdBufferPostBaseListReply_t;
/****************************************************************************/
/* Target Command Buffer Post List Request */
/****************************************************************************/
typedef struct _MSG_TARGET_CMD_BUF_POST_LIST_REQUEST
{
U8 Reserved; /* 00h */
U8 PortNumber; /* 01h */
U8 ChainOffset; /* 02h */
U8 Function; /* 03h */
U16 CmdBufferCount; /* 04h */
U8 Reserved1; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
U32 Reserved2; /* 0Ch */
U16 IoIndex[2]; /* 10h */
} MSG_TARGET_CMD_BUF_POST_LIST_REQUEST,
MPI_POINTER PTR_MSG_TARGET_CMD_BUF_POST_LIST_REQUEST,
TargetCmdBufferPostListRequest_t,
MPI_POINTER pTargetCmdBufferPostListRequest_t;
/****************************************************************************/
/* Command Buffer Formats (with 16 byte CDB) */
/****************************************************************************/
typedef struct _MPI_TARGET_FCP_CMD_BUFFER
{
@ -201,6 +282,46 @@ typedef struct _MPI_TARGET_SCSI_SPI_CMD_BUFFER
MpiTargetScsiSpiCmdBuffer, MPI_POINTER pMpiTargetScsiSpiCmdBuffer;
typedef struct _MPI_TARGET_SSP_CMD_BUFFER
{
U8 FrameType; /* 00h */
U8 Reserved1; /* 01h */
U16 Reserved2; /* 02h */
U16 InitiatorTag; /* 04h */
U16 DevHandle; /* 06h */
/* COMMAND information unit starts here */
U8 LogicalUnitNumber[8]; /* 08h */
U8 Reserved3; /* 10h */
U8 TaskAttribute; /* lower 3 bits */ /* 11h */
U8 Reserved4; /* 12h */
U8 AdditionalCDBLength; /* upper 5 bits */ /* 13h */
U8 CDB[16]; /* 14h */
/* Additional CDB bytes extend past the CDB field */
} MPI_TARGET_SSP_CMD_BUFFER, MPI_POINTER PTR_MPI_TARGET_SSP_CMD_BUFFER,
MpiTargetSspCmdBuffer, MPI_POINTER pMpiTargetSspCmdBuffer;
typedef struct _MPI_TARGET_SSP_TASK_BUFFER
{
U8 FrameType; /* 00h */
U8 Reserved1; /* 01h */
U16 Reserved2; /* 02h */
U16 InitiatorTag; /* 04h */
U16 DevHandle; /* 06h */
/* TASK information unit starts here */
U8 LogicalUnitNumber[8]; /* 08h */
U8 Reserved3; /* 10h */
U8 Reserved4; /* 11h */
U8 TaskManagementFunction; /* 12h */
U8 Reserved5; /* 13h */
U16 ManagedTaskTag; /* 14h */
U16 Reserved6; /* 16h */
U32 Reserved7; /* 18h */
U32 Reserved8; /* 1Ch */
U32 Reserved9; /* 20h */
} MPI_TARGET_SSP_TASK_BUFFER, MPI_POINTER PTR_MPI_TARGET_SSP_TASK_BUFFER,
MpiTargetSspTaskBuffer, MPI_POINTER pMpiTargetSspTaskBuffer;
/****************************************************************************/
/* Target Assist Request */
/****************************************************************************/
@ -308,6 +429,27 @@ typedef struct _MPI_TARGET_SCSI_SPI_STATUS_IU
} MPI_TARGET_SCSI_SPI_STATUS_IU, MPI_POINTER PTR_MPI_TARGET_SCSI_SPI_STATUS_IU,
TargetScsiSpiStatusIU_t, MPI_POINTER pTargetScsiSpiStatusIU_t;
/*
* NOTE: The SSP status IU is big-endian. When used on a little-endian system,
* this structure properly orders the bytes.
*/
typedef struct _MPI_TARGET_SSP_RSP_IU
{
U32 Reserved0[6]; /* reserved for SSP header */ /* 00h */
/* start of RESPONSE information unit */
U32 Reserved1; /* 18h */
U32 Reserved2; /* 1Ch */
U16 Reserved3; /* 20h */
U8 DataPres; /* lower 2 bits */ /* 22h */
U8 Status; /* 23h */
U32 Reserved4; /* 24h */
U32 SenseDataLength; /* 28h */
U32 ResponseDataLength; /* 2Ch */
U8 ResponseSenseData[4]; /* 30h */
} MPI_TARGET_SSP_RSP_IU, MPI_POINTER PTR_MPI_TARGET_SSP_RSP_IU,
MpiTargetSspRspIu_t, MPI_POINTER pMpiTargetSspRspIu_t;
/****************************************************************************/
/* Target Mode Abort Request */
/****************************************************************************/

View File

@ -1,12 +1,12 @@
/*
* Copyright (c) 2001-2003 LSI Logic Corporation.
* Copyright (c) 2001-2005 LSI Logic Corporation.
*
*
* Name: mpi_tool.h
* Title: MPI Toolbox structures and definitions
* Creation Date: July 30, 2001
*
* mpi_tool.h Version: 01.05.xx
* mpi_tool.h Version: 01.05.03
*
* Version History
* ---------------
@ -15,6 +15,16 @@
* -------- -------- ------------------------------------------------------
* 08-08-01 01.02.01 Original release.
* 08-29-01 01.02.02 Added DIAG_DATA_UPLOAD_HEADER and related defines.
* 01-16-04 01.02.03 Added defines and structures for new tools
*. MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL and
* MPI_TOOLBOX_FC_MANAGEMENT_TOOL.
* 04-29-04 01.02.04 Added message structures for Diagnostic Buffer Post and
* Diagnostic Release requests and replies.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Original release for MPI v1.5.
* 10-06-04 01.05.02 Added define for MPI_DIAG_BUF_TYPE_COUNT.
* 02-09-05 01.05.03 Added frame size option to FC management tool.
* Added Beacon tool to the Toolbox.
* --------------------------------------------------------------------------
*/
@ -26,6 +36,7 @@
#define MPI_TOOLBOX_DIAG_DATA_UPLOAD_TOOL (0x02)
#define MPI_TOOLBOX_ISTWI_READ_WRITE_TOOL (0x03)
#define MPI_TOOLBOX_FC_MANAGEMENT_TOOL (0x04)
#define MPI_TOOLBOX_BEACON_TOOL (0x05)
/****************************************************************************/
@ -185,11 +196,21 @@ typedef struct _MPI_TB_FC_MANAGE_PID_AI
} MPI_TB_FC_MANAGE_PID_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_PID_AI,
MpiTbFcManagePidAi_t, MPI_POINTER pMpiTbFcManagePidAi_t;
/* ActionInfo for set max frame size */
typedef struct _MPI_TB_FC_MANAGE_FRAME_SIZE_AI
{
U16 FrameSize; /* 00h */
U8 PortNum; /* 02h */
U8 Reserved1; /* 03h */
} MPI_TB_FC_MANAGE_FRAME_SIZE_AI, MPI_POINTER PTR_MPI_TB_FC_MANAGE_FRAME_SIZE_AI,
MpiTbFcManageFrameSizeAi_t, MPI_POINTER pMpiTbFcManageFrameSizeAi_t;
/* union of ActionInfo */
typedef union _MPI_TB_FC_MANAGE_AI_UNION
{
MPI_TB_FC_MANAGE_BUS_TID_AI BusTid;
MPI_TB_FC_MANAGE_PID_AI Port;
MPI_TB_FC_MANAGE_FRAME_SIZE_AI FrameSize;
} MPI_TB_FC_MANAGE_AI_UNION, MPI_POINTER PTR_MPI_TB_FC_MANAGE_AI_UNION,
MpiTbFcManageAiUnion_t, MPI_POINTER pMpiTbFcManageAiUnion_t;
@ -214,6 +235,32 @@ typedef struct _MSG_TOOLBOX_FC_MANAGE_REQUEST
#define MPI_TB_FC_MANAGE_ACTION_DISC_ALL (0x00)
#define MPI_TB_FC_MANAGE_ACTION_DISC_PID (0x01)
#define MPI_TB_FC_MANAGE_ACTION_DISC_BUS_TID (0x02)
#define MPI_TB_FC_MANAGE_ACTION_SET_MAX_FRAME_SIZE (0x03)
/****************************************************************************/
/* Toolbox Beacon Tool request */
/****************************************************************************/
typedef struct _MSG_TOOLBOX_BEACON_REQUEST
{
U8 Tool; /* 00h */
U8 Reserved; /* 01h */
U8 ChainOffset; /* 02h */
U8 Function; /* 03h */
U16 Reserved1; /* 04h */
U8 Reserved2; /* 06h */
U8 MsgFlags; /* 07h */
U32 MsgContext; /* 08h */
U8 ConnectNum; /* 0Ch */
U8 PortNum; /* 0Dh */
U8 Reserved3; /* 0Eh */
U8 Flags; /* 0Fh */
} MSG_TOOLBOX_BEACON_REQUEST, MPI_POINTER PTR_MSG_TOOLBOX_BEACON_REQUEST,
ToolboxBeaconRequest_t, MPI_POINTER pToolboxBeaconRequest_t;
#define MPI_TOOLBOX_FLAGS_BEACON_MODE_OFF (0x00)
#define MPI_TOOLBOX_FLAGS_BEACON_MODE_ON (0x01)
/****************************************************************************/
@ -233,14 +280,16 @@ typedef struct _MSG_DIAG_BUFFER_POST_REQUEST
U32 ExtendedType; /* 0Ch */
U32 BufferLength; /* 10h */
U32 ProductSpecific[4]; /* 14h */
U32 Reserved3; /* 18h */
SGE_SIMPLE_UNION SGL; /* 28h */
U32 Reserved3; /* 24h */
U64 BufferAddress; /* 28h */
} MSG_DIAG_BUFFER_POST_REQUEST, MPI_POINTER PTR_MSG_DIAG_BUFFER_POST_REQUEST,
DiagBufferPostRequest_t, MPI_POINTER pDiagBufferPostRequest_t;
#define MPI_DIAG_BUF_TYPE_TRACE (0x00)
#define MPI_DIAG_BUF_TYPE_SNAPSHOT (0x01)
#define MPI_DIAG_BUF_TYPE_EXTENDED (0x02)
/* count of the number of buffer types */
#define MPI_DIAG_BUF_TYPE_COUNT (0x03)
#define MPI_DIAG_EXTENDED_QTAG (0x00000001)

View File

@ -1,12 +1,12 @@
/*
* Copyright (c) 2000-2003 LSI Logic Corporation.
* Copyright (c) 2000-2004 LSI Logic Corporation.
*
*
* Name: mpi_type.h
* Title: MPI Basic type definitions
* Creation Date: June 6, 2000
*
* mpi_type.h Version: 01.05.xx
* mpi_type.h Version: 01.05.01
*
* Version History
* ---------------
@ -18,6 +18,8 @@
* 11-02-00 01.01.01 Original release for post 1.0 work
* 02-20-01 01.01.02 Added define and ifdef for MPI_POINTER.
* 08-08-01 01.02.01 Original release for v1.2 work.
* 05-11-04 01.03.01 Original release for MPI v1.3.
* 08-19-04 01.05.01 Original release for MPI v1.5.
* --------------------------------------------------------------------------
*/
@ -50,11 +52,6 @@ typedef unsigned short U16;
typedef int32_t S32;
typedef u_int32_t U32;
/*
* The only way crap below could work on big-endian boxen would be if it
* wasn't used at all.
*/
typedef struct _S64
{
U32 Low;

View File

@ -1,55 +1,13 @@
/*
* linux/drivers/message/fusion/mptbase.c
* High performance SCSI + LAN / Fibre Channel device drivers.
* This is the Fusion MPT base driver which supports multiple
* (SCSI + LAN) specialized protocol drivers.
* For use with PCI chip/adapter(s):
* LSIFC9xx/LSI409xx Fibre Channel
* For use with LSI Logic PCI chip/adapter(s)
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Credits:
* There are lots of people not mentioned below that deserve credit
* and thanks but won't get it here - sorry in advance that you
* got overlooked.
*
* This driver would not exist if not for Alan Cox's development
* of the linux i2o driver.
*
* A special thanks to Noah Romer (LSI Logic) for tons of work
* and tough debugging on the LAN driver, especially early on;-)
* And to Roger Hickerson (LSI Logic) for tirelessly supporting
* this driver project.
*
* A special thanks to Pamela Delaney (LSI Logic) for tons of work
* and countless enhancements while adding support for the 1030
* chip family. Pam has been instrumental in the development of
* of the 2.xx.xx series fusion drivers, and her contributions are
* far too numerous to hope to list in one place.
*
* All manner of help from Stephen Shirron (LSI Logic):
* low-level FC analysis, debug + various fixes in FCxx firmware,
* initial port to alpha platform, various driver code optimizations,
* being a faithful sounding board on all sorts of issues & ideas,
* etc.
*
* A huge debt of gratitude is owed to David S. Miller (DaveM)
* for fixing much of the stupid and broken stuff in the early
* driver while porting to sparc64 platform. THANK YOU!
*
* Special thanks goes to the I2O LAN driver people at the
* University of Helsinki, who, unbeknownst to them, provided
* the inspiration and initial structure for this driver.
*
* A really huge debt of gratitude is owed to Eddie C. Dost
* for gobs of hard work fixing and optimizing LAN code.
* THANK YOU!
*
* Copyright (c) 1999-2004 LSI Logic Corporation
* Originally By: Steven J. Ralston
* (mailto:sjralston1@netscape.net)
* Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
* $Id: mptbase.c,v 1.126 2002/12/16 15:28:45 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@ -101,6 +59,7 @@
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/interrupt.h> /* needed for in_interrupt() proto */
#include <linux/dma-mapping.h>
#include <asm/io.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
@ -218,41 +177,35 @@ static void mpt_fc_log_info(MPT_ADAPTER *ioc, u32 log_info);
static void mpt_sp_log_info(MPT_ADAPTER *ioc, u32 log_info);
/* module entry point */
static int __devinit mptbase_probe (struct pci_dev *, const struct pci_device_id *);
static void __devexit mptbase_remove(struct pci_dev *);
static void mptbase_shutdown(struct device * );
static int __init fusion_init (void);
static void __exit fusion_exit (void);
/****************************************************************************
* Supported hardware
*/
static struct pci_device_id mptbase_pci_table[] = {
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030,
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035,
PCI_ANY_ID, PCI_ANY_ID },
{0} /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, mptbase_pci_table);
#define CHIPREG_READ32(addr) readl_relaxed(addr)
#define CHIPREG_READ32_dmasync(addr) readl(addr)
#define CHIPREG_WRITE32(addr,val) writel(val, addr)
#define CHIPREG_PIO_WRITE32(addr,val) outl(val, (unsigned long)addr)
#define CHIPREG_PIO_READ32(addr) inl((unsigned long)addr)
static void
pci_disable_io_access(struct pci_dev *pdev)
{
u16 command_reg;
pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
command_reg &= ~1;
pci_write_config_word(pdev, PCI_COMMAND, command_reg);
}
static void
pci_enable_io_access(struct pci_dev *pdev)
{
u16 command_reg;
pci_read_config_word(pdev, PCI_COMMAND, &command_reg);
command_reg |= 1;
pci_write_config_word(pdev, PCI_COMMAND, command_reg);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mpt_interrupt - MPT adapter (IOC) specific interrupt handler.
@ -330,8 +283,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
ioc->name, mr, req_idx));
DBG_DUMP_REPLY_FRAME(mr)
/* NEW! 20010301 -sralston
* Check/log IOC log info
/* Check/log IOC log info
*/
ioc_stat = le16_to_cpu(mr->u.reply.IOCStatus);
if (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) {
@ -357,9 +309,7 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa);
} else if (type == MPI_CONTEXT_REPLY_TYPE_LAN) {
cb_idx = mpt_lan_index;
/*
* BUG FIX! 20001218 -sralston
* Blind set of mf to NULL here was fatal
/* Blind set of mf to NULL here was fatal
* after lan_reply says "freeme"
* Fix sort of combined with an optimization here;
* added explicit check for case where lan_reply
@ -430,15 +380,8 @@ mpt_interrupt(int irq, void *bus_id, struct pt_regs *r)
}
if (freeme) {
unsigned long flags;
/* Put Request back on FreeQ! */
spin_lock_irqsave(&ioc->FreeQlock, flags);
list_add_tail(&mf->u.frame.linkage.list, &ioc->FreeQ);
#ifdef MFCNT
ioc->mfcnt--;
#endif
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
mpt_free_msg_frame(ioc, mf);
}
mb();
@ -725,11 +668,9 @@ int
mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
{
MPT_ADAPTER *ioc;
int error=0;
if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) {
error= -EINVAL;
return error;
return -EINVAL;
}
MptDeviceDriverHandlers[cb_idx] = dd_cbfunc;
@ -737,14 +678,12 @@ mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx)
/* call per pci device probe entry point */
list_for_each_entry(ioc, &ioc_list, list) {
if(dd_cbfunc->probe) {
error = dd_cbfunc->probe(ioc->pcidev,
dd_cbfunc->probe(ioc->pcidev,
ioc->pcidev->driver->id_table);
if(error != 0)
return error;
}
}
return error;
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@ -809,8 +748,8 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc)
mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
/* u16! */
req_idx = cpu_to_le16(req_offset / ioc->req_sz);
mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx;
req_idx = req_offset / ioc->req_sz;
mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */
#ifdef MFCNT
@ -856,8 +795,8 @@ mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf)
mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */
req_offset = (u8 *)mf - (u8 *)ioc->req_frames;
/* u16! */
req_idx = cpu_to_le16(req_offset / ioc->req_sz);
mf->u.frame.hwhdr.msgctxu.fld.req_idx = req_idx;
req_idx = req_offset / ioc->req_sz;
mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx);
mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0;
#ifdef MPT_DEBUG_MSG_FRAME
@ -1058,7 +997,7 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mptbase_probe - Install a PCI intelligent MPT adapter.
* mpt_attach - Install a PCI intelligent MPT adapter.
* @pdev: Pointer to pci_dev structure
*
* This routine performs all the steps necessary to bring the IOC of
@ -1073,8 +1012,8 @@ mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp)
*
* TODO: Add support for polled controllers
*/
static int __devinit
mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
int
mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
{
MPT_ADAPTER *ioc;
u8 __iomem *mem;
@ -1084,7 +1023,6 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
u32 psize;
int ii;
int r = -ENODEV;
u64 mask = 0xffffffffffffffffULL;
u8 revision;
u8 pcixcmd;
static int mpt_ids = 0;
@ -1097,15 +1035,15 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
dinitprintk((KERN_WARNING MYNAM ": mpt_adapter_install\n"));
if (!pci_set_dma_mask(pdev, mask)) {
if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) {
dprintk((KERN_INFO MYNAM
": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n"));
} else if (pci_set_dma_mask(pdev, (u64) 0xffffffff)) {
} else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n");
return r;
}
if (!pci_set_consistent_dma_mask(pdev, mask))
if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
dprintk((KERN_INFO MYNAM
": Using 64 bit consistent mask\n"));
else
@ -1243,6 +1181,16 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pcixcmd &= 0x8F;
pci_write_config_byte(pdev, 0x6a, pcixcmd);
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC939X) {
ioc->prod_name = "LSIFC939X";
ioc->bus_type = FC;
ioc->errata_flag_1064 = 1;
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949X) {
ioc->prod_name = "LSIFC949X";
ioc->bus_type = FC;
ioc->errata_flag_1064 = 1;
}
else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
ioc->prod_name = "LSI53C1030";
ioc->bus_type = SCSI;
@ -1261,6 +1209,9 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ioc->bus_type = SCSI;
}
if (ioc->errata_flag_1064)
pci_disable_io_access(pdev);
sprintf(ioc->name, "ioc%d", ioc->id);
spin_lock_init(&ioc->FreeQlock);
@ -1303,8 +1254,7 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
#endif
}
/* NEW! 20010220 -sralston
* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
/* Check for "bound ports" (929, 929X, 1030, 1035) to reduce redundant resets.
*/
mpt_detect_bound_ports(ioc, pdev);
@ -1354,13 +1304,13 @@ mptbase_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mptbase_remove - Remove a PCI intelligent MPT adapter.
* mpt_detach - Remove a PCI intelligent MPT adapter.
* @pdev: Pointer to pci_dev structure
*
*/
static void __devexit
mptbase_remove(struct pci_dev *pdev)
void
mpt_detach(struct pci_dev *pdev)
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
char pname[32];
@ -1397,43 +1347,21 @@ mptbase_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mptbase_shutdown -
*
*/
static void
mptbase_shutdown(struct device * dev)
{
int ii;
/* call per device driver shutdown entry point */
for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
if(MptDeviceDriverHandlers[ii] &&
MptDeviceDriverHandlers[ii]->shutdown) {
MptDeviceDriverHandlers[ii]->shutdown(dev);
}
}
}
/**************************************************************************
* Power Management
*/
#ifdef CONFIG_PM
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mptbase_suspend - Fusion MPT base driver suspend routine.
* mpt_suspend - Fusion MPT base driver suspend routine.
*
*
*/
static int
mptbase_suspend(struct pci_dev *pdev, pm_message_t state)
int
mpt_suspend(struct pci_dev *pdev, pm_message_t state)
{
u32 device_state;
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
int ii;
switch(state)
{
@ -1453,14 +1381,6 @@ mptbase_suspend(struct pci_dev *pdev, pm_message_t state)
"pci-suspend: pdev=0x%p, slot=%s, Entering operating state [D%d]\n",
ioc->name, pdev, pci_name(pdev), device_state);
/* call per device driver suspend entry point */
for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
if(MptDeviceDriverHandlers[ii] &&
MptDeviceDriverHandlers[ii]->suspend) {
MptDeviceDriverHandlers[ii]->suspend(pdev, state);
}
}
pci_save_state(pdev);
/* put ioc into READY_STATE */
@ -1484,18 +1404,18 @@ mptbase_suspend(struct pci_dev *pdev, pm_message_t state)
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mptbase_resume - Fusion MPT base driver resume routine.
* mpt_resume - Fusion MPT base driver resume routine.
*
*
*/
static int
mptbase_resume(struct pci_dev *pdev)
int
mpt_resume(struct pci_dev *pdev)
{
MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
u32 device_state = pdev->current_state;
int recovery_state;
int ii;
printk(MYIOC_s_INFO_FMT
"pci-resume: pdev=0x%p, slot=%s, Previous operating state [D%d]\n",
ioc->name, pdev, pci_name(pdev), device_state);
@ -1533,14 +1453,6 @@ mptbase_resume(struct pci_dev *pdev)
"pci-resume: success\n", ioc->name);
}
/* call per device driver resume entry point */
for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) {
if(MptDeviceDriverHandlers[ii] &&
MptDeviceDriverHandlers[ii]->resume) {
MptDeviceDriverHandlers[ii]->resume(pdev);
}
}
return 0;
}
#endif
@ -1719,8 +1631,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
ioc->alt_ioc->active = 1;
}
/* NEW! 20010120 -sralston
* Enable MPT base driver management of EventNotification
/* Enable MPT base driver management of EventNotification
* and EventAck handling.
*/
if ((ret == 0) && (!ioc->facts.EventState))
@ -1729,9 +1640,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
if (ioc->alt_ioc && alt_ioc_ready && !ioc->alt_ioc->facts.EventState)
(void) SendEventNotification(ioc->alt_ioc, 1); /* 1=Enable EventNotification */
/* (Bugzilla:fibrebugs, #513)
* Bug fix (part 2)! 20010905 -sralston
* Add additional "reason" check before call to GetLanConfigPages
/* Add additional "reason" check before call to GetLanConfigPages
* (combined with GetIoUnitPage2 call). This prevents a somewhat
* recursive scenario; GetLanConfigPages times out, timer expired
* routine calls HardResetHandler, which calls into here again,
@ -1829,37 +1738,43 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
static void
mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev)
{
unsigned int match_lo, match_hi;
struct pci_dev *peer=NULL;
unsigned int slot = PCI_SLOT(pdev->devfn);
unsigned int func = PCI_FUNC(pdev->devfn);
MPT_ADAPTER *ioc_srch;
match_lo = pdev->devfn-1;
match_hi = pdev->devfn+1;
dprintk((MYIOC_s_INFO_FMT "PCI bus/devfn=%x/%x, searching for devfn match on %x or %x\n",
ioc->name, pdev->bus->number, pdev->devfn, match_lo, match_hi));
dprintk((MYIOC_s_INFO_FMT "PCI device %s devfn=%x/%x,"
" searching for devfn match on %x or %x\n",
ioc->name, pci_name(pdev), pdev->devfn,
func-1, func+1));
peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1));
if (!peer) {
peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func+1));
if (!peer)
return;
}
list_for_each_entry(ioc_srch, &ioc_list, list) {
struct pci_dev *_pcidev = ioc_srch->pcidev;
if ((_pcidev->device == pdev->device) &&
(_pcidev->bus->number == pdev->bus->number) &&
(_pcidev->devfn == match_lo || _pcidev->devfn == match_hi) ) {
if (_pcidev == peer) {
/* Paranoia checks */
if (ioc->alt_ioc != NULL) {
printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
ioc->name, ioc->alt_ioc->name);
ioc->name, ioc->alt_ioc->name);
break;
} else if (ioc_srch->alt_ioc != NULL) {
printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n",
ioc_srch->name, ioc_srch->alt_ioc->name);
ioc_srch->name, ioc_srch->alt_ioc->name);
break;
}
dprintk((KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n",
ioc->name, ioc_srch->name));
ioc->name, ioc_srch->name));
ioc_srch->alt_ioc = ioc;
ioc->alt_ioc = ioc_srch;
break;
}
}
pci_dev_put(peer);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@ -1922,15 +1837,10 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
ioc->alloc_total -= sz;
}
if (ioc->spi_data.nvram != NULL) {
kfree(ioc->spi_data.nvram);
ioc->spi_data.nvram = NULL;
}
if (ioc->spi_data.pIocPg3 != NULL) {
kfree(ioc->spi_data.pIocPg3);
ioc->spi_data.pIocPg3 = NULL;
}
kfree(ioc->spi_data.nvram);
kfree(ioc->spi_data.pIocPg3);
ioc->spi_data.nvram = NULL;
ioc->spi_data.pIocPg3 = NULL;
if (ioc->spi_data.pIocPg4 != NULL) {
sz = ioc->spi_data.IocPg4Sz;
@ -1947,10 +1857,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc)
ioc->ReqToChain = NULL;
}
if (ioc->ChainToChain != NULL) {
kfree(ioc->ChainToChain);
ioc->ChainToChain = NULL;
}
kfree(ioc->ChainToChain);
ioc->ChainToChain = NULL;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@ -2333,7 +2241,7 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason)
return -55;
}
r = sz = le32_to_cpu(facts->BlockSize);
r = sz = facts->BlockSize;
vv = ((63 / (sz * 4)) + 1) & 0x03;
ioc->NB_for_64_byte_frame = vv;
while ( sz )
@ -2785,7 +2693,7 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
/* prevent a second downloadboot and memory free with alt_ioc */
if (ioc->alt_ioc && ioc->alt_ioc->cached_fw)
ioc->alt_ioc->cached_fw = NULL;
CHIPREG_WRITE32(&ioc->chip->WriteSequence, 0xFF);
CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_1ST_KEY_VALUE);
CHIPREG_WRITE32(&ioc->chip->WriteSequence, MPI_WRSEQ_2ND_KEY_VALUE);
@ -2843,6 +2751,9 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
/* Write the LoadStartAddress to the DiagRw Address Register
* using Programmed IO
*/
if (ioc->errata_flag_1064)
pci_enable_io_access(ioc->pcidev);
CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, pFwHeader->LoadStartAddress);
ddlprintk((MYIOC_s_INFO_FMT "LoadStart addr written 0x%x \n",
ioc->name, pFwHeader->LoadStartAddress));
@ -2889,6 +2800,9 @@ mpt_downloadboot(MPT_ADAPTER *ioc, int sleepFlag)
CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwAddress, 0x3F000000);
CHIPREG_PIO_WRITE32(&ioc->pio_chip->DiagRwData, diagRwData);
if (ioc->errata_flag_1064)
pci_disable_io_access(ioc->pcidev);
diag0val = CHIPREG_READ32(&ioc->chip->Diagnostic);
ddlprintk((MYIOC_s_INFO_FMT "downloadboot diag0val=%x, turning off PREVENT_IOC_BOOT, DISABLE_ARM\n",
ioc->name, diag0val));
@ -4250,7 +4164,7 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum)
if ((ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_HVD) ||
(ioc->spi_data.busType == MPI_SCSIPORTPAGE0_PHY_SIGNAL_SE)) {
if (ioc->spi_data.minSyncFactor < MPT_ULTRA)
if (ioc->spi_data.minSyncFactor < MPT_ULTRA)
ioc->spi_data.minSyncFactor = MPT_ULTRA;
}
}
@ -4482,10 +4396,8 @@ mpt_read_ioc_pg_3(MPT_ADAPTER *ioc)
/* Free the old page
*/
if (ioc->spi_data.pIocPg3) {
kfree(ioc->spi_data.pIocPg3);
ioc->spi_data.pIocPg3 = NULL;
}
kfree(ioc->spi_data.pIocPg3);
ioc->spi_data.pIocPg3 = NULL;
/* There is at least one physical disk.
* Read and save IOC Page 3
@ -4753,9 +4665,7 @@ mpt_config(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
u32 flagsLength;
int in_isr;
/* (Bugzilla:fibrebugs, #513)
* Bug fix (part 1)! 20010905 -sralston
* Prevent calling wait_event() (below), if caller happens
/* Prevent calling wait_event() (below), if caller happens
* to be in ISR context, because that is fatal!
*/
in_isr = in_interrupt();
@ -4861,9 +4771,7 @@ mpt_toolbox(MPT_ADAPTER *ioc, CONFIGPARMS *pCfg)
u32 flagsLength;
int in_isr;
/* (Bugzilla:fibrebugs, #513)
* Bug fix (part 1)! 20010905 -sralston
* Prevent calling wait_event() (below), if caller happens
/* Prevent calling wait_event() (below), if caller happens
* to be in ISR context, because that is fatal!
*/
in_isr = in_interrupt();
@ -5130,20 +5038,26 @@ static int
procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data)
{
int ii;
int scsi, lan, ctl, targ, dmp;
int scsi, fc, sas, lan, ctl, targ, dmp;
char *drvname;
int len;
len = sprintf(buf, "%s-%s\n", "mptlinux", MPT_LINUX_VERSION_COMMON);
len += sprintf(buf+len, " Fusion MPT base driver\n");
scsi = lan = ctl = targ = dmp = 0;
scsi = fc = sas = lan = ctl = targ = dmp = 0;
for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) {
drvname = NULL;
if (MptCallbacks[ii]) {
switch (MptDriverClass[ii]) {
case MPTSCSIH_DRIVER:
if (!scsi++) drvname = "SCSI host";
case MPTSPI_DRIVER:
if (!scsi++) drvname = "SPI host";
break;
case MPTFC_DRIVER:
if (!fc++) drvname = "FC host";
break;
case MPTSAS_DRIVER:
if (!sas++) drvname = "SAS host";
break;
case MPTLAN_DRIVER:
if (!lan++) drvname = "LAN";
@ -5832,6 +5746,12 @@ mpt_sp_ioc_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf)
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
EXPORT_SYMBOL(mpt_attach);
EXPORT_SYMBOL(mpt_detach);
#ifdef CONFIG_PM
EXPORT_SYMBOL(mpt_resume);
EXPORT_SYMBOL(mpt_suspend);
#endif
EXPORT_SYMBOL(ioc_list);
EXPORT_SYMBOL(mpt_proc_root_dir);
EXPORT_SYMBOL(mpt_register);
@ -5860,19 +5780,6 @@ EXPORT_SYMBOL(mpt_read_ioc_pg_3);
EXPORT_SYMBOL(mpt_alloc_fw_memory);
EXPORT_SYMBOL(mpt_free_fw_memory);
static struct pci_driver mptbase_driver = {
.name = "mptbase",
.id_table = mptbase_pci_table,
.probe = mptbase_probe,
.remove = __devexit_p(mptbase_remove),
.driver = {
.shutdown = mptbase_shutdown,
},
#ifdef CONFIG_PM
.suspend = mptbase_suspend,
.resume = mptbase_resume,
#endif
};
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@ -5884,7 +5791,6 @@ static int __init
fusion_init(void)
{
int i;
int r;
show_mptmod_ver(my_NAME, my_VERSION);
printk(KERN_INFO COPYRIGHT "\n");
@ -5896,8 +5802,7 @@ fusion_init(void)
MptResetHandlers[i] = NULL;
}
/* NEW! 20010120 -sralston
* Register ourselves (mptbase) in order to facilitate
/* Register ourselves (mptbase) in order to facilitate
* EventNotification handling.
*/
mpt_base_index = mpt_register(mpt_base_reply, MPTBASE_DRIVER);
@ -5913,11 +5818,7 @@ fusion_init(void)
#ifdef CONFIG_PROC_FS
(void) procmpt_create();
#endif
r = pci_register_driver(&mptbase_driver);
if(r)
return(r);
return r;
return 0;
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@ -5933,7 +5834,6 @@ fusion_exit(void)
dexitprintk((KERN_INFO MYNAM ": fusion_exit() called!\n"));
pci_unregister_driver(&mptbase_driver);
mpt_reset_deregister(mpt_base_index);
#ifdef CONFIG_PROC_FS
@ -5941,6 +5841,5 @@ fusion_exit(void)
#endif
}
module_init(fusion_init);
module_exit(fusion_exit);

View File

@ -5,15 +5,9 @@
* LSIFC9xx/LSI409xx Fibre Channel
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Credits:
* (see mptbase.c)
*
* Copyright (c) 1999-2004 LSI Logic Corporation
* Originally By: Steven J. Ralston
* (mailto:sjralston1@netscape.net)
* Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
* $Id: mptbase.h,v 1.144 2003/01/28 21:31:56 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@ -71,7 +65,6 @@
#include "lsi/mpi_fc.h" /* Fibre Channel (lowlevel) support */
#include "lsi/mpi_targ.h" /* SCSI/FCP Target protcol support */
#include "lsi/mpi_tool.h" /* Tools support */
#include "lsi/fc_log.h"
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@ -80,11 +73,11 @@
#endif
#ifndef COPYRIGHT
#define COPYRIGHT "Copyright (c) 1999-2004 " MODULEAUTHOR
#define COPYRIGHT "Copyright (c) 1999-2005 " MODULEAUTHOR
#endif
#define MPT_LINUX_VERSION_COMMON "3.01.20"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.01.20"
#define MPT_LINUX_VERSION_COMMON "3.03.02"
#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.03.02"
#define WHAT_MAGIC_STRING "@" "(" "#" ")"
#define show_mptmod_ver(s,ver) \
@ -203,7 +196,9 @@
typedef enum {
MPTBASE_DRIVER, /* MPT base class */
MPTCTL_DRIVER, /* MPT ioctl class */
MPTSCSIH_DRIVER, /* MPT SCSI host (initiator) class */
MPTSPI_DRIVER, /* MPT SPI host class */
MPTFC_DRIVER, /* MPT FC host class */
MPTSAS_DRIVER, /* MPT SAS host class */
MPTLAN_DRIVER, /* MPT LAN class */
MPTSTM_DRIVER, /* MPT SCSI target mode class */
MPTUNKNOWN_DRIVER
@ -212,11 +207,6 @@ typedef enum {
struct mpt_pci_driver{
int (*probe) (struct pci_dev *dev, const struct pci_device_id *id);
void (*remove) (struct pci_dev *dev);
void (*shutdown) (struct device * dev);
#ifdef CONFIG_PM
int (*resume) (struct pci_dev *dev);
int (*suspend) (struct pci_dev *dev, pm_message_t state);
#endif
};
/*
@ -483,6 +473,7 @@ typedef struct _ScsiCfgData {
u8 forceDv; /* 1 to force DV scheduling */
u8 noQas; /* Disable QAS for this adapter */
u8 Saf_Te; /* 1 to force all Processors as SAF-TE if Inquiry data length is too short to check for SAF-TE */
u8 mpt_dv; /* command line option: enhanced=1, basic=0 */
u8 rsvd[1];
} ScsiCfgData;
@ -571,11 +562,21 @@ typedef struct _MPT_ADAPTER
FCPortPage0_t fc_port_page0[2];
LANPage0_t lan_cnfg_page0;
LANPage1_t lan_cnfg_page1;
/*
* Description: errata_flag_1064
* If a PCIX read occurs within 1 or 2 cycles after the chip receives
* a split completion for a read data, an internal address pointer incorrectly
* increments by 32 bytes
*/
int errata_flag_1064;
u8 FirstWhoInit;
u8 upload_fw; /* If set, do a fw upload */
u8 reload_fw; /* Force a FW Reload on next reset */
u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */
u8 pad1[4];
int DoneCtx;
int TaskCtx;
int InternalCtx;
struct list_head list;
struct net_device *netdev;
} MPT_ADAPTER;
@ -773,12 +774,6 @@ typedef struct _mpt_sge {
#define DBG_DUMP_TM_REPLY_FRAME(mfp)
#endif
#ifdef MPT_DEBUG_NEH
#define nehprintk(x) printk x
#else
#define nehprintk(x)
#endif
#if defined(MPT_DEBUG_CONFIG) || defined(MPT_DEBUG)
#define dcprintk(x) printk x
#else
@ -898,6 +893,11 @@ typedef struct _MPT_SCSI_HOST {
unsigned long soft_resets; /* fw/external bus resets count */
unsigned long timeouts; /* cmd timeouts */
ushort sel_timeout[MPT_MAX_FC_DEVICES];
char *info_kbuf;
wait_queue_head_t scandv_waitq;
int scandv_wait_done;
long last_queue_full;
u8 mpt_pq_filter;
} MPT_SCSI_HOST;
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@ -931,6 +931,12 @@ typedef struct _x_config_parms {
/*
* Public entry points...
*/
extern int mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id);
extern void mpt_detach(struct pci_dev *pdev);
#ifdef CONFIG_PM
extern int mpt_suspend(struct pci_dev *pdev, pm_message_t state);
extern int mpt_resume(struct pci_dev *pdev);
#endif
extern int mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass);
extern void mpt_deregister(int cb_idx);
extern int mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc);

View File

@ -1,40 +1,12 @@
/*
* linux/drivers/message/fusion/mptctl.c
* Fusion MPT misc device (ioctl) driver.
* For use with PCI chip/adapter(s):
* LSIFC9xx/LSI409xx Fibre Channel
* mpt Ioctl driver.
* For use with LSI Logic PCI chip/adapters
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Credits:
* This driver would not exist if not for Alan Cox's development
* of the linux i2o driver.
*
* A special thanks to Pamela Delaney (LSI Logic) for tons of work
* and countless enhancements while adding support for the 1030
* chip family. Pam has been instrumental in the development of
* of the 2.xx.xx series fusion drivers, and her contributions are
* far too numerous to hope to list in one place.
*
* A huge debt of gratitude is owed to David S. Miller (DaveM)
* for fixing much of the stupid and broken stuff in the early
* driver while porting to sparc64 platform. THANK YOU!
*
* A big THANKS to Eddie C. Dost for fixing the ioctl path
* and most importantly f/w download on sparc64 platform!
* (plus Eddie's other helpful hints and insights)
*
* Thanks to Arnaldo Carvalho de Melo for finding and patching
* a potential memory leak in mptctl_do_fw_download(),
* and for some kmalloc insight:-)
*
* (see also mptbase.c)
*
* Copyright (c) 1999-2004 LSI Logic Corporation
* Originally By: Steven J. Ralston, Noah Romer
* (mailto:sjralston1@netscape.net)
* Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
* $Id: mptctl.c,v 1.63 2002/12/03 21:26:33 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@ -95,8 +67,8 @@
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
#define COPYRIGHT "Copyright (c) 1999-2004 LSI Logic Corporation"
#define MODULEAUTHOR "Steven J. Ralston, Noah Romer, Pamela Delaney"
#define COPYRIGHT "Copyright (c) 1999-2005 LSI Logic Corporation"
#define MODULEAUTHOR "LSI Logic Corporation"
#include "mptbase.h"
#include "mptctl.h"
@ -127,14 +99,14 @@ struct buflist {
* arg contents specific to function.
*/
static int mptctl_fw_download(unsigned long arg);
static int mptctl_getiocinfo (unsigned long arg, unsigned int cmd);
static int mptctl_gettargetinfo (unsigned long arg);
static int mptctl_readtest (unsigned long arg);
static int mptctl_mpt_command (unsigned long arg);
static int mptctl_eventquery (unsigned long arg);
static int mptctl_eventenable (unsigned long arg);
static int mptctl_eventreport (unsigned long arg);
static int mptctl_replace_fw (unsigned long arg);
static int mptctl_getiocinfo(unsigned long arg, unsigned int cmd);
static int mptctl_gettargetinfo(unsigned long arg);
static int mptctl_readtest(unsigned long arg);
static int mptctl_mpt_command(unsigned long arg);
static int mptctl_eventquery(unsigned long arg);
static int mptctl_eventenable(unsigned long arg);
static int mptctl_eventreport(unsigned long arg);
static int mptctl_replace_fw(unsigned long arg);
static int mptctl_do_reset(unsigned long arg);
static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
@ -149,11 +121,11 @@ static long compat_mpctl_ioctl(struct file *f, unsigned cmd, unsigned long arg);
/*
* Private function calls.
*/
static int mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr);
static int mptctl_do_mpt_command(struct mpt_ioctl_command karg, void __user *mfPtr);
static int mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen);
static MptSge_t *kbuf_alloc_2_sgl( int bytes, u32 dir, int sge_offset, int *frags,
static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags,
struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
static void kfree_sgl( MptSge_t *sgl, dma_addr_t sgl_dma,
static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
struct buflist *buflist, MPT_ADAPTER *ioc);
static void mptctl_timeout_expired (MPT_IOCTL *ioctl);
static int mptctl_bus_reset(MPT_IOCTL *ioctl);
@ -1119,7 +1091,7 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
int numDevices = 0;
unsigned int max_id;
int ii;
int port;
unsigned int port;
int cim_rev;
u8 revision;
@ -1162,9 +1134,7 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
return -ENODEV;
}
/* Verify the data transfer size is correct.
* Ignore the port setting.
*/
/* Verify the data transfer size is correct. */
if (karg->hdr.maxDataSize != data_size) {
printk(KERN_ERR "%s@%d::mptctl_getiocinfo - "
"Structure size mismatch. Command not completed.\n",
@ -1181,6 +1151,8 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
else
karg->adapterType = MPT_IOCTL_INTERFACE_SCSI;
if (karg->hdr.port > 1)
return -EINVAL;
port = karg->hdr.port;
karg->port = port;

View File

@ -5,22 +5,9 @@
* LSIFC9xx/LSI409xx Fibre Channel
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Credits:
* This driver would not exist if not for Alan Cox's development
* of the linux i2o driver.
*
* A huge debt of gratitude is owed to David S. Miller (DaveM)
* for fixing much of the stupid and broken stuff in the early
* driver while porting to sparc64 platform. THANK YOU!
*
* (see also mptbase.c)
*
* Copyright (c) 1999-2004 LSI Logic Corporation
* Originally By: Steven J. Ralston
* (mailto:sjralston1@netscape.net)
* Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
* $Id: mptctl.h,v 1.13 2002/12/03 21:26:33 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*

View File

@ -0,0 +1,431 @@
/*
* linux/drivers/message/fusion/mptfc.c
* For use with LSI Logic PCI chip/adapter(s)
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
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; version 2 of the License.
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.
NO WARRANTY
THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
solely responsible for determining the appropriateness of using and
distributing the Program and assumes all risks associated with its
exercise of rights under this Agreement, including but not limited to
the risks and costs of program errors, damage to or loss of data,
programs or equipment, and unavailability or interruption of operations.
DISCLAIMER OF LIABILITY
NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
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 "linux_compat.h" /* linux-2.6 tweaks */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/kdev_t.h>
#include <linux/blkdev.h>
#include <linux/delay.h> /* for mdelay */
#include <linux/interrupt.h> /* needed for in_interrupt() proto */
#include <linux/reboot.h> /* notifier code */
#include <linux/sched.h>
#include <linux/workqueue.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
#include "mptbase.h"
#include "mptscsih.h"
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#define my_NAME "Fusion MPT FC Host driver"
#define my_VERSION MPT_LINUX_VERSION_COMMON
#define MYNAM "mptfc"
MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
/* Command line args */
static int mpt_pq_filter = 0;
module_param(mpt_pq_filter, int, 0);
MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
static int mptfcDoneCtx = -1;
static int mptfcTaskCtx = -1;
static int mptfcInternalCtx = -1; /* Used only for internal commands */
static struct device_attribute mptfc_queue_depth_attr = {
.attr = {
.name = "queue_depth",
.mode = S_IWUSR,
},
.store = mptscsih_store_queue_depth,
};
static struct device_attribute *mptfc_dev_attrs[] = {
&mptfc_queue_depth_attr,
NULL,
};
static struct scsi_host_template mptfc_driver_template = {
.proc_name = "mptfc",
.proc_info = mptscsih_proc_info,
.name = "MPT FC Host",
.info = mptscsih_info,
.queuecommand = mptscsih_qcmd,
.slave_alloc = mptscsih_slave_alloc,
.slave_configure = mptscsih_slave_configure,
.slave_destroy = mptscsih_slave_destroy,
.eh_abort_handler = mptscsih_abort,
.eh_device_reset_handler = mptscsih_dev_reset,
.eh_bus_reset_handler = mptscsih_bus_reset,
.eh_host_reset_handler = mptscsih_host_reset,
.bios_param = mptscsih_bios_param,
.can_queue = MPT_FC_CAN_QUEUE,
.this_id = -1,
.sg_tablesize = MPT_SCSI_SG_DEPTH,
.max_sectors = 8192,
.cmd_per_lun = 7,
.use_clustering = ENABLE_CLUSTERING,
.sdev_attrs = mptfc_dev_attrs,
};
/****************************************************************************
* Supported hardware
*/
static struct pci_device_id mptfc_pci_table[] = {
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC909,
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919,
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929,
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC919X,
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC929X,
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC939X,
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
PCI_ANY_ID, PCI_ANY_ID },
{0} /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mptfc_probe - Installs scsi devices per bus.
* @pdev: Pointer to pci_dev structure
*
* Returns 0 for success, non-zero for failure.
*
*/
static int
mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct Scsi_Host *sh;
MPT_SCSI_HOST *hd;
MPT_ADAPTER *ioc;
unsigned long flags;
int sz, ii;
int numSGE = 0;
int scale;
int ioc_cap;
u8 *mem;
int error=0;
int r;
if ((r = mpt_attach(pdev,id)) != 0)
return r;
ioc = pci_get_drvdata(pdev);
ioc->DoneCtx = mptfcDoneCtx;
ioc->TaskCtx = mptfcTaskCtx;
ioc->InternalCtx = mptfcInternalCtx;
/* Added sanity check on readiness of the MPT adapter.
*/
if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
printk(MYIOC_s_WARN_FMT
"Skipping because it's not operational!\n",
ioc->name);
return -ENODEV;
}
if (!ioc->active) {
printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
ioc->name);
return -ENODEV;
}
/* Sanity check - ensure at least 1 port is INITIATOR capable
*/
ioc_cap = 0;
for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
if (ioc->pfacts[ii].ProtocolFlags &
MPI_PORTFACTS_PROTOCOL_INITIATOR)
ioc_cap ++;
}
if (!ioc_cap) {
printk(MYIOC_s_WARN_FMT
"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
ioc->name, ioc);
return -ENODEV;
}
sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
if (!sh) {
printk(MYIOC_s_WARN_FMT
"Unable to register controller with SCSI subsystem\n",
ioc->name);
return -1;
}
spin_lock_irqsave(&ioc->FreeQlock, flags);
/* Attach the SCSI Host to the IOC structure
*/
ioc->sh = sh;
sh->io_port = 0;
sh->n_io_port = 0;
sh->irq = 0;
/* set 16 byte cdb's */
sh->max_cmd_len = 16;
sh->max_id = MPT_MAX_FC_DEVICES<256 ? MPT_MAX_FC_DEVICES : 255;
sh->max_lun = MPT_LAST_LUN + 1;
sh->max_channel = 0;
sh->this_id = ioc->pfacts[0].PortSCSIID;
/* Required entry.
*/
sh->unique_id = ioc->id;
/* Verify that we won't exceed the maximum
* number of chain buffers
* We can optimize: ZZ = req_sz/sizeof(SGE)
* For 32bit SGE's:
* numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
* + (req_sz - 64)/sizeof(SGE)
* A slightly different algorithm is required for
* 64bit SGEs.
*/
scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
if (sizeof(dma_addr_t) == sizeof(u64)) {
numSGE = (scale - 1) *
(ioc->facts.MaxChainDepth-1) + scale +
(ioc->req_sz - 60) / (sizeof(dma_addr_t) +
sizeof(u32));
} else {
numSGE = 1 + (scale - 1) *
(ioc->facts.MaxChainDepth-1) + scale +
(ioc->req_sz - 64) / (sizeof(dma_addr_t) +
sizeof(u32));
}
if (numSGE < sh->sg_tablesize) {
/* Reset this value */
dprintk((MYIOC_s_INFO_FMT
"Resetting sg_tablesize to %d from %d\n",
ioc->name, numSGE, sh->sg_tablesize));
sh->sg_tablesize = numSGE;
}
/* Set the pci device pointer in Scsi_Host structure.
*/
scsi_set_device(sh, &ioc->pcidev->dev);
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
hd = (MPT_SCSI_HOST *) sh->hostdata;
hd->ioc = ioc;
/* SCSI needs scsi_cmnd lookup table!
* (with size equal to req_depth*PtrSz!)
*/
sz = ioc->req_depth * sizeof(void *);
mem = kmalloc(sz, GFP_ATOMIC);
if (mem == NULL) {
error = -ENOMEM;
goto mptfc_probe_failed;
}
memset(mem, 0, sz);
hd->ScsiLookup = (struct scsi_cmnd **) mem;
dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
ioc->name, hd->ScsiLookup, sz));
/* Allocate memory for the device structures.
* A non-Null pointer at an offset
* indicates a device exists.
* max_id = 1 + maximum id (hosts.h)
*/
sz = sh->max_id * sizeof(void *);
mem = kmalloc(sz, GFP_ATOMIC);
if (mem == NULL) {
error = -ENOMEM;
goto mptfc_probe_failed;
}
memset(mem, 0, sz);
hd->Targets = (VirtDevice **) mem;
dprintk((KERN_INFO
" Targets @ %p, sz=%d\n", hd->Targets, sz));
/* Clear the TM flags
*/
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
hd->resetPending = 0;
hd->abortSCpnt = NULL;
/* Clear the pointer used to store
* single-threaded commands, i.e., those
* issued during a bus scan, dv and
* configuration pages.
*/
hd->cmdPtr = NULL;
/* Initialize this SCSI Hosts' timers
* To use, set the timer expires field
* and add_timer
*/
init_timer(&hd->timer);
hd->timer.data = (unsigned long) hd;
hd->timer.function = mptscsih_timer_expired;
hd->mpt_pq_filter = mpt_pq_filter;
ddvprintk((MYIOC_s_INFO_FMT
"mpt_pq_filter %x\n",
ioc->name,
mpt_pq_filter));
init_waitqueue_head(&hd->scandv_waitq);
hd->scandv_wait_done = 0;
hd->last_queue_full = 0;
error = scsi_add_host (sh, &ioc->pcidev->dev);
if(error) {
dprintk((KERN_ERR MYNAM
"scsi_add_host failed\n"));
goto mptfc_probe_failed;
}
scsi_scan_host(sh);
return 0;
mptfc_probe_failed:
mptscsih_remove(pdev);
return error;
}
static struct pci_driver mptfc_driver = {
.name = "mptfc",
.id_table = mptfc_pci_table,
.probe = mptfc_probe,
.remove = __devexit_p(mptscsih_remove),
.driver = {
.shutdown = mptscsih_shutdown,
},
#ifdef CONFIG_PM
.suspend = mptscsih_suspend,
.resume = mptscsih_resume,
#endif
};
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptfc_init - Register MPT adapter(s) as SCSI host(s) with
* linux scsi mid-layer.
*
* Returns 0 for success, non-zero for failure.
*/
static int __init
mptfc_init(void)
{
show_mptmod_ver(my_NAME, my_VERSION);
mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
if (mpt_event_register(mptfcDoneCtx, mptscsih_event_process) == 0) {
devtprintk((KERN_INFO MYNAM
": Registered for IOC event notifications\n"));
}
if (mpt_reset_register(mptfcDoneCtx, mptscsih_ioc_reset) == 0) {
dprintk((KERN_INFO MYNAM
": Registered for IOC reset notifications\n"));
}
return pci_register_driver(&mptfc_driver);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptfc_exit - Unregisters MPT adapter(s)
*
*/
static void __exit
mptfc_exit(void)
{
pci_unregister_driver(&mptfc_driver);
mpt_reset_deregister(mptfcDoneCtx);
dprintk((KERN_INFO MYNAM
": Deregistered for IOC reset notifications\n"));
mpt_event_deregister(mptfcDoneCtx);
dprintk((KERN_INFO MYNAM
": Deregistered for IOC event notifications\n"));
mpt_deregister(mptfcInternalCtx);
mpt_deregister(mptfcTaskCtx);
mpt_deregister(mptfcDoneCtx);
}
module_init(mptfc_init);
module_exit(mptfc_exit);

View File

@ -1,33 +1,11 @@
/*
* linux/drivers/message/fusion/mptlan.c
* IP Over Fibre Channel device driver.
* For use with PCI chip/adapter(s):
* LSIFC9xx/LSI409xx Fibre Channel
* For use with LSI Logic Fibre Channel PCI chip/adapters
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Credits:
* This driver would not exist if not for Alan Cox's development
* of the linux i2o driver.
* Copyright (c) 2000-2005 LSI Logic Corporation
*
* Special thanks goes to the I2O LAN driver people at the
* University of Helsinki, who, unbeknownst to them, provided
* the inspiration and initial structure for this driver.
*
* A huge debt of gratitude is owed to David S. Miller (DaveM)
* for fixing much of the stupid and broken stuff in the early
* driver while porting to sparc64 platform. THANK YOU!
*
* A really huge debt of gratitude is owed to Eddie C. Dost
* for gobs of hard work fixing and optimizing LAN code.
* THANK YOU!
*
* (see also mptbase.c)
*
* Copyright (c) 2000-2004 LSI Logic Corporation
* Originally By: Noah Romer
* (mailto:mpt_linux_developer@lsil.com)
*
* $Id: mptlan.c,v 1.53 2002/10/17 20:15:58 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@ -221,7 +199,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
// NOTE! (Optimization) First case here is now caught in
// mptbase.c::mpt_interrupt() routine and callcack here
// is now skipped for this case! 20001218 -sralston
// is now skipped for this case!
#if 0
case LAN_REPLY_FORM_MESSAGE_CONTEXT:
// dioprintk((KERN_INFO MYNAM "/lan_reply: "
@ -234,7 +212,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
// dioprintk((MYNAM "/lan_reply: "
// "calling mpt_lan_send_reply (turbo)\n"));
// Potential BUG here? -sralston
// Potential BUG here?
// FreeReqFrame = mpt_lan_send_turbo(dev, tmsg);
// If/when mpt_lan_send_turbo would return 1 here,
// calling routine (mptbase.c|mpt_interrupt)
@ -310,8 +288,7 @@ lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
case MPI_FUNCTION_EVENT_NOTIFICATION:
case MPI_FUNCTION_EVENT_ACK:
/* UPDATE! 20010120 -sralston
* _EVENT_NOTIFICATION should NOT come down this path any more.
/* _EVENT_NOTIFICATION should NOT come down this path any more.
* Should be routed to mpt_lan_event_process(), but just in case...
*/
FreeReqFrame = 1;
@ -561,8 +538,8 @@ mpt_lan_close(struct net_device *dev)
}
}
kfree (priv->RcvCtl);
kfree (priv->mpt_rxfidx);
kfree(priv->RcvCtl);
kfree(priv->mpt_rxfidx);
for (i = 0; i < priv->tx_max_out; i++) {
if (priv->SendCtl[i].skb != NULL) {

View File

@ -1,3 +1,49 @@
/*
* linux/drivers/message/fusion/mptlan.h
* IP Over Fibre Channel device driver.
* For use with LSI Logic Fibre Channel PCI chip/adapters
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Copyright (c) 2000-2005 LSI Logic Corporation
*
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
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.
NO WARRANTY
THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
solely responsible for determining the appropriateness of using and
distributing the Program and assumes all risks associated with its
exercise of rights under this Agreement, including but not limited to
the risks and costs of program errors, damage to or loss of data,
programs or equipment, and unavailability or interruption of operations.
DISCLAIMER OF LIABILITY
NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
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
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/* mptlan.h */
#ifndef LINUX_MPTLAN_H_INCLUDED
@ -29,7 +75,7 @@
#include <asm/io.h>
/* Override mptbase.h by pre-defining these! */
#define MODULEAUTHOR "Noah Romer, Eddie C. Dost"
#define MODULEAUTHOR "LSI Logic Corporation"
#include "mptbase.h"

File diff suppressed because it is too large Load Diff

View File

@ -1,26 +1,13 @@
/*
* linux/drivers/message/fusion/mptscsih.h
* linux/drivers/message/fusion/mptscsi.h
* High performance SCSI / Fibre Channel SCSI Host device driver.
* For use with PCI chip/adapter(s):
* LSIFC9xx/LSI409xx Fibre Channel
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Credits:
* This driver would not exist if not for Alan Cox's development
* of the linux i2o driver.
*
* A huge debt of gratitude is owed to David S. Miller (DaveM)
* for fixing much of the stupid and broken stuff in the early
* driver while porting to sparc64 platform. THANK YOU!
*
* (see also mptbase.c)
*
* Copyright (c) 1999-2004 LSI Logic Corporation
* Originally By: Steven J. Ralston
* (mailto:netscape.net)
* Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
* $Id: mptscsih.h,v 1.21 2002/12/03 21:26:35 pdelaney Exp $
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
@ -91,4 +78,30 @@
#define MPTSCSIH_MIN_SYNC 0x08
#define MPTSCSIH_SAF_TE 0
#endif
extern void mptscsih_remove(struct pci_dev *);
extern void mptscsih_shutdown(struct device *);
#ifdef CONFIG_PM
extern int mptscsih_suspend(struct pci_dev *pdev, u32 state);
extern int mptscsih_resume(struct pci_dev *pdev);
#endif
extern int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func);
extern const char * mptscsih_info(struct Scsi_Host *SChost);
extern int mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *));
extern int mptscsih_slave_alloc(struct scsi_device *device);
extern void mptscsih_slave_destroy(struct scsi_device *device);
extern int mptscsih_slave_configure(struct scsi_device *device);
extern int mptscsih_abort(struct scsi_cmnd * SCpnt);
extern int mptscsih_dev_reset(struct scsi_cmnd * SCpnt);
extern int mptscsih_bus_reset(struct scsi_cmnd * SCpnt);
extern int mptscsih_host_reset(struct scsi_cmnd *SCpnt);
extern int mptscsih_bios_param(struct scsi_device * sdev, struct block_device *bdev, sector_t capacity, int geom[]);
extern int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
extern int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
extern int mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r);
extern int mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply);
extern int mptscsih_ioc_reset(MPT_ADAPTER *ioc, int post_reset);
extern ssize_t mptscsih_store_queue_depth(struct device *dev, const char *buf, size_t count);
extern void mptscsih_timer_expired(unsigned long data);

View File

@ -0,0 +1,486 @@
/*
* linux/drivers/message/fusion/mptspi.c
* For use with LSI Logic PCI chip/adapter(s)
* running LSI Logic Fusion MPT (Message Passing Technology) firmware.
*
* Copyright (c) 1999-2005 LSI Logic Corporation
* (mailto:mpt_linux_developer@lsil.com)
*
*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
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; version 2 of the License.
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.
NO WARRANTY
THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
solely responsible for determining the appropriateness of using and
distributing the Program and assumes all risks associated with its
exercise of rights under this Agreement, including but not limited to
the risks and costs of program errors, damage to or loss of data,
programs or equipment, and unavailability or interruption of operations.
DISCLAIMER OF LIABILITY
NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
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 "linux_compat.h" /* linux-2.6 tweaks */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/kdev_t.h>
#include <linux/blkdev.h>
#include <linux/delay.h> /* for mdelay */
#include <linux/interrupt.h> /* needed for in_interrupt() proto */
#include <linux/reboot.h> /* notifier code */
#include <linux/sched.h>
#include <linux/workqueue.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_tcq.h>
#include "mptbase.h"
#include "mptscsih.h"
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
#define my_NAME "Fusion MPT SPI Host driver"
#define my_VERSION MPT_LINUX_VERSION_COMMON
#define MYNAM "mptspi"
MODULE_AUTHOR(MODULEAUTHOR);
MODULE_DESCRIPTION(my_NAME);
MODULE_LICENSE("GPL");
/* Command line args */
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
static int mpt_dv = MPTSCSIH_DOMAIN_VALIDATION;
module_param(mpt_dv, int, 0);
MODULE_PARM_DESC(mpt_dv, " DV Algorithm: enhanced=1, basic=0 (default=MPTSCSIH_DOMAIN_VALIDATION=1)");
static int mpt_width = MPTSCSIH_MAX_WIDTH;
module_param(mpt_width, int, 0);
MODULE_PARM_DESC(mpt_width, " Max Bus Width: wide=1, narrow=0 (default=MPTSCSIH_MAX_WIDTH=1)");
static ushort mpt_factor = MPTSCSIH_MIN_SYNC;
module_param(mpt_factor, ushort, 0);
MODULE_PARM_DESC(mpt_factor, " Min Sync Factor (default=MPTSCSIH_MIN_SYNC=0x08)");
#endif
static int mpt_saf_te = MPTSCSIH_SAF_TE;
module_param(mpt_saf_te, int, 0);
MODULE_PARM_DESC(mpt_saf_te, " Force enabling SEP Processor: enable=1 (default=MPTSCSIH_SAF_TE=0)");
static int mpt_pq_filter = 0;
module_param(mpt_pq_filter, int, 0);
MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1 (default=0)");
static int mptspiDoneCtx = -1;
static int mptspiTaskCtx = -1;
static int mptspiInternalCtx = -1; /* Used only for internal commands */
static struct device_attribute mptspi_queue_depth_attr = {
.attr = {
.name = "queue_depth",
.mode = S_IWUSR,
},
.store = mptscsih_store_queue_depth,
};
static struct device_attribute *mptspi_dev_attrs[] = {
&mptspi_queue_depth_attr,
NULL,
};
static struct scsi_host_template mptspi_driver_template = {
.proc_name = "mptspi",
.proc_info = mptscsih_proc_info,
.name = "MPT SPI Host",
.info = mptscsih_info,
.queuecommand = mptscsih_qcmd,
.slave_alloc = mptscsih_slave_alloc,
.slave_configure = mptscsih_slave_configure,
.slave_destroy = mptscsih_slave_destroy,
.eh_abort_handler = mptscsih_abort,
.eh_device_reset_handler = mptscsih_dev_reset,
.eh_bus_reset_handler = mptscsih_bus_reset,
.eh_host_reset_handler = mptscsih_host_reset,
.bios_param = mptscsih_bios_param,
.can_queue = MPT_SCSI_CAN_QUEUE,
.this_id = -1,
.sg_tablesize = MPT_SCSI_SG_DEPTH,
.max_sectors = 8192,
.cmd_per_lun = 7,
.use_clustering = ENABLE_CLUSTERING,
.sdev_attrs = mptspi_dev_attrs,
};
/****************************************************************************
* Supported hardware
*/
static struct pci_device_id mptspi_pci_table[] = {
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030,
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_1030_53C1035,
PCI_ANY_ID, PCI_ANY_ID },
{0} /* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, mptspi_pci_table);
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*
* mptspi_probe - Installs scsi devices per bus.
* @pdev: Pointer to pci_dev structure
*
* Returns 0 for success, non-zero for failure.
*
*/
static int
mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct Scsi_Host *sh;
MPT_SCSI_HOST *hd;
MPT_ADAPTER *ioc;
unsigned long flags;
int sz, ii;
int numSGE = 0;
int scale;
int ioc_cap;
u8 *mem;
int error=0;
int r;
if ((r = mpt_attach(pdev,id)) != 0)
return r;
ioc = pci_get_drvdata(pdev);
ioc->DoneCtx = mptspiDoneCtx;
ioc->TaskCtx = mptspiTaskCtx;
ioc->InternalCtx = mptspiInternalCtx;
/* Added sanity check on readiness of the MPT adapter.
*/
if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
printk(MYIOC_s_WARN_FMT
"Skipping because it's not operational!\n",
ioc->name);
return -ENODEV;
}
if (!ioc->active) {
printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
ioc->name);
return -ENODEV;
}
/* Sanity check - ensure at least 1 port is INITIATOR capable
*/
ioc_cap = 0;
for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
if (ioc->pfacts[ii].ProtocolFlags &
MPI_PORTFACTS_PROTOCOL_INITIATOR)
ioc_cap ++;
}
if (!ioc_cap) {
printk(MYIOC_s_WARN_FMT
"Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
ioc->name, ioc);
return -ENODEV;
}
sh = scsi_host_alloc(&mptspi_driver_template, sizeof(MPT_SCSI_HOST));
if (!sh) {
printk(MYIOC_s_WARN_FMT
"Unable to register controller with SCSI subsystem\n",
ioc->name);
return -1;
}
spin_lock_irqsave(&ioc->FreeQlock, flags);
/* Attach the SCSI Host to the IOC structure
*/
ioc->sh = sh;
sh->io_port = 0;
sh->n_io_port = 0;
sh->irq = 0;
/* set 16 byte cdb's */
sh->max_cmd_len = 16;
/* Yikes! This is important!
* Otherwise, by default, linux
* only scans target IDs 0-7!
* pfactsN->MaxDevices unreliable
* (not supported in early
* versions of the FW).
* max_id = 1 + actual max id,
* max_lun = 1 + actual last lun,
* see hosts.h :o(
*/
sh->max_id = MPT_MAX_SCSI_DEVICES;
sh->max_lun = MPT_LAST_LUN + 1;
sh->max_channel = 0;
sh->this_id = ioc->pfacts[0].PortSCSIID;
/* Required entry.
*/
sh->unique_id = ioc->id;
/* Verify that we won't exceed the maximum
* number of chain buffers
* We can optimize: ZZ = req_sz/sizeof(SGE)
* For 32bit SGE's:
* numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
* + (req_sz - 64)/sizeof(SGE)
* A slightly different algorithm is required for
* 64bit SGEs.
*/
scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
if (sizeof(dma_addr_t) == sizeof(u64)) {
numSGE = (scale - 1) *
(ioc->facts.MaxChainDepth-1) + scale +
(ioc->req_sz - 60) / (sizeof(dma_addr_t) +
sizeof(u32));
} else {
numSGE = 1 + (scale - 1) *
(ioc->facts.MaxChainDepth-1) + scale +
(ioc->req_sz - 64) / (sizeof(dma_addr_t) +
sizeof(u32));
}
if (numSGE < sh->sg_tablesize) {
/* Reset this value */
dprintk((MYIOC_s_INFO_FMT
"Resetting sg_tablesize to %d from %d\n",
ioc->name, numSGE, sh->sg_tablesize));
sh->sg_tablesize = numSGE;
}
/* Set the pci device pointer in Scsi_Host structure.
*/
scsi_set_device(sh, &ioc->pcidev->dev);
spin_unlock_irqrestore(&ioc->FreeQlock, flags);
hd = (MPT_SCSI_HOST *) sh->hostdata;
hd->ioc = ioc;
/* SCSI needs scsi_cmnd lookup table!
* (with size equal to req_depth*PtrSz!)
*/
sz = ioc->req_depth * sizeof(void *);
mem = kmalloc(sz, GFP_ATOMIC);
if (mem == NULL) {
error = -ENOMEM;
goto mptspi_probe_failed;
}
memset(mem, 0, sz);
hd->ScsiLookup = (struct scsi_cmnd **) mem;
dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
ioc->name, hd->ScsiLookup, sz));
/* Allocate memory for the device structures.
* A non-Null pointer at an offset
* indicates a device exists.
* max_id = 1 + maximum id (hosts.h)
*/
sz = sh->max_id * sizeof(void *);
mem = kmalloc(sz, GFP_ATOMIC);
if (mem == NULL) {
error = -ENOMEM;
goto mptspi_probe_failed;
}
memset(mem, 0, sz);
hd->Targets = (VirtDevice **) mem;
dprintk((KERN_INFO
" Targets @ %p, sz=%d\n", hd->Targets, sz));
/* Clear the TM flags
*/
hd->tmPending = 0;
hd->tmState = TM_STATE_NONE;
hd->resetPending = 0;
hd->abortSCpnt = NULL;
/* Clear the pointer used to store
* single-threaded commands, i.e., those
* issued during a bus scan, dv and
* configuration pages.
*/
hd->cmdPtr = NULL;
/* Initialize this SCSI Hosts' timers
* To use, set the timer expires field
* and add_timer
*/
init_timer(&hd->timer);
hd->timer.data = (unsigned long) hd;
hd->timer.function = mptscsih_timer_expired;
ioc->spi_data.Saf_Te = mpt_saf_te;
hd->mpt_pq_filter = mpt_pq_filter;
#ifdef MPTSCSIH_ENABLE_DOMAIN_VALIDATION
if (ioc->spi_data.maxBusWidth > mpt_width)
ioc->spi_data.maxBusWidth = mpt_width;
if (ioc->spi_data.minSyncFactor < mpt_factor)
ioc->spi_data.minSyncFactor = mpt_factor;
if (ioc->spi_data.minSyncFactor == MPT_ASYNC) {
ioc->spi_data.maxSyncOffset = 0;
}
ioc->spi_data.mpt_dv = mpt_dv;
hd->negoNvram = 0;
ddvprintk((MYIOC_s_INFO_FMT
"dv %x width %x factor %x saf_te %x mpt_pq_filter %x\n",
ioc->name,
mpt_dv,
mpt_width,
mpt_factor,
mpt_saf_te,
mpt_pq_filter));
#else
hd->negoNvram = MPT_SCSICFG_USE_NVRAM;
ddvprintk((MYIOC_s_INFO_FMT
"saf_te %x mpt_pq_filter %x\n",
ioc->name,
mpt_saf_te,
mpt_pq_filter));
#endif
ioc->spi_data.forceDv = 0;
ioc->spi_data.noQas = 0;
for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
ioc->spi_data.dvStatus[ii] =
MPT_SCSICFG_NEGOTIATE;
for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++)
ioc->spi_data.dvStatus[ii] |=
MPT_SCSICFG_DV_NOT_DONE;
init_waitqueue_head(&hd->scandv_waitq);
hd->scandv_wait_done = 0;
hd->last_queue_full = 0;
error = scsi_add_host (sh, &ioc->pcidev->dev);
if(error) {
dprintk((KERN_ERR MYNAM
"scsi_add_host failed\n"));
goto mptspi_probe_failed;
}
scsi_scan_host(sh);
return 0;
mptspi_probe_failed:
mptscsih_remove(pdev);
return error;
}
static struct pci_driver mptspi_driver = {
.name = "mptspi",
.id_table = mptspi_pci_table,
.probe = mptspi_probe,
.remove = __devexit_p(mptscsih_remove),
.driver = {
.shutdown = mptscsih_shutdown,
},
#ifdef CONFIG_PM
.suspend = mptscsih_suspend,
.resume = mptscsih_resume,
#endif
};
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptspi_init - Register MPT adapter(s) as SCSI host(s) with
* linux scsi mid-layer.
*
* Returns 0 for success, non-zero for failure.
*/
static int __init
mptspi_init(void)
{
show_mptmod_ver(my_NAME, my_VERSION);
mptspiDoneCtx = mpt_register(mptscsih_io_done, MPTSPI_DRIVER);
mptspiTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSPI_DRIVER);
mptspiInternalCtx = mpt_register(mptscsih_scandv_complete, MPTSPI_DRIVER);
if (mpt_event_register(mptspiDoneCtx, mptscsih_event_process) == 0) {
devtprintk((KERN_INFO MYNAM
": Registered for IOC event notifications\n"));
}
if (mpt_reset_register(mptspiDoneCtx, mptscsih_ioc_reset) == 0) {
dprintk((KERN_INFO MYNAM
": Registered for IOC reset notifications\n"));
}
return pci_register_driver(&mptspi_driver);
}
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
/**
* mptspi_exit - Unregisters MPT adapter(s)
*
*/
static void __exit
mptspi_exit(void)
{
pci_unregister_driver(&mptspi_driver);
mpt_reset_deregister(mptspiDoneCtx);
dprintk((KERN_INFO MYNAM
": Deregistered for IOC reset notifications\n"));
mpt_event_deregister(mptspiDoneCtx);
dprintk((KERN_INFO MYNAM
": Deregistered for IOC event notifications\n"));
mpt_deregister(mptspiInternalCtx);
mpt_deregister(mptspiTaskCtx);
mpt_deregister(mptspiDoneCtx);
}
module_init(mptspi_init);
module_exit(mptspi_exit);

View File

@ -54,6 +54,7 @@
#include <linux/config.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/compiler.h>
#include <linux/netdevice.h>
@ -91,16 +92,17 @@ KERN_INFO DRV_NAME ": 10/100 PCI Ethernet driver v" DRV_VERSION " (" DRV_RELDATE
MODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>");
MODULE_DESCRIPTION("RealTek RTL-8139C+ series 10/100 PCI Ethernet driver");
MODULE_VERSION(DRV_VERSION);
MODULE_LICENSE("GPL");
static int debug = -1;
MODULE_PARM (debug, "i");
module_param(debug, int, 0);
MODULE_PARM_DESC (debug, "8139cp: bitmapped message enable number");
/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
The RTL chips use a 64 element hash table based on the Ethernet CRC. */
static int multicast_filter_limit = 32;
MODULE_PARM (multicast_filter_limit, "i");
module_param(multicast_filter_limit, int, 0);
MODULE_PARM_DESC (multicast_filter_limit, "8139cp: maximum number of filtered multicast addresses");
#define PFX DRV_NAME ": "
@ -186,6 +188,9 @@ enum {
RingEnd = (1 << 30), /* End of descriptor ring */
FirstFrag = (1 << 29), /* First segment of a packet */
LastFrag = (1 << 28), /* Final segment of a packet */
LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */
MSSShift = 16, /* MSS value position */
MSSMask = 0xfff, /* MSS value: 11 bits */
TxError = (1 << 23), /* Tx error summary */
RxError = (1 << 20), /* Rx error summary */
IPCS = (1 << 18), /* Calculate IP checksum */
@ -312,7 +317,7 @@ struct cp_desc {
struct ring_info {
struct sk_buff *skb;
dma_addr_t mapping;
unsigned frag;
u32 len;
};
struct cp_dma_stats {
@ -394,6 +399,9 @@ struct cp_private {
static void __cp_set_rx_mode (struct net_device *dev);
static void cp_tx (struct cp_private *cp);
static void cp_clean_rings (struct cp_private *cp);
#ifdef CONFIG_NET_POLL_CONTROLLER
static void cp_poll_controller(struct net_device *dev);
#endif
static struct pci_device_id cp_pci_tbl[] = {
{ PCI_VENDOR_ID_REALTEK, PCI_DEVICE_ID_REALTEK_8139,
@ -688,6 +696,19 @@ cp_interrupt (int irq, void *dev_instance, struct pt_regs *regs)
return IRQ_HANDLED;
}
#ifdef CONFIG_NET_POLL_CONTROLLER
/*
* Polling receive - used by netconsole and other diagnostic tools
* to allow network i/o with interrupts disabled.
*/
static void cp_poll_controller(struct net_device *dev)
{
disable_irq(dev->irq);
cp_interrupt(dev->irq, dev, NULL);
enable_irq(dev->irq);
}
#endif
static void cp_tx (struct cp_private *cp)
{
unsigned tx_head = cp->tx_head;
@ -707,7 +728,7 @@ static void cp_tx (struct cp_private *cp)
BUG();
pci_unmap_single(cp->pdev, cp->tx_skb[tx_tail].mapping,
skb->len, PCI_DMA_TODEVICE);
cp->tx_skb[tx_tail].len, PCI_DMA_TODEVICE);
if (status & LastFrag) {
if (status & (TxError | TxFIFOUnder)) {
@ -749,10 +770,11 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
struct cp_private *cp = netdev_priv(dev);
unsigned entry;
u32 eor;
u32 eor, flags;
#if CP_VLAN_TAG_USED
u32 vlan_tag = 0;
#endif
int mss = 0;
spin_lock_irq(&cp->lock);
@ -772,6 +794,9 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
entry = cp->tx_head;
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
if (dev->features & NETIF_F_TSO)
mss = skb_shinfo(skb)->tso_size;
if (skb_shinfo(skb)->nr_frags == 0) {
struct cp_desc *txd = &cp->tx_ring[entry];
u32 len;
@ -783,26 +808,26 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
txd->addr = cpu_to_le64(mapping);
wmb();
if (skb->ip_summed == CHECKSUM_HW) {
flags = eor | len | DescOwn | FirstFrag | LastFrag;
if (mss)
flags |= LargeSend | ((mss & MSSMask) << MSSShift);
else if (skb->ip_summed == CHECKSUM_HW) {
const struct iphdr *ip = skb->nh.iph;
if (ip->protocol == IPPROTO_TCP)
txd->opts1 = cpu_to_le32(eor | len | DescOwn |
FirstFrag | LastFrag |
IPCS | TCPCS);
flags |= IPCS | TCPCS;
else if (ip->protocol == IPPROTO_UDP)
txd->opts1 = cpu_to_le32(eor | len | DescOwn |
FirstFrag | LastFrag |
IPCS | UDPCS);
flags |= IPCS | UDPCS;
else
BUG();
} else
txd->opts1 = cpu_to_le32(eor | len | DescOwn |
FirstFrag | LastFrag);
WARN_ON(1); /* we need a WARN() */
}
txd->opts1 = cpu_to_le32(flags);
wmb();
cp->tx_skb[entry].skb = skb;
cp->tx_skb[entry].mapping = mapping;
cp->tx_skb[entry].frag = 0;
cp->tx_skb[entry].len = len;
entry = NEXT_TX(entry);
} else {
struct cp_desc *txd;
@ -820,7 +845,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
first_len, PCI_DMA_TODEVICE);
cp->tx_skb[entry].skb = skb;
cp->tx_skb[entry].mapping = first_mapping;
cp->tx_skb[entry].frag = 1;
cp->tx_skb[entry].len = first_len;
entry = NEXT_TX(entry);
for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
@ -836,16 +861,19 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
len, PCI_DMA_TODEVICE);
eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0;
if (skb->ip_summed == CHECKSUM_HW) {
ctrl = eor | len | DescOwn | IPCS;
ctrl = eor | len | DescOwn;
if (mss)
ctrl |= LargeSend |
((mss & MSSMask) << MSSShift);
else if (skb->ip_summed == CHECKSUM_HW) {
if (ip->protocol == IPPROTO_TCP)
ctrl |= TCPCS;
ctrl |= IPCS | TCPCS;
else if (ip->protocol == IPPROTO_UDP)
ctrl |= UDPCS;
ctrl |= IPCS | UDPCS;
else
BUG();
} else
ctrl = eor | len | DescOwn;
}
if (frag == skb_shinfo(skb)->nr_frags - 1)
ctrl |= LastFrag;
@ -860,7 +888,7 @@ static int cp_start_xmit (struct sk_buff *skb, struct net_device *dev)
cp->tx_skb[entry].skb = skb;
cp->tx_skb[entry].mapping = mapping;
cp->tx_skb[entry].frag = frag + 2;
cp->tx_skb[entry].len = len;
entry = NEXT_TX(entry);
}
@ -1074,7 +1102,6 @@ static int cp_refill_rx (struct cp_private *cp)
cp->rx_skb[i].mapping = pci_map_single(cp->pdev,
skb->tail, cp->rx_buf_sz, PCI_DMA_FROMDEVICE);
cp->rx_skb[i].skb = skb;
cp->rx_skb[i].frag = 0;
cp->rx_ring[i].opts2 = 0;
cp->rx_ring[i].addr = cpu_to_le64(cp->rx_skb[i].mapping);
@ -1126,9 +1153,6 @@ static void cp_clean_rings (struct cp_private *cp)
{
unsigned i;
memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
for (i = 0; i < CP_RX_RING_SIZE; i++) {
if (cp->rx_skb[i].skb) {
pci_unmap_single(cp->pdev, cp->rx_skb[i].mapping,
@ -1140,13 +1164,18 @@ static void cp_clean_rings (struct cp_private *cp)
for (i = 0; i < CP_TX_RING_SIZE; i++) {
if (cp->tx_skb[i].skb) {
struct sk_buff *skb = cp->tx_skb[i].skb;
pci_unmap_single(cp->pdev, cp->tx_skb[i].mapping,
skb->len, PCI_DMA_TODEVICE);
dev_kfree_skb(skb);
cp->tx_skb[i].len, PCI_DMA_TODEVICE);
if (le32_to_cpu(cp->tx_ring[i].opts1) & LastFrag)
dev_kfree_skb(skb);
cp->net_stats.tx_dropped++;
}
}
memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE);
memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE);
memset(&cp->rx_skb, 0, sizeof(struct ring_info) * CP_RX_RING_SIZE);
memset(&cp->tx_skb, 0, sizeof(struct ring_info) * CP_TX_RING_SIZE);
}
@ -1538,6 +1567,8 @@ static struct ethtool_ops cp_ethtool_ops = {
.set_tx_csum = ethtool_op_set_tx_csum, /* local! */
.get_sg = ethtool_op_get_sg,
.set_sg = ethtool_op_set_sg,
.get_tso = ethtool_op_get_tso,
.set_tso = ethtool_op_set_tso,
.get_regs = cp_get_regs,
.get_wol = cp_get_wol,
.set_wol = cp_set_wol,
@ -1749,6 +1780,9 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
dev->get_stats = cp_get_stats;
dev->do_ioctl = cp_ioctl;
dev->poll = cp_rx_poll;
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = cp_poll_controller;
#endif
dev->weight = 16; /* arbitrary? from NAPI_HOWTO.txt. */
#ifdef BROKEN
dev->change_mtu = cp_change_mtu;
@ -1768,6 +1802,10 @@ static int cp_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (pci_using_dac)
dev->features |= NETIF_F_HIGHDMA;
#if 0 /* disabled by default until verified */
dev->features |= NETIF_F_TSO;
#endif
dev->irq = pdev->irq;
rc = register_netdev(dev);

View File

@ -569,7 +569,7 @@ struct rtl_extra_stats {
};
struct rtl8139_private {
void *mmio_addr;
void __iomem *mmio_addr;
int drv_flags;
struct pci_dev *pci_dev;
u32 msg_enable;
@ -614,7 +614,7 @@ MODULE_PARM_DESC (multicast_filter_limit, "8139too maximum number of filtered mu
MODULE_PARM_DESC (media, "8139too: Bits 4+9: force full duplex, bit 5: 100Mbps");
MODULE_PARM_DESC (full_duplex, "8139too: Force full duplex for board(s) (1)");
static int read_eeprom (void *ioaddr, int location, int addr_len);
static int read_eeprom (void __iomem *ioaddr, int location, int addr_len);
static int rtl8139_open (struct net_device *dev);
static int mdio_read (struct net_device *dev, int phy_id, int location);
static void mdio_write (struct net_device *dev, int phy_id, int location,
@ -638,46 +638,20 @@ static void __set_rx_mode (struct net_device *dev);
static void rtl8139_hw_start (struct net_device *dev);
static struct ethtool_ops rtl8139_ethtool_ops;
#ifdef USE_IO_OPS
#define RTL_R8(reg) inb (((unsigned long)ioaddr) + (reg))
#define RTL_R16(reg) inw (((unsigned long)ioaddr) + (reg))
#define RTL_R32(reg) ((unsigned long) inl (((unsigned long)ioaddr) + (reg)))
#define RTL_W8(reg, val8) outb ((val8), ((unsigned long)ioaddr) + (reg))
#define RTL_W16(reg, val16) outw ((val16), ((unsigned long)ioaddr) + (reg))
#define RTL_W32(reg, val32) outl ((val32), ((unsigned long)ioaddr) + (reg))
#define RTL_W8_F RTL_W8
#define RTL_W16_F RTL_W16
#define RTL_W32_F RTL_W32
#undef readb
#undef readw
#undef readl
#undef writeb
#undef writew
#undef writel
#define readb(addr) inb((unsigned long)(addr))
#define readw(addr) inw((unsigned long)(addr))
#define readl(addr) inl((unsigned long)(addr))
#define writeb(val,addr) outb((val),(unsigned long)(addr))
#define writew(val,addr) outw((val),(unsigned long)(addr))
#define writel(val,addr) outl((val),(unsigned long)(addr))
#else
/* write MMIO register, with flush */
/* Flush avoids rtl8139 bug w/ posted MMIO writes */
#define RTL_W8_F(reg, val8) do { writeb ((val8), ioaddr + (reg)); readb (ioaddr + (reg)); } while (0)
#define RTL_W16_F(reg, val16) do { writew ((val16), ioaddr + (reg)); readw (ioaddr + (reg)); } while (0)
#define RTL_W32_F(reg, val32) do { writel ((val32), ioaddr + (reg)); readl (ioaddr + (reg)); } while (0)
#define RTL_W8_F(reg, val8) do { iowrite8 ((val8), ioaddr + (reg)); ioread8 (ioaddr + (reg)); } while (0)
#define RTL_W16_F(reg, val16) do { iowrite16 ((val16), ioaddr + (reg)); ioread16 (ioaddr + (reg)); } while (0)
#define RTL_W32_F(reg, val32) do { iowrite32 ((val32), ioaddr + (reg)); ioread32 (ioaddr + (reg)); } while (0)
#define MMIO_FLUSH_AUDIT_COMPLETE 1
#if MMIO_FLUSH_AUDIT_COMPLETE
/* write MMIO register */
#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg))
#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg))
#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg))
#define RTL_W8(reg, val8) iowrite8 ((val8), ioaddr + (reg))
#define RTL_W16(reg, val16) iowrite16 ((val16), ioaddr + (reg))
#define RTL_W32(reg, val32) iowrite32 ((val32), ioaddr + (reg))
#else
@ -689,11 +663,9 @@ static struct ethtool_ops rtl8139_ethtool_ops;
#endif /* MMIO_FLUSH_AUDIT_COMPLETE */
/* read MMIO register */
#define RTL_R8(reg) readb (ioaddr + (reg))
#define RTL_R16(reg) readw (ioaddr + (reg))
#define RTL_R32(reg) ((unsigned long) readl (ioaddr + (reg)))
#endif /* USE_IO_OPS */
#define RTL_R8(reg) ioread8 (ioaddr + (reg))
#define RTL_R16(reg) ioread16 (ioaddr + (reg))
#define RTL_R32(reg) ((unsigned long) ioread32 (ioaddr + (reg)))
static const u16 rtl8139_intr_mask =
@ -740,10 +712,13 @@ static void __rtl8139_cleanup_dev (struct net_device *dev)
assert (tp->pci_dev != NULL);
pdev = tp->pci_dev;
#ifndef USE_IO_OPS
#ifdef USE_IO_OPS
if (tp->mmio_addr)
iounmap (tp->mmio_addr);
#endif /* !USE_IO_OPS */
ioport_unmap (tp->mmio_addr);
#else
if (tp->mmio_addr)
pci_iounmap (pdev, tp->mmio_addr);
#endif /* USE_IO_OPS */
/* it's ok to call this even if we have no regions to free */
pci_release_regions (pdev);
@ -753,7 +728,7 @@ static void __rtl8139_cleanup_dev (struct net_device *dev)
}
static void rtl8139_chip_reset (void *ioaddr)
static void rtl8139_chip_reset (void __iomem *ioaddr)
{
int i;
@ -773,7 +748,7 @@ static void rtl8139_chip_reset (void *ioaddr)
static int __devinit rtl8139_init_board (struct pci_dev *pdev,
struct net_device **dev_out)
{
void *ioaddr;
void __iomem *ioaddr;
struct net_device *dev;
struct rtl8139_private *tp;
u8 tmp8;
@ -855,13 +830,18 @@ static int __devinit rtl8139_init_board (struct pci_dev *pdev,
pci_set_master (pdev);
#ifdef USE_IO_OPS
ioaddr = (void *) pio_start;
ioaddr = ioport_map(pio_start, pio_len);
if (!ioaddr) {
printk (KERN_ERR PFX "%s: cannot map PIO, aborting\n", pci_name(pdev));
rc = -EIO;
goto err_out;
}
dev->base_addr = pio_start;
tp->mmio_addr = ioaddr;
tp->regs_len = pio_len;
#else
/* ioremap MMIO region */
ioaddr = ioremap (mmio_start, mmio_len);
ioaddr = pci_iomap(pdev, 1, 0);
if (ioaddr == NULL) {
printk (KERN_ERR PFX "%s: cannot remap MMIO, aborting\n", pci_name(pdev));
rc = -EIO;
@ -947,7 +927,7 @@ static int __devinit rtl8139_init_one (struct pci_dev *pdev,
struct net_device *dev = NULL;
struct rtl8139_private *tp;
int i, addr_len, option;
void *ioaddr;
void __iomem *ioaddr;
static int board_idx = -1;
u8 pci_rev;
@ -1147,47 +1127,46 @@ static void __devexit rtl8139_remove_one (struct pci_dev *pdev)
No extra delay is needed with 33Mhz PCI, but 66Mhz may change this.
*/
#define eeprom_delay() readl(ee_addr)
#define eeprom_delay() RTL_R32(Cfg9346)
/* The EEPROM commands include the alway-set leading bit. */
#define EE_WRITE_CMD (5)
#define EE_READ_CMD (6)
#define EE_ERASE_CMD (7)
static int __devinit read_eeprom (void *ioaddr, int location, int addr_len)
static int __devinit read_eeprom (void __iomem *ioaddr, int location, int addr_len)
{
int i;
unsigned retval = 0;
void *ee_addr = ioaddr + Cfg9346;
int read_cmd = location | (EE_READ_CMD << addr_len);
writeb (EE_ENB & ~EE_CS, ee_addr);
writeb (EE_ENB, ee_addr);
RTL_W8 (Cfg9346, EE_ENB & ~EE_CS);
RTL_W8 (Cfg9346, EE_ENB);
eeprom_delay ();
/* Shift the read command bits out. */
for (i = 4 + addr_len; i >= 0; i--) {
int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
writeb (EE_ENB | dataval, ee_addr);
RTL_W8 (Cfg9346, EE_ENB | dataval);
eeprom_delay ();
writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
RTL_W8 (Cfg9346, EE_ENB | dataval | EE_SHIFT_CLK);
eeprom_delay ();
}
writeb (EE_ENB, ee_addr);
RTL_W8 (Cfg9346, EE_ENB);
eeprom_delay ();
for (i = 16; i > 0; i--) {
writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);
RTL_W8 (Cfg9346, EE_ENB | EE_SHIFT_CLK);
eeprom_delay ();
retval =
(retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 :
(retval << 1) | ((RTL_R8 (Cfg9346) & EE_DATA_READ) ? 1 :
0);
writeb (EE_ENB, ee_addr);
RTL_W8 (Cfg9346, EE_ENB);
eeprom_delay ();
}
/* Terminate the EEPROM access. */
writeb (~EE_CS, ee_addr);
RTL_W8 (Cfg9346, ~EE_CS);
eeprom_delay ();
return retval;
@ -1206,7 +1185,7 @@ static int __devinit read_eeprom (void *ioaddr, int location, int addr_len)
#define MDIO_WRITE0 (MDIO_DIR)
#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT)
#define mdio_delay(mdio_addr) readb(mdio_addr)
#define mdio_delay() RTL_R8(Config4)
static char mii_2_8139_map[8] = {
@ -1223,15 +1202,15 @@ static char mii_2_8139_map[8] = {
#ifdef CONFIG_8139TOO_8129
/* Syncronize the MII management interface by shifting 32 one bits out. */
static void mdio_sync (void *mdio_addr)
static void mdio_sync (void __iomem *ioaddr)
{
int i;
for (i = 32; i >= 0; i--) {
writeb (MDIO_WRITE1, mdio_addr);
mdio_delay (mdio_addr);
writeb (MDIO_WRITE1 | MDIO_CLK, mdio_addr);
mdio_delay (mdio_addr);
RTL_W8 (Config4, MDIO_WRITE1);
mdio_delay ();
RTL_W8 (Config4, MDIO_WRITE1 | MDIO_CLK);
mdio_delay ();
}
}
#endif
@ -1241,35 +1220,36 @@ static int mdio_read (struct net_device *dev, int phy_id, int location)
struct rtl8139_private *tp = netdev_priv(dev);
int retval = 0;
#ifdef CONFIG_8139TOO_8129
void *mdio_addr = tp->mmio_addr + Config4;
void __iomem *ioaddr = tp->mmio_addr;
int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
int i;
#endif
if (phy_id > 31) { /* Really a 8139. Use internal registers. */
void __iomem *ioaddr = tp->mmio_addr;
return location < 8 && mii_2_8139_map[location] ?
readw (tp->mmio_addr + mii_2_8139_map[location]) : 0;
RTL_R16 (mii_2_8139_map[location]) : 0;
}
#ifdef CONFIG_8139TOO_8129
mdio_sync (mdio_addr);
mdio_sync (ioaddr);
/* Shift the read command bits out. */
for (i = 15; i >= 0; i--) {
int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
writeb (MDIO_DIR | dataval, mdio_addr);
mdio_delay (mdio_addr);
writeb (MDIO_DIR | dataval | MDIO_CLK, mdio_addr);
mdio_delay (mdio_addr);
RTL_W8 (Config4, MDIO_DIR | dataval);
mdio_delay ();
RTL_W8 (Config4, MDIO_DIR | dataval | MDIO_CLK);
mdio_delay ();
}
/* Read the two transition, 16 data, and wire-idle bits. */
for (i = 19; i > 0; i--) {
writeb (0, mdio_addr);
mdio_delay (mdio_addr);
retval = (retval << 1) | ((readb (mdio_addr) & MDIO_DATA_IN) ? 1 : 0);
writeb (MDIO_CLK, mdio_addr);
mdio_delay (mdio_addr);
RTL_W8 (Config4, 0);
mdio_delay ();
retval = (retval << 1) | ((RTL_R8 (Config4) & MDIO_DATA_IN) ? 1 : 0);
RTL_W8 (Config4, MDIO_CLK);
mdio_delay ();
}
#endif
@ -1282,13 +1262,13 @@ static void mdio_write (struct net_device *dev, int phy_id, int location,
{
struct rtl8139_private *tp = netdev_priv(dev);
#ifdef CONFIG_8139TOO_8129
void *mdio_addr = tp->mmio_addr + Config4;
void __iomem *ioaddr = tp->mmio_addr;
int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
int i;
#endif
if (phy_id > 31) { /* Really a 8139. Use internal registers. */
void *ioaddr = tp->mmio_addr;
void __iomem *ioaddr = tp->mmio_addr;
if (location == 0) {
RTL_W8 (Cfg9346, Cfg9346_Unlock);
RTL_W16 (BasicModeCtrl, value);
@ -1299,23 +1279,23 @@ static void mdio_write (struct net_device *dev, int phy_id, int location,
}
#ifdef CONFIG_8139TOO_8129
mdio_sync (mdio_addr);
mdio_sync (ioaddr);
/* Shift the command bits out. */
for (i = 31; i >= 0; i--) {
int dataval =
(mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
writeb (dataval, mdio_addr);
mdio_delay (mdio_addr);
writeb (dataval | MDIO_CLK, mdio_addr);
mdio_delay (mdio_addr);
RTL_W8 (Config4, dataval);
mdio_delay ();
RTL_W8 (Config4, dataval | MDIO_CLK);
mdio_delay ();
}
/* Clear out extra bits. */
for (i = 2; i > 0; i--) {
writeb (0, mdio_addr);
mdio_delay (mdio_addr);
writeb (MDIO_CLK, mdio_addr);
mdio_delay (mdio_addr);
RTL_W8 (Config4, 0);
mdio_delay ();
RTL_W8 (Config4, MDIO_CLK);
mdio_delay ();
}
#endif
}
@ -1325,7 +1305,7 @@ static int rtl8139_open (struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
int retval;
void *ioaddr = tp->mmio_addr;
void __iomem *ioaddr = tp->mmio_addr;
retval = request_irq (dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev);
if (retval)
@ -1382,7 +1362,7 @@ static void rtl_check_media (struct net_device *dev, unsigned int init_media)
static void rtl8139_hw_start (struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
void __iomem *ioaddr = tp->mmio_addr;
u32 i;
u8 tmp;
@ -1484,7 +1464,7 @@ static void rtl8139_tune_twister (struct net_device *dev,
struct rtl8139_private *tp)
{
int linkcase;
void *ioaddr = tp->mmio_addr;
void __iomem *ioaddr = tp->mmio_addr;
/* This is a complicated state machine to configure the "twister" for
impedance/echos based on the cable length.
@ -1568,7 +1548,7 @@ static void rtl8139_tune_twister (struct net_device *dev,
static inline void rtl8139_thread_iter (struct net_device *dev,
struct rtl8139_private *tp,
void *ioaddr)
void __iomem *ioaddr)
{
int mii_lpa;
@ -1676,7 +1656,7 @@ static inline void rtl8139_tx_clear (struct rtl8139_private *tp)
static void rtl8139_tx_timeout (struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
void __iomem *ioaddr = tp->mmio_addr;
int i;
u8 tmp8;
unsigned long flags;
@ -1721,7 +1701,7 @@ static void rtl8139_tx_timeout (struct net_device *dev)
static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
void __iomem *ioaddr = tp->mmio_addr;
unsigned int entry;
unsigned int len = skb->len;
@ -1763,7 +1743,7 @@ static int rtl8139_start_xmit (struct sk_buff *skb, struct net_device *dev)
static void rtl8139_tx_interrupt (struct net_device *dev,
struct rtl8139_private *tp,
void *ioaddr)
void __iomem *ioaddr)
{
unsigned long dirty_tx, tx_left;
@ -1833,7 +1813,7 @@ static void rtl8139_tx_interrupt (struct net_device *dev,
/* TODO: clean this up! Rx reset need not be this intensive */
static void rtl8139_rx_err (u32 rx_status, struct net_device *dev,
struct rtl8139_private *tp, void *ioaddr)
struct rtl8139_private *tp, void __iomem *ioaddr)
{
u8 tmp8;
#ifdef CONFIG_8139_OLD_RX_RESET
@ -1930,7 +1910,7 @@ static __inline__ void wrap_copy(struct sk_buff *skb, const unsigned char *ring,
static void rtl8139_isr_ack(struct rtl8139_private *tp)
{
void *ioaddr = tp->mmio_addr;
void __iomem *ioaddr = tp->mmio_addr;
u16 status;
status = RTL_R16 (IntrStatus) & RxAckBits;
@ -1949,7 +1929,7 @@ static void rtl8139_isr_ack(struct rtl8139_private *tp)
static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp,
int budget)
{
void *ioaddr = tp->mmio_addr;
void __iomem *ioaddr = tp->mmio_addr;
int received = 0;
unsigned char *rx_ring = tp->rx_ring;
unsigned int cur_rx = tp->cur_rx;
@ -2087,7 +2067,7 @@ out:
static void rtl8139_weird_interrupt (struct net_device *dev,
struct rtl8139_private *tp,
void *ioaddr,
void __iomem *ioaddr,
int status, int link_changed)
{
DPRINTK ("%s: Abnormal interrupt, status %8.8x.\n",
@ -2127,7 +2107,7 @@ static void rtl8139_weird_interrupt (struct net_device *dev,
static int rtl8139_poll(struct net_device *dev, int *budget)
{
struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
void __iomem *ioaddr = tp->mmio_addr;
int orig_budget = min(*budget, dev->quota);
int done = 1;
@ -2165,7 +2145,7 @@ static irqreturn_t rtl8139_interrupt (int irq, void *dev_instance,
{
struct net_device *dev = (struct net_device *) dev_instance;
struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
void __iomem *ioaddr = tp->mmio_addr;
u16 status, ackstat;
int link_changed = 0; /* avoid bogus "uninit" warning */
int handled = 0;
@ -2241,7 +2221,7 @@ static void rtl8139_poll_controller(struct net_device *dev)
static int rtl8139_close (struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
void __iomem *ioaddr = tp->mmio_addr;
int ret = 0;
unsigned long flags;
@ -2304,7 +2284,7 @@ static int rtl8139_close (struct net_device *dev)
static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct rtl8139_private *np = netdev_priv(dev);
void *ioaddr = np->mmio_addr;
void __iomem *ioaddr = np->mmio_addr;
spin_lock_irq(&np->lock);
if (rtl_chip_info[np->chipset].flags & HasLWake) {
@ -2338,7 +2318,7 @@ static void rtl8139_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
{
struct rtl8139_private *np = netdev_priv(dev);
void *ioaddr = np->mmio_addr;
void __iomem *ioaddr = np->mmio_addr;
u32 support;
u8 cfg3, cfg5;
@ -2506,7 +2486,7 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
void __iomem *ioaddr = tp->mmio_addr;
unsigned long flags;
if (netif_running(dev)) {
@ -2525,7 +2505,7 @@ static struct net_device_stats *rtl8139_get_stats (struct net_device *dev)
static void __set_rx_mode (struct net_device *dev)
{
struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
void __iomem *ioaddr = tp->mmio_addr;
u32 mc_filter[2]; /* Multicast hash filter */
int i, rx_mode;
u32 tmp;
@ -2586,7 +2566,7 @@ static int rtl8139_suspend (struct pci_dev *pdev, pm_message_t state)
{
struct net_device *dev = pci_get_drvdata (pdev);
struct rtl8139_private *tp = netdev_priv(dev);
void *ioaddr = tp->mmio_addr;
void __iomem *ioaddr = tp->mmio_addr;
unsigned long flags;
pci_save_state (pdev);

View File

@ -824,6 +824,18 @@ config SMC9194
<file:Documentation/networking/net-modules.txt>. The module
will be called smc9194.
config DM9000
tristate "DM9000 support"
depends on ARM && NET_ETHERNET
select CRC32
select MII
---help---
Support for DM9000 chipset.
To compile this driver as a module, choose M here and read
<file:Documentation/networking/net-modules.txt>. The module will be
called dm9000.
config NET_VENDOR_RACAL
bool "Racal-Interlan (Micom) NI cards"
depends on NET_ETHERNET && ISA
@ -989,21 +1001,6 @@ config EEXPRESS_PRO
<file:Documentation/networking/net-modules.txt>. The module
will be called eepro.
config FMV18X
tristate "FMV-181/182/183/184 support (OBSOLETE)"
depends on NET_ISA && OBSOLETE
---help---
If you have a Fujitsu FMV-181/182/183/184 network (Ethernet) card,
say Y and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
If you use an FMV-183 or FMV-184 and it is not working, you may need
to disable Plug & Play mode of the card.
To compile this driver as a module, choose M here and read
<file:Documentation/networking/net-modules.txt>. The module
will be called fmv18x.
config HPLAN_PLUS
tristate "HP PCLAN+ (27247B and 27252A) support"
depends on NET_ISA
@ -1092,14 +1089,6 @@ config SEEQ8005
<file:Documentation/networking/net-modules.txt>. The module
will be called seeq8005.
config SK_G16
tristate "SK_G16 support (OBSOLETE)"
depends on NET_ISA && OBSOLETE
help
If you have a network (Ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
config SKMC
tristate "SKnet MCA support"
depends on NET_ETHERNET && MCA && BROKEN
@ -1932,6 +1921,18 @@ config R8169_VLAN
If in doubt, say Y.
config SKGE
tristate "New SysKonnect GigaEthernet support (EXPERIMENTAL)"
depends on PCI && EXPERIMENTAL
select CRC32
---help---
This driver support the Marvell Yukon or SysKonnect SK-98xx/SK-95xx
and related Gigabit Ethernet adapters. It is a new smaller driver
driver with better performance and more complete ethtool support.
It does not support the link failover and network management
features that "portable" vendor supplied sk98lin driver does.
config SK98LIN
tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support"
depends on PCI

View File

@ -53,6 +53,7 @@ obj-$(CONFIG_FEALNX) += fealnx.o
obj-$(CONFIG_TIGON3) += tg3.o
obj-$(CONFIG_BNX2) += bnx2.o
obj-$(CONFIG_TC35815) += tc35815.o
obj-$(CONFIG_SKGE) += skge.o
obj-$(CONFIG_SK98LIN) += sk98lin/
obj-$(CONFIG_SKFP) += skfp/
obj-$(CONFIG_VIA_RHINE) += via-rhine.o
@ -74,7 +75,6 @@ obj-$(CONFIG_MAC8390) += mac8390.o 8390.o
obj-$(CONFIG_APNE) += apne.o 8390.o
obj-$(CONFIG_PCMCIA_PCNET) += 8390.o
obj-$(CONFIG_SHAPER) += shaper.o
obj-$(CONFIG_SK_G16) += sk_g16.o
obj-$(CONFIG_HP100) += hp100.o
obj-$(CONFIG_SMC9194) += smc9194.o
obj-$(CONFIG_FEC) += fec.o
@ -122,7 +122,6 @@ obj-$(CONFIG_DEFXX) += defxx.o
obj-$(CONFIG_SGISEEQ) += sgiseeq.o
obj-$(CONFIG_SGI_O2MACE_ETH) += meth.o
obj-$(CONFIG_AT1700) += at1700.o
obj-$(CONFIG_FMV18X) += fmv18x.o
obj-$(CONFIG_EL1) += 3c501.o
obj-$(CONFIG_EL16) += 3c507.o
obj-$(CONFIG_ELMC) += 3c523.o
@ -180,6 +179,7 @@ obj-$(CONFIG_AMD8111_ETH) += amd8111e.o
obj-$(CONFIG_IBMVETH) += ibmveth.o
obj-$(CONFIG_S2IO) += s2io.o
obj-$(CONFIG_SMC91X) += smc91x.o
obj-$(CONFIG_DM9000) += dm9000.o
obj-$(CONFIG_FEC_8XX) += fec_8xx/
obj-$(CONFIG_ARM) += arm/

View File

@ -210,9 +210,6 @@ static struct devprobe2 isa_probes[] __initdata = {
#ifdef CONFIG_AT1700
{at1700_probe, 0},
#endif
#ifdef CONFIG_FMV18X /* Fujitsu FMV-181/182 */
{fmv18x_probe, 0},
#endif
#ifdef CONFIG_ETH16I
{eth16i_probe, 0}, /* ICL EtherTeam 16i/32 */
#endif
@ -243,9 +240,6 @@ static struct devprobe2 isa_probes[] __initdata = {
#ifdef CONFIG_ELPLUS /* 3c505 */
{elplus_probe, 0},
#endif
#ifdef CONFIG_SK_G16
{SK_init, 0},
#endif
#ifdef CONFIG_NI5010
{ni5010_probe, 0},
#endif

View File

@ -68,6 +68,7 @@ struct etherh_priv {
void __iomem *dma_base;
unsigned int id;
void __iomem *ctrl_port;
void __iomem *base;
unsigned char ctrl;
u32 supported;
};
@ -177,7 +178,7 @@ etherh_setif(struct net_device *dev)
switch (etherh_priv(dev)->id) {
case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A:
addr = (void *)dev->base_addr + EN0_RCNTHI;
addr = etherh_priv(dev)->base + EN0_RCNTHI;
switch (dev->if_port) {
case IF_PORT_10BASE2:
@ -218,7 +219,7 @@ etherh_getifstat(struct net_device *dev)
switch (etherh_priv(dev)->id) {
case PROD_I3_ETHERLAN600:
case PROD_I3_ETHERLAN600A:
addr = (void *)dev->base_addr + EN0_RCNTHI;
addr = etherh_priv(dev)->base + EN0_RCNTHI;
switch (dev->if_port) {
case IF_PORT_10BASE2:
stat = 1;
@ -281,7 +282,7 @@ static void
etherh_reset(struct net_device *dev)
{
struct ei_device *ei_local = netdev_priv(dev);
void __iomem *addr = (void *)dev->base_addr;
void __iomem *addr = etherh_priv(dev)->base;
writeb(E8390_NODMA+E8390_PAGE0+E8390_STOP, addr);
@ -327,7 +328,7 @@ etherh_block_output (struct net_device *dev, int count, const unsigned char *buf
ei_local->dmaing = 1;
addr = (void *)dev->base_addr;
addr = etherh_priv(dev)->base;
dma_base = etherh_priv(dev)->dma_base;
count = (count + 1) & ~1;
@ -387,7 +388,7 @@ etherh_block_input (struct net_device *dev, int count, struct sk_buff *skb, int
ei_local->dmaing = 1;
addr = (void *)dev->base_addr;
addr = etherh_priv(dev)->base;
dma_base = etherh_priv(dev)->dma_base;
buf = skb->data;
@ -427,7 +428,7 @@ etherh_get_header (struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_p
ei_local->dmaing = 1;
addr = (void *)dev->base_addr;
addr = etherh_priv(dev)->base;
dma_base = etherh_priv(dev)->dma_base;
writeb (E8390_NODMA | E8390_PAGE0 | E8390_START, addr + E8390_CMD);
@ -696,7 +697,8 @@ etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
eh->ctrl_port = eh->ioc_fast;
}
dev->base_addr = (unsigned long)eh->memc + data->ns8390_offset;
eh->base = eh->memc + data->ns8390_offset;
dev->base_addr = (unsigned long)eh->base;
eh->dma_base = eh->memc + data->dataport_offset;
eh->ctrl_port += data->ctrlport_offset;

View File

@ -1681,10 +1681,6 @@ static int au1000_init(struct net_device *dev)
control |= MAC_FULL_DUPLEX;
}
/* fix for startup without cable */
if (!link)
dev->flags &= ~IFF_RUNNING;
aup->mac->control = control;
aup->mac->vlan1_tag = 0x8100; /* activate vlan support */
au_sync();
@ -1709,16 +1705,14 @@ static void au1000_timer(unsigned long data)
if_port = dev->if_port;
if (aup->phy_ops->phy_status(dev, aup->phy_addr, &link, &speed) == 0) {
if (link) {
if (!(dev->flags & IFF_RUNNING)) {
if (!netif_carrier_ok(dev)) {
netif_carrier_on(dev);
dev->flags |= IFF_RUNNING;
printk(KERN_INFO "%s: link up\n", dev->name);
}
}
else {
if (dev->flags & IFF_RUNNING) {
if (netif_carrier_ok(dev)) {
netif_carrier_off(dev);
dev->flags &= ~IFF_RUNNING;
dev->if_port = 0;
printk(KERN_INFO "%s: link down\n", dev->name);
}

View File

@ -1412,7 +1412,6 @@ static int bmac_open(struct net_device *dev)
bp->opened = 1;
bmac_reset_and_enable(dev);
enable_irq(dev->irq);
dev->flags |= IFF_RUNNING;
return 0;
}
@ -1425,7 +1424,6 @@ static int bmac_close(struct net_device *dev)
int i;
bp->sleeping = 1;
dev->flags &= ~(IFF_UP | IFF_RUNNING);
/* disable rx and tx */
config = bmread(dev, RXCFG);

1219
drivers/net/dm9000.c Normal file

File diff suppressed because it is too large Load Diff

135
drivers/net/dm9000.h Normal file
View File

@ -0,0 +1,135 @@
/*
* dm9000 Ethernet
*/
#ifndef _DM9000X_H_
#define _DM9000X_H_
#define DM9000_ID 0x90000A46
/* although the registers are 16 bit, they are 32-bit aligned.
*/
#define DM9000_NCR 0x00
#define DM9000_NSR 0x01
#define DM9000_TCR 0x02
#define DM9000_TSR1 0x03
#define DM9000_TSR2 0x04
#define DM9000_RCR 0x05
#define DM9000_RSR 0x06
#define DM9000_ROCR 0x07
#define DM9000_BPTR 0x08
#define DM9000_FCTR 0x09
#define DM9000_FCR 0x0A
#define DM9000_EPCR 0x0B
#define DM9000_EPAR 0x0C
#define DM9000_EPDRL 0x0D
#define DM9000_EPDRH 0x0E
#define DM9000_WCR 0x0F
#define DM9000_PAR 0x10
#define DM9000_MAR 0x16
#define DM9000_GPCR 0x1e
#define DM9000_GPR 0x1f
#define DM9000_TRPAL 0x22
#define DM9000_TRPAH 0x23
#define DM9000_RWPAL 0x24
#define DM9000_RWPAH 0x25
#define DM9000_VIDL 0x28
#define DM9000_VIDH 0x29
#define DM9000_PIDL 0x2A
#define DM9000_PIDH 0x2B
#define DM9000_CHIPR 0x2C
#define DM9000_SMCR 0x2F
#define DM9000_MRCMDX 0xF0
#define DM9000_MRCMD 0xF2
#define DM9000_MRRL 0xF4
#define DM9000_MRRH 0xF5
#define DM9000_MWCMDX 0xF6
#define DM9000_MWCMD 0xF8
#define DM9000_MWRL 0xFA
#define DM9000_MWRH 0xFB
#define DM9000_TXPLL 0xFC
#define DM9000_TXPLH 0xFD
#define DM9000_ISR 0xFE
#define DM9000_IMR 0xFF
#define NCR_EXT_PHY (1<<7)
#define NCR_WAKEEN (1<<6)
#define NCR_FCOL (1<<4)
#define NCR_FDX (1<<3)
#define NCR_LBK (3<<1)
#define NCR_RST (1<<0)
#define NSR_SPEED (1<<7)
#define NSR_LINKST (1<<6)
#define NSR_WAKEST (1<<5)
#define NSR_TX2END (1<<3)
#define NSR_TX1END (1<<2)
#define NSR_RXOV (1<<1)
#define TCR_TJDIS (1<<6)
#define TCR_EXCECM (1<<5)
#define TCR_PAD_DIS2 (1<<4)
#define TCR_CRC_DIS2 (1<<3)
#define TCR_PAD_DIS1 (1<<2)
#define TCR_CRC_DIS1 (1<<1)
#define TCR_TXREQ (1<<0)
#define TSR_TJTO (1<<7)
#define TSR_LC (1<<6)
#define TSR_NC (1<<5)
#define TSR_LCOL (1<<4)
#define TSR_COL (1<<3)
#define TSR_EC (1<<2)
#define RCR_WTDIS (1<<6)
#define RCR_DIS_LONG (1<<5)
#define RCR_DIS_CRC (1<<4)
#define RCR_ALL (1<<3)
#define RCR_RUNT (1<<2)
#define RCR_PRMSC (1<<1)
#define RCR_RXEN (1<<0)
#define RSR_RF (1<<7)
#define RSR_MF (1<<6)
#define RSR_LCS (1<<5)
#define RSR_RWTO (1<<4)
#define RSR_PLE (1<<3)
#define RSR_AE (1<<2)
#define RSR_CE (1<<1)
#define RSR_FOE (1<<0)
#define FCTR_HWOT(ot) (( ot & 0xf ) << 4 )
#define FCTR_LWOT(ot) ( ot & 0xf )
#define IMR_PAR (1<<7)
#define IMR_ROOM (1<<3)
#define IMR_ROM (1<<2)
#define IMR_PTM (1<<1)
#define IMR_PRM (1<<0)
#define ISR_ROOS (1<<3)
#define ISR_ROS (1<<2)
#define ISR_PTS (1<<1)
#define ISR_PRS (1<<0)
#define ISR_CLR_STATUS (ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS)
#define EPCR_REEP (1<<5)
#define EPCR_WEP (1<<4)
#define EPCR_EPOS (1<<3)
#define EPCR_ERPRR (1<<2)
#define EPCR_ERPRW (1<<1)
#define EPCR_ERRE (1<<0)
#define GPCR_GEP_CNTL (1<<0)
#define DM9000_PKT_RDY 0x01 /* Packet ready to receive */
#define DM9000_PKT_MAX 1536 /* Received packet max size */
#endif /* _DM9000X_H_ */

View File

@ -1,689 +0,0 @@
/* fmv18x.c: A network device driver for the Fujitsu FMV-181/182/183/184.
Original: at1700.c (1993-94 by Donald Becker).
Copyright 1993 United States Government as represented by the
Director, National Security Agency.
The author may be reached as becker@scyld.com, or C/O
Scyld Computing Corporation
410 Severn Ave., Suite 210
Annapolis MD 21403
Modified by Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)
Copyright 1994 Fujitsu Laboratories Ltd.
Special thanks to:
Masayoshi UTAKA (utaka@ace.yk.fujitsu.co.jp)
for testing this driver.
H. NEGISHI (agy, negishi@sun45.psd.cs.fujitsu.co.jp)
for suggestion of some program modification.
Masahiro SEKIGUCHI <seki@sysrap.cs.fujitsu.co.jp>
for suggestion of some program modification.
Kazutoshi MORIOKA (morioka@aurora.oaks.cs.fujitsu.co.jp)
for testing this driver.
This software may be used and distributed according to the terms
of the GNU General Public License, incorporated herein by reference.
This is a device driver for the Fujitsu FMV-181/182/183/184, which
is a straight-forward Fujitsu MB86965 implementation.
Sources:
at1700.c
The Fujitsu MB86965 datasheet.
The Fujitsu FMV-181/182 user's guide
*/
static const char version[] =
"fmv18x.c:v2.2.0 09/24/98 Yutaka TAMIYA (tamy@flab.fujitsu.co.jp)\n";
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/spinlock.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <linux/delay.h>
#include <linux/bitops.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/dma.h>
#define DRV_NAME "fmv18x"
static unsigned fmv18x_probe_list[] __initdata = {
0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x300, 0x340, 0
};
/* use 0 for production, 1 for verification, >2 for debug */
#ifndef NET_DEBUG
#define NET_DEBUG 1
#endif
static unsigned int net_debug = NET_DEBUG;
typedef unsigned char uchar;
/* Information that need to be kept for each board. */
struct net_local {
struct net_device_stats stats;
long open_time; /* Useless example local info. */
uint tx_started:1; /* Number of packet on the Tx queue. */
uint tx_queue_ready:1; /* Tx queue is ready to be sent. */
uint rx_started:1; /* Packets are Rxing. */
uchar tx_queue; /* Number of packet on the Tx queue. */
ushort tx_queue_len; /* Current length of the Tx queue. */
spinlock_t lock;
};
/* Offsets from the base address. */
#define STATUS 0
#define TX_STATUS 0
#define RX_STATUS 1
#define TX_INTR 2 /* Bit-mapped interrupt enable registers. */
#define RX_INTR 3
#define TX_MODE 4
#define RX_MODE 5
#define CONFIG_0 6 /* Misc. configuration settings. */
#define CONFIG_1 7
/* Run-time register bank 2 definitions. */
#define DATAPORT 8 /* Word-wide DMA or programmed-I/O dataport. */
#define TX_START 10
#define COL16CNTL 11 /* Controll Reg for 16 collisions */
#define MODE13 13
/* Fujitsu FMV-18x Card Configuration */
#define FJ_STATUS0 0x10
#define FJ_STATUS1 0x11
#define FJ_CONFIG0 0x12
#define FJ_CONFIG1 0x13
#define FJ_MACADDR 0x14 /* 0x14 - 0x19 */
#define FJ_BUFCNTL 0x1A
#define FJ_BUFDATA 0x1C
#define FMV18X_IO_EXTENT 32
/* Index to functions, as function prototypes. */
static int fmv18x_probe1(struct net_device *dev, short ioaddr);
static int net_open(struct net_device *dev);
static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static void net_rx(struct net_device *dev);
static void net_timeout(struct net_device *dev);
static int net_close(struct net_device *dev);
static struct net_device_stats *net_get_stats(struct net_device *dev);
static void set_multicast_list(struct net_device *dev);
/* Check for a network adaptor of this type, and return '0' iff one exists.
If dev->base_addr == 0, probe all likely locations.
If dev->base_addr == 1, always return failure.
If dev->base_addr == 2, allocate space for the device and return success
(detachable devices only).
*/
static int io = 0x220;
static int irq;
struct net_device * __init fmv18x_probe(int unit)
{
struct net_device *dev = alloc_etherdev(sizeof(struct net_local));
unsigned *port;
int err = 0;
if (!dev)
return ERR_PTR(-ENODEV);
if (unit >= 0) {
sprintf(dev->name, "eth%d", unit);
netdev_boot_setup_check(dev);
io = dev->base_addr;
irq = dev->irq;
}
SET_MODULE_OWNER(dev);
if (io > 0x1ff) { /* Check a single specified location. */
err = fmv18x_probe1(dev, io);
} else if (io != 0) { /* Don't probe at all. */
err = -ENXIO;
} else {
for (port = fmv18x_probe_list; *port; port++)
if (fmv18x_probe1(dev, *port) == 0)
break;
if (!*port)
err = -ENODEV;
}
if (err)
goto out;
err = register_netdev(dev);
if (err)
goto out1;
return dev;
out1:
free_irq(dev->irq, dev);
release_region(dev->base_addr, FMV18X_IO_EXTENT);
out:
free_netdev(dev);
return ERR_PTR(err);
}
/* The Fujitsu datasheet suggests that the NIC be probed for by checking its
"signature", the default bit pattern after a reset. This *doesn't* work --
there is no way to reset the bus interface without a complete power-cycle!
It turns out that ATI came to the same conclusion I did: the only thing
that can be done is checking a few bits and then diving right into MAC
address check. */
static int __init fmv18x_probe1(struct net_device *dev, short ioaddr)
{
char irqmap[4] = {3, 7, 10, 15};
char irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
unsigned int i, retval;
struct net_local *lp;
/* Resetting the chip doesn't reset the ISA interface, so don't bother.
That means we have to be careful with the register values we probe for.
*/
if (!request_region(ioaddr, FMV18X_IO_EXTENT, DRV_NAME))
return -EBUSY;
dev->irq = irq;
dev->base_addr = ioaddr;
/* Check I/O address configuration and Fujitsu vendor code */
if (inb(ioaddr+FJ_MACADDR ) != 0x00
|| inb(ioaddr+FJ_MACADDR+1) != 0x00
|| inb(ioaddr+FJ_MACADDR+2) != 0x0e) {
retval = -ENODEV;
goto out;
}
/* Check PnP mode for FMV-183/184/183A/184A. */
/* This PnP routine is very poor. IO and IRQ should be known. */
if (inb(ioaddr + FJ_STATUS1) & 0x20) {
for (i = 0; i < 8; i++) {
if (dev->irq == irqmap_pnp[i])
break;
}
if (i == 8) {
retval = -ENODEV;
goto out;
}
} else {
if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr)
return -ENODEV;
dev->irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03];
}
/* Snarf the interrupt vector now. */
retval = request_irq(dev->irq, &net_interrupt, 0, DRV_NAME, dev);
if (retval) {
printk ("FMV-18x found at %#3x, but it's unusable due to a conflict on"
"IRQ %d.\n", ioaddr, dev->irq);
goto out;
}
printk("%s: FMV-18x found at %#3x, IRQ %d, address ", dev->name,
ioaddr, dev->irq);
for(i = 0; i < 6; i++) {
unsigned char val = inb(ioaddr + FJ_MACADDR + i);
printk("%02x", val);
dev->dev_addr[i] = val;
}
/* "FJ_STATUS0" 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
rather than 150 ohm shielded twisted pair compensation.
0x0000 == auto-sense the interface
0x0800 == use TP interface
0x1800 == use coax interface
*/
{
const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2/5"};
ushort setup_value = inb(ioaddr + FJ_STATUS0);
switch( setup_value & 0x07 ){
case 0x01 /* 10base5 */:
case 0x02 /* 10base2 */: dev->if_port = 0x18; break;
case 0x04 /* 10baseT */: dev->if_port = 0x08; break;
default /* auto-sense*/: dev->if_port = 0x00; break;
}
printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]);
}
/* Initialize LAN Controller and LAN Card */
outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */
outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */
outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure (TAMIYA) */
/* wait for a while */
udelay(200);
/* Set the station address in bank zero. */
outb(0x00, ioaddr + CONFIG_1);
for (i = 0; i < 6; i++)
outb(dev->dev_addr[i], ioaddr + 8 + i);
/* Switch to bank 1 and set the multicast table to accept none. */
outb(0x04, ioaddr + CONFIG_1);
for (i = 0; i < 8; i++)
outb(0x00, ioaddr + 8 + i);
/* Switch to bank 2 and lock our I/O address. */
outb(0x08, ioaddr + CONFIG_1);
outb(dev->if_port, ioaddr + MODE13);
outb(0x00, ioaddr + COL16CNTL);
if (net_debug)
printk(version);
/* Initialize the device structure. */
dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
if (!dev->priv) {
retval = -ENOMEM;
goto out_irq;
}
memset(dev->priv, 0, sizeof(struct net_local));
lp = dev->priv;
spin_lock_init(&lp->lock);
dev->open = net_open;
dev->stop = net_close;
dev->hard_start_xmit = net_send_packet;
dev->tx_timeout = net_timeout;
dev->watchdog_timeo = HZ/10;
dev->get_stats = net_get_stats;
dev->set_multicast_list = set_multicast_list;
return 0;
out_irq:
free_irq(dev->irq, dev);
out:
release_region(ioaddr, FMV18X_IO_EXTENT);
return retval;
}
static int net_open(struct net_device *dev)
{
struct net_local *lp = dev->priv;
int ioaddr = dev->base_addr;
/* Set the configuration register 0 to 32K 100ns. byte-wide memory,
16 bit bus access, and two 4K Tx, enable the Rx and Tx. */
outb(0x5a, ioaddr + CONFIG_0);
/* Powerup and switch to register bank 2 for the run-time registers. */
outb(0xe8, ioaddr + CONFIG_1);
lp->tx_started = 0;
lp->tx_queue_ready = 1;
lp->rx_started = 0;
lp->tx_queue = 0;
lp->tx_queue_len = 0;
/* Clear Tx and Rx Status */
outb(0xff, ioaddr + TX_STATUS);
outb(0xff, ioaddr + RX_STATUS);
lp->open_time = jiffies;
netif_start_queue(dev);
/* Enable the IRQ of the LAN Card */
outb(0x80, ioaddr + FJ_CONFIG1);
/* Enable both Tx and Rx interrupts */
outw(0x8182, ioaddr+TX_INTR);
return 0;
}
static void net_timeout(struct net_device *dev)
{
struct net_local *lp = dev->priv;
int ioaddr = dev->base_addr;
unsigned long flags;
printk(KERN_WARNING "%s: transmit timed out with status %04x, %s?\n", dev->name,
htons(inw(ioaddr + TX_STATUS)),
inb(ioaddr + TX_STATUS) & 0x80
? "IRQ conflict" : "network cable problem");
printk(KERN_WARNING "%s: timeout registers: %04x %04x %04x %04x %04x %04x %04x %04x.\n",
dev->name, htons(inw(ioaddr + 0)),
htons(inw(ioaddr + 2)), htons(inw(ioaddr + 4)),
htons(inw(ioaddr + 6)), htons(inw(ioaddr + 8)),
htons(inw(ioaddr +10)), htons(inw(ioaddr +12)),
htons(inw(ioaddr +14)));
printk(KERN_WARNING "eth card: %04x %04x\n",
htons(inw(ioaddr+FJ_STATUS0)),
htons(inw(ioaddr+FJ_CONFIG0)));
lp->stats.tx_errors++;
/* ToDo: We should try to restart the adaptor... */
spin_lock_irqsave(&lp->lock, flags);
/* Initialize LAN Controller and LAN Card */
outb(0xda, ioaddr + CONFIG_0); /* Initialize LAN Controller */
outb(0x00, ioaddr + CONFIG_1); /* Stand by mode */
outb(0x00, ioaddr + FJ_CONFIG1); /* Disable IRQ of LAN Card */
outb(0x00, ioaddr + FJ_BUFCNTL); /* Reset ? I'm not sure */
net_open(dev);
spin_unlock_irqrestore(&lp->lock, flags);
netif_wake_queue(dev);
}
static int net_send_packet(struct sk_buff *skb, struct net_device *dev)
{
struct net_local *lp = dev->priv;
int ioaddr = dev->base_addr;
short length = skb->len;
unsigned char *buf;
unsigned long flags;
/* Block a transmit from overlapping. */
if (length > ETH_FRAME_LEN) {
if (net_debug)
printk("%s: Attempting to send a large packet (%d bytes).\n",
dev->name, length);
return 1;
}
if (length < ETH_ZLEN) {
skb = skb_padto(skb, ETH_ZLEN);
if (skb == NULL)
return 0;
length = ETH_ZLEN;
}
buf = skb->data;
if (net_debug > 4)
printk("%s: Transmitting a packet of length %lu.\n", dev->name,
(unsigned long)skb->len);
/* We may not start transmitting unless we finish transferring
a packet into the Tx queue. During executing the following
codes we possibly catch a Tx interrupt. Thus we flag off
tx_queue_ready, so that we prevent the interrupt routine
(net_interrupt) to start transmitting. */
spin_lock_irqsave(&lp->lock, flags);
lp->tx_queue_ready = 0;
{
outw(length, ioaddr + DATAPORT);
outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
lp->tx_queue++;
lp->tx_queue_len += length + 2;
}
lp->tx_queue_ready = 1;
spin_unlock_irqrestore(&lp->lock, flags);
if (lp->tx_started == 0) {
/* If the Tx is idle, always trigger a transmit. */
outb(0x80 | lp->tx_queue, ioaddr + TX_START);
lp->tx_queue = 0;
lp->tx_queue_len = 0;
dev->trans_start = jiffies;
lp->tx_started = 1;
} else if (lp->tx_queue_len >= 4096 - 1502) /* No room for a packet */
netif_stop_queue(dev);
dev_kfree_skb(skb);
return 0;
}
/* The typical workload of the driver:
Handle the network interface interrupts. */
static irqreturn_t
net_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
struct net_device *dev = dev_id;
struct net_local *lp;
int ioaddr, status;
ioaddr = dev->base_addr;
lp = dev->priv;
status = inw(ioaddr + TX_STATUS);
outw(status, ioaddr + TX_STATUS);
if (net_debug > 4)
printk("%s: Interrupt with status %04x.\n", dev->name, status);
if (lp->rx_started == 0 &&
(status & 0xff00 || (inb(ioaddr + RX_MODE) & 0x40) == 0)) {
/* Got a packet(s).
We cannot execute net_rx more than once at the same time for
the same device. During executing net_rx, we possibly catch a
Tx interrupt. Thus we flag on rx_started, so that we prevent
the interrupt routine (net_interrupt) to dive into net_rx
again. */
lp->rx_started = 1;
outb(0x00, ioaddr + RX_INTR); /* Disable RX intr. */
net_rx(dev);
outb(0x81, ioaddr + RX_INTR); /* Enable RX intr. */
lp->rx_started = 0;
}
if (status & 0x00ff) {
if (status & 0x02) {
/* More than 16 collisions occurred */
if (net_debug > 4)
printk("%s: 16 Collision occur during Txing.\n", dev->name);
/* Cancel sending a packet. */
outb(0x03, ioaddr + COL16CNTL);
lp->stats.collisions++;
}
if (status & 0x82) {
spin_lock(&lp->lock);
lp->stats.tx_packets++;
if (lp->tx_queue && lp->tx_queue_ready) {
outb(0x80 | lp->tx_queue, ioaddr + TX_START);
lp->tx_queue = 0;
lp->tx_queue_len = 0;
dev->trans_start = jiffies;
netif_wake_queue(dev); /* Inform upper layers. */
} else {
lp->tx_started = 0;
netif_wake_queue(dev); /* Inform upper layers. */
}
spin_unlock(&lp->lock);
}
}
return IRQ_RETVAL(status);
}
/* We have a good packet(s), get it/them out of the buffers. */
static void net_rx(struct net_device *dev)
{
struct net_local *lp = dev->priv;
int ioaddr = dev->base_addr;
int boguscount = 5;
while ((inb(ioaddr + RX_MODE) & 0x40) == 0) {
/* Clear PKT_RDY bit: by agy 19940922 */
/* outb(0x80, ioaddr + RX_STATUS); */
ushort status = inw(ioaddr + DATAPORT);
if (net_debug > 4)
printk("%s: Rxing packet mode %02x status %04x.\n",
dev->name, inb(ioaddr + RX_MODE), status);
#ifndef final_version
if (status == 0) {
outb(0x05, ioaddr + 14);
break;
}
#endif
if ((status & 0xF0) != 0x20) { /* There was an error. */
lp->stats.rx_errors++;
if (status & 0x08) lp->stats.rx_length_errors++;
if (status & 0x04) lp->stats.rx_frame_errors++;
if (status & 0x02) lp->stats.rx_crc_errors++;
if (status & 0x01) lp->stats.rx_over_errors++;
} else {
ushort pkt_len = inw(ioaddr + DATAPORT);
/* Malloc up new buffer. */
struct sk_buff *skb;
if (pkt_len > 1550) {
printk("%s: The FMV-18x claimed a very large packet, size %d.\n",
dev->name, pkt_len);
outb(0x05, ioaddr + 14);
lp->stats.rx_errors++;
break;
}
skb = dev_alloc_skb(pkt_len+3);
if (skb == NULL) {
printk("%s: Memory squeeze, dropping packet (len %d).\n",
dev->name, pkt_len);
outb(0x05, ioaddr + 14);
lp->stats.rx_dropped++;
break;
}
skb->dev = dev;
skb_reserve(skb,2);
insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1);
if (net_debug > 5) {
int i;
printk("%s: Rxed packet of length %d: ", dev->name, pkt_len);
for (i = 0; i < 14; i++)
printk(" %02x", skb->data[i]);
printk(".\n");
}
skb->protocol=eth_type_trans(skb, dev);
netif_rx(skb);
dev->last_rx = jiffies;
lp->stats.rx_packets++;
lp->stats.rx_bytes += pkt_len;
}
if (--boguscount <= 0)
break;
}
/* If any worth-while packets have been received, dev_rint()
has done a mark_bh(NET_BH) for us and will work on them
when we get to the bottom-half routine. */
{
int i;
for (i = 0; i < 20; i++) {
if ((inb(ioaddr + RX_MODE) & 0x40) == 0x40)
break;
(void)inw(ioaddr + DATAPORT); /* dummy status read */
outb(0x05, ioaddr + 14);
}
if (net_debug > 5 && i > 0)
printk("%s: Exint Rx packet with mode %02x after %d ticks.\n",
dev->name, inb(ioaddr + RX_MODE), i);
}
return;
}
/* The inverse routine to net_open(). */
static int net_close(struct net_device *dev)
{
int ioaddr = dev->base_addr;
((struct net_local *)dev->priv)->open_time = 0;
netif_stop_queue(dev);
/* Set configuration register 0 to disable Tx and Rx. */
outb(0xda, ioaddr + CONFIG_0);
/* Update the statistics -- ToDo. */
/* Power-down the chip. Green, green, green! */
outb(0x00, ioaddr + CONFIG_1);
/* Set the ethernet adaptor disable IRQ */
outb(0x00, ioaddr + FJ_CONFIG1);
return 0;
}
/* Get the current statistics. This may be called with the card open or
closed. */
static struct net_device_stats *net_get_stats(struct net_device *dev)
{
struct net_local *lp = dev->priv;
return &lp->stats;
}
/* Set or clear the multicast filter for this adaptor.
num_addrs == -1 Promiscuous mode, receive all packets
num_addrs == 0 Normal mode, clear multicast list
num_addrs > 0 Multicast mode, receive normal and MC packets, and do
best-effort filtering.
*/
static void set_multicast_list(struct net_device *dev)
{
short ioaddr = dev->base_addr;
if (dev->mc_count || dev->flags&(IFF_PROMISC|IFF_ALLMULTI))
{
/*
* We must make the kernel realise we had to move
* into promisc mode or we start all out war on
* the cable. - AC
*/
dev->flags|=IFF_PROMISC;
outb(3, ioaddr + RX_MODE); /* Enable promiscuous mode */
}
else
outb(2, ioaddr + RX_MODE); /* Disable promiscuous, use normal mode */
}
#ifdef MODULE
static struct net_device *dev_fmv18x;
MODULE_PARM(io, "i");
MODULE_PARM(irq, "i");
MODULE_PARM(net_debug, "i");
MODULE_PARM_DESC(io, "FMV-18X I/O address");
MODULE_PARM_DESC(irq, "FMV-18X IRQ number");
MODULE_PARM_DESC(net_debug, "FMV-18X debug level (0-1,5-6)");
MODULE_LICENSE("GPL");
int init_module(void)
{
if (io == 0)
printk("fmv18x: You should not use auto-probing with insmod!\n");
dev_fmv18x = fmv18x_probe(-1);
if (IS_ERR(dev_fmv18x))
return PTR_ERR(dev_fmv18x);
return 0;
}
void
cleanup_module(void)
{
unregister_netdev(dev_fmv18x);
free_irq(dev_fmv18x->irq, dev_fmv18x);
release_region(dev_fmv18x->base_addr, FMV18X_IO_EXTENT);
free_netdev(dev_fmv18x);
}
#endif /* MODULE */
/*
* Local variables:
* compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c fmv18x.c"
* version-control: t
* kept-new-versions: 5
* tab-width: 4
* c-indent-level: 4
* End:
*/

View File

@ -1537,20 +1537,20 @@ static void shmem_get_8390_hdr(struct net_device *dev,
static void shmem_block_input(struct net_device *dev, int count,
struct sk_buff *skb, int ring_offset)
{
void __iomem *xfer_start = ei_status.mem + (TX_PAGES<<8)
+ ring_offset
void __iomem *base = ei_status.mem;
unsigned long offset = (TX_PAGES<<8) + ring_offset
- (ei_status.rx_start_page << 8);
char *buf = skb->data;
if (xfer_start + count > (void __iomem *)ei_status.rmem_end) {
if (offset + count > ei_status.priv) {
/* We must wrap the input move. */
int semi_count = (void __iomem *)ei_status.rmem_end - xfer_start;
copyin(buf, xfer_start, semi_count);
int semi_count = ei_status.priv - offset;
copyin(buf, base + offset, semi_count);
buf += semi_count;
xfer_start = ei_status.mem + (TX_PAGES<<8);
offset = TX_PAGES<<8;
count -= semi_count;
}
copyin(buf, xfer_start, count);
copyin(buf, base + offset, count);
}
/*====================================================================*/
@ -1611,8 +1611,9 @@ static int setup_shmem_window(dev_link_t *link, int start_pg,
}
ei_status.mem = info->base + offset;
ei_status.priv = req.Size;
dev->mem_start = (u_long)ei_status.mem;
dev->mem_end = ei_status.rmem_end = (u_long)info->base + req.Size;
dev->mem_end = dev->mem_start + req.Size;
ei_status.tx_start_page = start_pg;
ei_status.rx_start_page = start_pg + TX_PAGES;

View File

@ -1217,36 +1217,43 @@ ppp_push(struct ppp *ppp)
*/
static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
{
int nch, len, fragsize;
int len, fragsize;
int i, bits, hdrlen, mtu;
int flen, fnb;
int flen;
int navail, nfree;
int nbigger;
unsigned char *p, *q;
struct list_head *list;
struct channel *pch;
struct sk_buff *frag;
struct ppp_channel *chan;
nch = 0;
nfree = 0; /* # channels which have no packet already queued */
navail = 0; /* total # of usable channels (not deregistered) */
hdrlen = (ppp->flags & SC_MP_XSHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
i = 0;
list = &ppp->channels;
while ((list = list->next) != &ppp->channels) {
pch = list_entry(list, struct channel, clist);
nch += pch->avail = (skb_queue_len(&pch->file.xq) == 0);
/*
* If a channel hasn't had a fragment yet, it has to get
* one before we send any fragments on later channels.
* If it can't take a fragment now, don't give any
* to subsequent channels.
*/
if (!pch->had_frag && !pch->avail) {
while ((list = list->next) != &ppp->channels) {
pch = list_entry(list, struct channel, clist);
pch->avail = 0;
navail += pch->avail = (pch->chan != NULL);
if (pch->avail) {
if (skb_queue_len(&pch->file.xq) == 0
|| !pch->had_frag) {
pch->avail = 2;
++nfree;
}
break;
if (!pch->had_frag && i < ppp->nxchan)
ppp->nxchan = i;
}
++i;
}
if (nch == 0)
/*
* Don't start sending this packet unless at least half of
* the channels are free. This gives much better TCP
* performance if we have a lot of channels.
*/
if (nfree == 0 || nfree < navail / 2)
return 0; /* can't take now, leave it in xmit_pending */
/* Do protocol field compression (XXX this should be optional) */
@ -1257,14 +1264,19 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
--len;
}
/* decide on fragment size */
/*
* Decide on fragment size.
* We create a fragment for each free channel regardless of
* how small they are (i.e. even 0 length) in order to minimize
* the time that it will take to detect when a channel drops
* a fragment.
*/
fragsize = len;
if (nch > 1) {
int maxch = ROUNDUP(len, MIN_FRAG_SIZE);
if (nch > maxch)
nch = maxch;
fragsize = ROUNDUP(fragsize, nch);
}
if (nfree > 1)
fragsize = ROUNDUP(fragsize, nfree);
/* nbigger channels get fragsize bytes, the rest get fragsize-1,
except if nbigger==0, then they all get fragsize. */
nbigger = len % nfree;
/* skip to the channel after the one we last used
and start at that one */
@ -1278,7 +1290,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
/* create a fragment for each channel */
bits = B;
do {
while (nfree > 0 || len > 0) {
list = list->next;
if (list == &ppp->channels) {
i = 0;
@ -1289,61 +1301,92 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb)
if (!pch->avail)
continue;
/*
* Skip this channel if it has a fragment pending already and
* we haven't given a fragment to all of the free channels.
*/
if (pch->avail == 1) {
if (nfree > 0)
continue;
} else {
--nfree;
pch->avail = 1;
}
/* check the channel's mtu and whether it is still attached. */
spin_lock_bh(&pch->downl);
if (pch->chan == 0 || (mtu = pch->chan->mtu) < hdrlen) {
/* can't use this channel */
if (pch->chan == NULL) {
/* can't use this channel, it's being deregistered */
spin_unlock_bh(&pch->downl);
pch->avail = 0;
if (--nch == 0)
if (--navail == 0)
break;
continue;
}
/*
* We have to create multiple fragments for this channel
* if fragsize is greater than the channel's mtu.
* Create a fragment for this channel of
* min(max(mtu+2-hdrlen, 4), fragsize, len) bytes.
* If mtu+2-hdrlen < 4, that is a ridiculously small
* MTU, so we use mtu = 2 + hdrlen.
*/
if (fragsize > len)
fragsize = len;
for (flen = fragsize; flen > 0; flen -= fnb) {
fnb = flen;
if (fnb > mtu + 2 - hdrlen)
fnb = mtu + 2 - hdrlen;
if (fnb >= len)
bits |= E;
frag = alloc_skb(fnb + hdrlen, GFP_ATOMIC);
if (frag == 0)
goto noskb;
q = skb_put(frag, fnb + hdrlen);
/* make the MP header */
q[0] = PPP_MP >> 8;
q[1] = PPP_MP;
if (ppp->flags & SC_MP_XSHORTSEQ) {
q[2] = bits + ((ppp->nxseq >> 8) & 0xf);
q[3] = ppp->nxseq;
} else {
q[2] = bits;
q[3] = ppp->nxseq >> 16;
q[4] = ppp->nxseq >> 8;
q[5] = ppp->nxseq;
}
flen = fragsize;
mtu = pch->chan->mtu + 2 - hdrlen;
if (mtu < 4)
mtu = 4;
if (flen > mtu)
flen = mtu;
if (flen == len && nfree == 0)
bits |= E;
frag = alloc_skb(flen + hdrlen + (flen == 0), GFP_ATOMIC);
if (frag == 0)
goto noskb;
q = skb_put(frag, flen + hdrlen);
/* copy the data in */
memcpy(q + hdrlen, p, fnb);
/* try to send it down the channel */
chan = pch->chan;
if (!chan->ops->start_xmit(chan, frag))
skb_queue_tail(&pch->file.xq, frag);
pch->had_frag = 1;
p += fnb;
len -= fnb;
++ppp->nxseq;
bits = 0;
/* make the MP header */
q[0] = PPP_MP >> 8;
q[1] = PPP_MP;
if (ppp->flags & SC_MP_XSHORTSEQ) {
q[2] = bits + ((ppp->nxseq >> 8) & 0xf);
q[3] = ppp->nxseq;
} else {
q[2] = bits;
q[3] = ppp->nxseq >> 16;
q[4] = ppp->nxseq >> 8;
q[5] = ppp->nxseq;
}
/*
* Copy the data in.
* Unfortunately there is a bug in older versions of
* the Linux PPP multilink reconstruction code where it
* drops 0-length fragments. Therefore we make sure the
* fragment has at least one byte of data. Any bytes
* we add in this situation will end up as padding on the
* end of the reconstructed packet.
*/
if (flen == 0)
*skb_put(frag, 1) = 0;
else
memcpy(q + hdrlen, p, flen);
/* try to send it down the channel */
chan = pch->chan;
if (skb_queue_len(&pch->file.xq)
|| !chan->ops->start_xmit(chan, frag))
skb_queue_tail(&pch->file.xq, frag);
pch->had_frag = 1;
p += flen;
len -= flen;
++ppp->nxseq;
bits = 0;
spin_unlock_bh(&pch->downl);
} while (len > 0);
if (--nbigger == 0 && fragsize > 0)
--fragsize;
}
ppp->nxchan = i;
return 1;
@ -1422,7 +1465,7 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
kfree_skb(skb);
return;
}
proto = PPP_PROTO(skb);
read_lock_bh(&pch->upl);
if (pch->ppp == 0 || proto >= 0xc000 || proto == PPP_CCPFRAG) {
@ -1691,7 +1734,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
struct list_head *l;
int mphdrlen = (ppp->flags & SC_MP_SHORTSEQ)? MPHDRLEN_SSN: MPHDRLEN;
if (!pskb_may_pull(skb, mphdrlen + 1) || ppp->mrru == 0)
if (!pskb_may_pull(skb, mphdrlen) || ppp->mrru == 0)
goto err; /* no good, throw it away */
/* Decode sequence number and begin/end bits */

View File

@ -69,7 +69,13 @@ VERSION 2.2LK <2005/01/25>
#include <asm/io.h>
#include <asm/irq.h>
#define RTL8169_VERSION "2.2LK"
#ifdef CONFIG_R8169_NAPI
#define NAPI_SUFFIX "-NAPI"
#else
#define NAPI_SUFFIX ""
#endif
#define RTL8169_VERSION "2.2LK" NAPI_SUFFIX
#define MODULENAME "r8169"
#define PFX MODULENAME ": "
@ -85,6 +91,10 @@ VERSION 2.2LK <2005/01/25>
#define dprintk(fmt, args...) do {} while (0)
#endif /* RTL8169_DEBUG */
#define R8169_MSG_DEFAULT \
(NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK | NETIF_MSG_IFUP | \
NETIF_MSG_IFDOWN)
#define TX_BUFFS_AVAIL(tp) \
(tp->dirty_tx + NUM_TX_DESC - tp->cur_tx - 1)
@ -174,8 +184,9 @@ const static struct {
#undef _R
static struct pci_device_id rtl8169_pci_tbl[] = {
{0x10ec, 0x8169, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{0x1186, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), },
{ PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), },
{ PCI_DEVICE(0x16ec, 0x0116), },
{0,},
};
@ -183,10 +194,15 @@ MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
static int rx_copybreak = 200;
static int use_dac;
static struct {
u32 msg_enable;
} debug = { -1 };
enum RTL8169_registers {
MAC0 = 0, /* Ethernet hardware address. */
MAR0 = 8, /* Multicast filter. */
CounterAddrLow = 0x10,
CounterAddrHigh = 0x14,
TxDescStartAddrLow = 0x20,
TxDescStartAddrHigh = 0x24,
TxHDescStartAddrLow = 0x28,
@ -328,6 +344,9 @@ enum RTL8169_register_content {
/* _TBICSRBit */
TBILinkOK = 0x02000000,
/* DumpCounterCommand */
CounterDump = 0x8,
};
enum _DescStatusBit {
@ -385,6 +404,7 @@ struct rtl8169_private {
struct pci_dev *pci_dev; /* Index of PCI device */
struct net_device_stats stats; /* statistics of net device */
spinlock_t lock; /* spin lock flag */
u32 msg_enable;
int chipset;
int mac_version;
int phy_version;
@ -418,9 +438,13 @@ struct rtl8169_private {
MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
module_param_array(media, int, &num_media, 0);
MODULE_PARM_DESC(media, "force phy operation. Deprecated by ethtool (8).");
module_param(rx_copybreak, int, 0);
MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames");
module_param(use_dac, int, 0);
MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
module_param_named(debug, debug.msg_enable, int, 0);
MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
MODULE_LICENSE("GPL");
MODULE_VERSION(RTL8169_VERSION);
@ -433,10 +457,10 @@ static void rtl8169_hw_start(struct net_device *dev);
static int rtl8169_close(struct net_device *dev);
static void rtl8169_set_rx_mode(struct net_device *dev);
static void rtl8169_tx_timeout(struct net_device *dev);
static struct net_device_stats *rtl8169_get_stats(struct net_device *netdev);
static struct net_device_stats *rtl8169_get_stats(struct net_device *dev);
static int rtl8169_rx_interrupt(struct net_device *, struct rtl8169_private *,
void __iomem *);
static int rtl8169_change_mtu(struct net_device *netdev, int new_mtu);
static int rtl8169_change_mtu(struct net_device *dev, int new_mtu);
static void rtl8169_down(struct net_device *dev);
#ifdef CONFIG_R8169_NAPI
@ -543,9 +567,13 @@ static void rtl8169_check_link_status(struct net_device *dev,
spin_lock_irqsave(&tp->lock, flags);
if (tp->link_ok(ioaddr)) {
netif_carrier_on(dev);
printk(KERN_INFO PFX "%s: link up\n", dev->name);
} else
if (netif_msg_ifup(tp))
printk(KERN_INFO PFX "%s: link up\n", dev->name);
} else {
if (netif_msg_ifdown(tp))
printk(KERN_INFO PFX "%s: link down\n", dev->name);
netif_carrier_off(dev);
}
spin_unlock_irqrestore(&tp->lock, flags);
}
@ -569,7 +597,7 @@ static void rtl8169_link_option(int idx, u8 *autoneg, u16 *speed, u8 *duplex)
option = ((idx < MAX_UNITS) && (idx >= 0)) ? media[idx] : 0xff;
if ((option != 0xff) && !idx)
if ((option != 0xff) && !idx && netif_msg_drv(&debug))
printk(KERN_WARNING PFX "media option is deprecated.\n");
for (p = link_settings; p->media != 0xff; p++) {
@ -611,9 +639,11 @@ static int rtl8169_set_speed_tbi(struct net_device *dev,
} else if (autoneg == AUTONEG_ENABLE)
RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart);
else {
printk(KERN_WARNING PFX
"%s: incorrect speed setting refused in TBI mode\n",
dev->name);
if (netif_msg_link(tp)) {
printk(KERN_WARNING "%s: "
"incorrect speed setting refused in TBI mode\n",
dev->name);
}
ret = -EOPNOTSUPP;
}
@ -871,12 +901,120 @@ static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
spin_unlock_irqrestore(&tp->lock, flags);
}
static u32 rtl8169_get_msglevel(struct net_device *dev)
{
struct rtl8169_private *tp = netdev_priv(dev);
return tp->msg_enable;
}
static void rtl8169_set_msglevel(struct net_device *dev, u32 value)
{
struct rtl8169_private *tp = netdev_priv(dev);
tp->msg_enable = value;
}
static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
"tx_packets",
"rx_packets",
"tx_errors",
"rx_errors",
"rx_missed",
"align_errors",
"tx_single_collisions",
"tx_multi_collisions",
"unicast",
"broadcast",
"multicast",
"tx_aborted",
"tx_underrun",
};
struct rtl8169_counters {
u64 tx_packets;
u64 rx_packets;
u64 tx_errors;
u32 rx_errors;
u16 rx_missed;
u16 align_errors;
u32 tx_one_collision;
u32 tx_multi_collision;
u64 rx_unicast;
u64 rx_broadcast;
u32 rx_multicast;
u16 tx_aborted;
u16 tx_underun;
};
static int rtl8169_get_stats_count(struct net_device *dev)
{
return ARRAY_SIZE(rtl8169_gstrings);
}
static void rtl8169_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats, u64 *data)
{
struct rtl8169_private *tp = netdev_priv(dev);
void __iomem *ioaddr = tp->mmio_addr;
struct rtl8169_counters *counters;
dma_addr_t paddr;
u32 cmd;
ASSERT_RTNL();
counters = pci_alloc_consistent(tp->pci_dev, sizeof(*counters), &paddr);
if (!counters)
return;
RTL_W32(CounterAddrHigh, (u64)paddr >> 32);
cmd = (u64)paddr & DMA_32BIT_MASK;
RTL_W32(CounterAddrLow, cmd);
RTL_W32(CounterAddrLow, cmd | CounterDump);
while (RTL_R32(CounterAddrLow) & CounterDump) {
if (msleep_interruptible(1))
break;
}
RTL_W32(CounterAddrLow, 0);
RTL_W32(CounterAddrHigh, 0);
data[0] = le64_to_cpu(counters->tx_packets);
data[1] = le64_to_cpu(counters->rx_packets);
data[2] = le64_to_cpu(counters->tx_errors);
data[3] = le32_to_cpu(counters->rx_errors);
data[4] = le16_to_cpu(counters->rx_missed);
data[5] = le16_to_cpu(counters->align_errors);
data[6] = le32_to_cpu(counters->tx_one_collision);
data[7] = le32_to_cpu(counters->tx_multi_collision);
data[8] = le64_to_cpu(counters->rx_unicast);
data[9] = le64_to_cpu(counters->rx_broadcast);
data[10] = le32_to_cpu(counters->rx_multicast);
data[11] = le16_to_cpu(counters->tx_aborted);
data[12] = le16_to_cpu(counters->tx_underun);
pci_free_consistent(tp->pci_dev, sizeof(*counters), counters, paddr);
}
static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
{
switch(stringset) {
case ETH_SS_STATS:
memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings));
break;
}
}
static struct ethtool_ops rtl8169_ethtool_ops = {
.get_drvinfo = rtl8169_get_drvinfo,
.get_regs_len = rtl8169_get_regs_len,
.get_link = ethtool_op_get_link,
.get_settings = rtl8169_get_settings,
.set_settings = rtl8169_set_settings,
.get_msglevel = rtl8169_get_msglevel,
.set_msglevel = rtl8169_set_msglevel,
.get_rx_csum = rtl8169_get_rx_csum,
.set_rx_csum = rtl8169_set_rx_csum,
.get_tx_csum = ethtool_op_get_tx_csum,
@ -886,6 +1024,9 @@ static struct ethtool_ops rtl8169_ethtool_ops = {
.get_tso = ethtool_op_get_tso,
.set_tso = ethtool_op_set_tso,
.get_regs = rtl8169_get_regs,
.get_strings = rtl8169_get_strings,
.get_stats_count = rtl8169_get_stats_count,
.get_ethtool_stats = rtl8169_get_ethtool_stats,
};
static void rtl8169_write_gmii_reg_bit(void __iomem *ioaddr, int reg, int bitnum,
@ -1091,7 +1232,8 @@ static void rtl8169_phy_timer(unsigned long __opaque)
if (tp->link_ok(ioaddr))
goto out_unlock;
printk(KERN_WARNING PFX "%s: PHY reset until link up\n", dev->name);
if (netif_msg_link(tp))
printk(KERN_WARNING "%s: PHY reset until link up\n", dev->name);
tp->phy_reset_enable(ioaddr);
@ -1169,18 +1311,23 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
/* dev zeroed in alloc_etherdev */
dev = alloc_etherdev(sizeof (*tp));
if (dev == NULL) {
printk(KERN_ERR PFX "unable to alloc new ethernet\n");
if (netif_msg_drv(&debug))
printk(KERN_ERR PFX "unable to alloc new ethernet\n");
goto err_out;
}
SET_MODULE_OWNER(dev);
SET_NETDEV_DEV(dev, &pdev->dev);
tp = netdev_priv(dev);
tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT);
/* enable device (incl. PCI PM wakeup and hotplug setup) */
rc = pci_enable_device(pdev);
if (rc) {
printk(KERN_ERR PFX "%s: enable failure\n", pci_name(pdev));
if (rc < 0) {
if (netif_msg_probe(tp)) {
printk(KERN_ERR PFX "%s: enable failure\n",
pci_name(pdev));
}
goto err_out_free_dev;
}
@ -1196,29 +1343,39 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command);
acpi_idle_state = pwr_command & PCI_PM_CTRL_STATE_MASK;
} else {
printk(KERN_ERR PFX
"Cannot find PowerManagement capability, aborting.\n");
if (netif_msg_probe(tp)) {
printk(KERN_ERR PFX
"Cannot find PowerManagement capability. "
"Aborting.\n");
}
goto err_out_mwi;
}
/* make sure PCI base addr 1 is MMIO */
if (!(pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) {
printk(KERN_ERR PFX
"region #1 not an MMIO resource, aborting\n");
if (netif_msg_probe(tp)) {
printk(KERN_ERR PFX
"region #1 not an MMIO resource, aborting\n");
}
rc = -ENODEV;
goto err_out_mwi;
}
/* check for weird/broken PCI region reporting */
if (pci_resource_len(pdev, 1) < R8169_REGS_SIZE) {
printk(KERN_ERR PFX "Invalid PCI region size(s), aborting\n");
if (netif_msg_probe(tp)) {
printk(KERN_ERR PFX
"Invalid PCI region size(s), aborting\n");
}
rc = -ENODEV;
goto err_out_mwi;
}
rc = pci_request_regions(pdev, MODULENAME);
if (rc) {
printk(KERN_ERR PFX "%s: could not request regions.\n",
pci_name(pdev));
if (rc < 0) {
if (netif_msg_probe(tp)) {
printk(KERN_ERR PFX "%s: could not request regions.\n",
pci_name(pdev));
}
goto err_out_mwi;
}
@ -1231,7 +1388,10 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
} else {
rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
if (rc < 0) {
printk(KERN_ERR PFX "DMA configuration failed.\n");
if (netif_msg_probe(tp)) {
printk(KERN_ERR PFX
"DMA configuration failed.\n");
}
goto err_out_free_res;
}
}
@ -1241,7 +1401,8 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
/* ioremap MMIO region */
ioaddr = ioremap(pci_resource_start(pdev, 1), R8169_REGS_SIZE);
if (ioaddr == NULL) {
printk(KERN_ERR PFX "cannot remap MMIO, aborting\n");
if (netif_msg_probe(tp))
printk(KERN_ERR PFX "cannot remap MMIO, aborting\n");
rc = -EIO;
goto err_out_free_res;
}
@ -1272,9 +1433,11 @@ rtl8169_init_board(struct pci_dev *pdev, struct net_device **dev_out,
}
if (i < 0) {
/* Unknown chip: assume array element #0, original RTL-8169 */
printk(KERN_DEBUG PFX
"PCI device %s: unknown chip version, assuming %s\n",
pci_name(pdev), rtl_chip_info[0].name);
if (netif_msg_probe(tp)) {
printk(KERN_DEBUG PFX "PCI device %s: "
"unknown chip version, assuming %s\n",
pci_name(pdev), rtl_chip_info[0].name);
}
i++;
}
tp->chipset = i;
@ -1308,7 +1471,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
struct rtl8169_private *tp;
void __iomem *ioaddr = NULL;
static int board_idx = -1;
static int printed_version = 0;
u8 autoneg, duplex;
u16 speed;
int i, rc;
@ -1318,10 +1480,9 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
board_idx++;
if (!printed_version) {
if (netif_msg_drv(&debug)) {
printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n",
MODULENAME, RTL8169_VERSION);
printed_version = 1;
}
rc = rtl8169_init_board(pdev, &dev, &ioaddr);
@ -1366,7 +1527,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
#ifdef CONFIG_R8169_NAPI
dev->poll = rtl8169_poll;
dev->weight = R8169_NAPI_WEIGHT;
printk(KERN_INFO PFX "NAPI enabled\n");
#endif
#ifdef CONFIG_R8169_VLAN
@ -1391,20 +1551,24 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
return rc;
}
printk(KERN_DEBUG "%s: Identified chip type is '%s'.\n", dev->name,
rtl_chip_info[tp->chipset].name);
if (netif_msg_probe(tp)) {
printk(KERN_DEBUG "%s: Identified chip type is '%s'.\n",
dev->name, rtl_chip_info[tp->chipset].name);
}
pci_set_drvdata(pdev, dev);
printk(KERN_INFO "%s: %s at 0x%lx, "
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
"IRQ %d\n",
dev->name,
rtl_chip_info[ent->driver_data].name,
dev->base_addr,
dev->dev_addr[0], dev->dev_addr[1],
dev->dev_addr[2], dev->dev_addr[3],
dev->dev_addr[4], dev->dev_addr[5], dev->irq);
if (netif_msg_probe(tp)) {
printk(KERN_INFO "%s: %s at 0x%lx, "
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
"IRQ %d\n",
dev->name,
rtl_chip_info[ent->driver_data].name,
dev->base_addr,
dev->dev_addr[0], dev->dev_addr[1],
dev->dev_addr[2], dev->dev_addr[3],
dev->dev_addr[4], dev->dev_addr[5], dev->irq);
}
rtl8169_hw_phy_config(dev);
@ -1427,7 +1591,7 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
rtl8169_set_speed(dev, autoneg, speed, duplex);
if (RTL_R8(PHYstatus) & TBI_Enable)
if ((RTL_R8(PHYstatus) & TBI_Enable) && netif_msg_link(tp))
printk(KERN_INFO PFX "%s: TBI auto-negotiating\n", dev->name);
return 0;
@ -1860,8 +2024,13 @@ static void rtl8169_reinit_task(void *_data)
ret = rtl8169_open(dev);
if (unlikely(ret < 0)) {
if (net_ratelimit()) {
printk(PFX KERN_ERR "%s: reinit failure (status = %d)."
" Rescheduling.\n", dev->name, ret);
struct rtl8169_private *tp = netdev_priv(dev);
if (netif_msg_drv(tp)) {
printk(PFX KERN_ERR
"%s: reinit failure (status = %d)."
" Rescheduling.\n", dev->name, ret);
}
}
rtl8169_schedule_work(dev, rtl8169_reinit_task);
}
@ -1886,8 +2055,12 @@ static void rtl8169_reset_task(void *_data)
netif_wake_queue(dev);
} else {
if (net_ratelimit()) {
printk(PFX KERN_EMERG "%s: Rx buffers shortage\n",
dev->name);
struct rtl8169_private *tp = netdev_priv(dev);
if (netif_msg_intr(tp)) {
printk(PFX KERN_EMERG
"%s: Rx buffers shortage\n", dev->name);
}
}
rtl8169_schedule_work(dev, rtl8169_reset_task);
}
@ -1973,8 +2146,11 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev)
int ret = 0;
if (unlikely(TX_BUFFS_AVAIL(tp) < skb_shinfo(skb)->nr_frags)) {
printk(KERN_ERR PFX "%s: BUG! Tx Ring full when queue awake!\n",
dev->name);
if (netif_msg_drv(tp)) {
printk(KERN_ERR
"%s: BUG! Tx Ring full when queue awake!\n",
dev->name);
}
goto err_stop;
}
@ -2049,8 +2225,11 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
pci_read_config_word(pdev, PCI_STATUS, &pci_status);
printk(KERN_ERR PFX "%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n",
dev->name, pci_cmd, pci_status);
if (netif_msg_intr(tp)) {
printk(KERN_ERR
"%s: PCI error (cmd = 0x%04x, status = 0x%04x).\n",
dev->name, pci_cmd, pci_status);
}
/*
* The recovery sequence below admits a very elaborated explanation:
@ -2069,7 +2248,8 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev)
/* The infamous DAC f*ckup only happens at boot time */
if ((tp->cp_cmd & PCIDAC) && !tp->dirty_rx && !tp->cur_rx) {
printk(KERN_INFO PFX "%s: disabling PCI DAC.\n", dev->name);
if (netif_msg_intr(tp))
printk(KERN_INFO "%s: disabling PCI DAC.\n", dev->name);
tp->cp_cmd &= ~PCIDAC;
RTL_W16(CPlusCmd, tp->cp_cmd);
dev->features &= ~NETIF_F_HIGHDMA;
@ -2180,7 +2360,7 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx;
rx_left = rtl8169_rx_quota(rx_left, (u32) dev->quota);
while (rx_left > 0) {
for (; rx_left > 0; rx_left--, cur_rx++) {
unsigned int entry = cur_rx % NUM_RX_DESC;
struct RxDesc *desc = tp->RxDescArray + entry;
u32 status;
@ -2190,9 +2370,12 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
if (status & DescOwn)
break;
if (status & RxRES) {
printk(KERN_INFO "%s: Rx ERROR. status = %08x\n",
dev->name, status);
if (unlikely(status & RxRES)) {
if (netif_msg_rx_err(tp)) {
printk(KERN_INFO
"%s: Rx ERROR. status = %08x\n",
dev->name, status);
}
tp->stats.rx_errors++;
if (status & (RxRWT | RxRUNT))
tp->stats.rx_length_errors++;
@ -2214,7 +2397,7 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
tp->stats.rx_dropped++;
tp->stats.rx_length_errors++;
rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
goto move_on;
continue;
}
rtl8169_rx_csum(skb, desc);
@ -2243,16 +2426,13 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
tp->stats.rx_bytes += pkt_size;
tp->stats.rx_packets++;
}
move_on:
cur_rx++;
rx_left--;
}
count = cur_rx - tp->cur_rx;
tp->cur_rx = cur_rx;
delta = rtl8169_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx);
if (!delta && count)
if (!delta && count && netif_msg_intr(tp))
printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name);
tp->dirty_rx += delta;
@ -2263,7 +2443,7 @@ move_on:
* after refill ?
* - how do others driver handle this condition (Uh oh...).
*/
if (tp->dirty_rx + NUM_RX_DESC == tp->cur_rx)
if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp))
printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name);
return count;
@ -2315,7 +2495,7 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
if (likely(netif_rx_schedule_prep(dev)))
__netif_rx_schedule(dev);
else {
else if (netif_msg_intr(tp)) {
printk(KERN_INFO "%s: interrupt %04x taken in poll\n",
dev->name, status);
}
@ -2334,8 +2514,10 @@ rtl8169_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
} while (boguscnt > 0);
if (boguscnt <= 0) {
printk(KERN_WARNING "%s: Too much work at interrupt!\n",
dev->name);
if (net_ratelimit() && netif_msg_intr(tp)) {
printk(KERN_WARNING
"%s: Too much work at interrupt!\n", dev->name);
}
/* Clear all interrupt sources. */
RTL_W16(IntrStatus, 0xffff);
}
@ -2458,8 +2640,10 @@ rtl8169_set_rx_mode(struct net_device *dev)
if (dev->flags & IFF_PROMISC) {
/* Unconditionally log net taps. */
printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n",
dev->name);
if (netif_msg_link(tp)) {
printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n",
dev->name);
}
rx_mode =
AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
AcceptAllPhys;

View File

@ -4212,7 +4212,7 @@ SK_BOOL DualNet;
Flags);
SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING;
netif_carrier_off(pAC->dev[Param.Para32[0]]);
spin_unlock_irqrestore(
&pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
Flags);
@ -4355,7 +4355,7 @@ SK_BOOL DualNet;
}
/* Inform the world that link protocol is up. */
pAC->dev[Param.Para32[0]]->flags |= IFF_RUNNING;
netif_carrier_on(pAC->dev[Param.Para32[0]]);
break;
case SK_DRV_NET_DOWN: /* SK_U32 Reason */
@ -4368,7 +4368,7 @@ SK_BOOL DualNet;
} else {
DoPrintInterfaceChange = SK_TRUE;
}
pAC->dev[Param.Para32[1]]->flags &= ~IFF_RUNNING;
netif_carrier_off(pAC->dev[Param.Para32[1]]);
break;
case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
@ -4961,7 +4961,6 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
#ifdef CONFIG_NET_POLL_CONTROLLER
dev->poll_controller = &SkGePollController;
#endif
dev->flags &= ~IFF_RUNNING;
SET_NETDEV_DEV(dev, &pdev->dev);
SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);
@ -5035,7 +5034,6 @@ static int __devinit skge_probe_one(struct pci_dev *pdev,
dev->set_mac_address = &SkGeSetMacAddr;
dev->do_ioctl = &SkGeIoctl;
dev->change_mtu = &SkGeChangeMtu;
dev->flags &= ~IFF_RUNNING;
SET_NETDEV_DEV(dev, &pdev->dev);
SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps);

File diff suppressed because it is too large Load Diff

View File

@ -1,165 +0,0 @@
/*-
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* Module : sk_g16.h
* Version : $Revision$
*
* Author : M.Hipp (mhipp@student.uni-tuebingen.de)
* changes by : Patrick J.D. Weichmann
*
* Date Created : 94/05/25
*
* Description : In here are all necessary definitions of
* the am7990 (LANCE) chip used for writing a
* network device driver which uses this chip
*
* $Log$
-*/
#ifndef SK_G16_H
#define SK_G16_H
/*
* Control and Status Register 0 (CSR0) bit definitions
*
* (R=Readable) (W=Writeable) (S=Set on write) (C-Clear on write)
*
*/
#define CSR0_ERR 0x8000 /* Error summary (R) */
#define CSR0_BABL 0x4000 /* Babble transmitter timeout error (RC) */
#define CSR0_CERR 0x2000 /* Collision Error (RC) */
#define CSR0_MISS 0x1000 /* Missed packet (RC) */
#define CSR0_MERR 0x0800 /* Memory Error (RC) */
#define CSR0_RINT 0x0400 /* Receiver Interrupt (RC) */
#define CSR0_TINT 0x0200 /* Transmit Interrupt (RC) */
#define CSR0_IDON 0x0100 /* Initialization Done (RC) */
#define CSR0_INTR 0x0080 /* Interrupt Flag (R) */
#define CSR0_INEA 0x0040 /* Interrupt Enable (RW) */
#define CSR0_RXON 0x0020 /* Receiver on (R) */
#define CSR0_TXON 0x0010 /* Transmitter on (R) */
#define CSR0_TDMD 0x0008 /* Transmit Demand (RS) */
#define CSR0_STOP 0x0004 /* Stop (RS) */
#define CSR0_STRT 0x0002 /* Start (RS) */
#define CSR0_INIT 0x0001 /* Initialize (RS) */
#define CSR0_CLRALL 0x7f00 /* mask for all clearable bits */
/*
* Control and Status Register 3 (CSR3) bit definitions
*
*/
#define CSR3_BSWAP 0x0004 /* Byte Swap (RW) */
#define CSR3_ACON 0x0002 /* ALE Control (RW) */
#define CSR3_BCON 0x0001 /* Byte Control (RW) */
/*
* Initialization Block Mode operation Bit Definitions.
*/
#define MODE_PROM 0x8000 /* Promiscuous Mode */
#define MODE_INTL 0x0040 /* Internal Loopback */
#define MODE_DRTY 0x0020 /* Disable Retry */
#define MODE_COLL 0x0010 /* Force Collision */
#define MODE_DTCR 0x0008 /* Disable Transmit CRC) */
#define MODE_LOOP 0x0004 /* Loopback */
#define MODE_DTX 0x0002 /* Disable the Transmitter */
#define MODE_DRX 0x0001 /* Disable the Receiver */
#define MODE_NORMAL 0x0000 /* Normal operation mode */
/*
* Receive message descriptor status bit definitions.
*/
#define RX_OWN 0x80 /* Owner bit 0 = host, 1 = lance */
#define RX_ERR 0x40 /* Error Summary */
#define RX_FRAM 0x20 /* Framing Error */
#define RX_OFLO 0x10 /* Overflow Error */
#define RX_CRC 0x08 /* CRC Error */
#define RX_BUFF 0x04 /* Buffer Error */
#define RX_STP 0x02 /* Start of Packet */
#define RX_ENP 0x01 /* End of Packet */
/*
* Transmit message descriptor status bit definitions.
*/
#define TX_OWN 0x80 /* Owner bit 0 = host, 1 = lance */
#define TX_ERR 0x40 /* Error Summary */
#define TX_MORE 0x10 /* More the 1 retry needed to Xmit */
#define TX_ONE 0x08 /* One retry needed to Xmit */
#define TX_DEF 0x04 /* Deferred */
#define TX_STP 0x02 /* Start of Packet */
#define TX_ENP 0x01 /* End of Packet */
/*
* Transmit status (2) (valid if TX_ERR == 1)
*/
#define TX_BUFF 0x8000 /* Buffering error (no ENP) */
#define TX_UFLO 0x4000 /* Underflow (late memory) */
#define TX_LCOL 0x1000 /* Late collision */
#define TX_LCAR 0x0400 /* Loss of Carrier */
#define TX_RTRY 0x0200 /* Failed after 16 retransmissions */
#define TX_TDR 0x003f /* Time-domain-reflectometer-value */
/*
* Structures used for Communication with the LANCE
*/
/* LANCE Initialize Block */
struct init_block
{
unsigned short mode; /* Mode Register */
unsigned char paddr[6]; /* Physical Address (MAC) */
unsigned char laddr[8]; /* Logical Filter Address (not used) */
unsigned int rdrp; /* Receive Descriptor Ring pointer */
unsigned int tdrp; /* Transmit Descriptor Ring pointer */
};
/* Receive Message Descriptor Entry */
struct rmd
{
union
{
unsigned long buffer; /* Address of buffer */
struct
{
unsigned char unused[3];
unsigned volatile char status; /* Status Bits */
} s;
} u;
volatile short blen; /* Buffer Length (two's complement) */
unsigned short mlen; /* Message Byte Count */
};
/* Transmit Message Descriptor Entry */
struct tmd
{
union
{
unsigned long buffer; /* Address of buffer */
struct
{
unsigned char unused[3];
unsigned volatile char status; /* Status Bits */
} s;
} u;
unsigned short blen; /* Buffer Length (two's complement) */
unsigned volatile short status2; /* Error Status Bits */
};
#endif /* End of SK_G16_H */

3386
drivers/net/skge.c Normal file

File diff suppressed because it is too large Load Diff

3005
drivers/net/skge.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -129,7 +129,7 @@ MODULE_PARM_DESC(nowait, "set to 1 for no wait state");
/*
* Transmit timeout, default 5 seconds.
*/
static int watchdog = 5000;
static int watchdog = 1000;
module_param(watchdog, int, 0400);
MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds");
@ -660,15 +660,14 @@ static void smc_hardware_send_pkt(unsigned long data)
SMC_outw(((len & 1) ? (0x2000 | buf[len-1]) : 0), ioaddr, DATA_REG);
/*
* If THROTTLE_TX_PKTS is set, we look at the TX_EMPTY flag
* before queueing this packet for TX, and if it's clear then
* we stop the queue here. This will have the effect of
* having at most 2 packets queued for TX in the chip's memory
* at all time. If THROTTLE_TX_PKTS is not set then the queue
* is stopped only when memory allocation (MC_ALLOC) does not
* succeed right away.
* If THROTTLE_TX_PKTS is set, we stop the queue here. This will
* have the effect of having at most one packet queued for TX
* in the chip's memory at all time.
*
* If THROTTLE_TX_PKTS is not set then the queue is stopped only
* when memory allocation (MC_ALLOC) does not succeed right away.
*/
if (THROTTLE_TX_PKTS && !(SMC_GET_INT() & IM_TX_EMPTY_INT))
if (THROTTLE_TX_PKTS)
netif_stop_queue(dev);
/* queue the packet for TX */
@ -792,17 +791,20 @@ static void smc_tx(struct net_device *dev)
DBG(2, "%s: TX STATUS 0x%04x PNR 0x%02x\n",
dev->name, tx_status, packet_no);
if (!(tx_status & TS_SUCCESS))
if (!(tx_status & ES_TX_SUC))
lp->stats.tx_errors++;
if (tx_status & TS_LOSTCAR)
if (tx_status & ES_LOSTCARR)
lp->stats.tx_carrier_errors++;
if (tx_status & TS_LATCOL) {
PRINTK("%s: late collision occurred on last xmit\n", dev->name);
if (tx_status & (ES_LATCOL | ES_16COL)) {
PRINTK("%s: %s occurred on last xmit\n", dev->name,
(tx_status & ES_LATCOL) ?
"late collision" : "too many collisions");
lp->stats.tx_window_errors++;
if (!(lp->stats.tx_window_errors & 63) && net_ratelimit()) {
printk(KERN_INFO "%s: unexpectedly large numbers of "
"late collisions. Please check duplex "
printk(KERN_INFO "%s: unexpectedly large number of "
"bad collisions. Please check duplex "
"setting.\n", dev->name);
}
}
@ -1236,7 +1238,7 @@ static void smc_10bt_check_media(struct net_device *dev, int init)
old_carrier = netif_carrier_ok(dev) ? 1 : 0;
SMC_SELECT_BANK(0);
new_carrier = SMC_inw(ioaddr, EPH_STATUS_REG) & ES_LINK_OK ? 1 : 0;
new_carrier = (SMC_GET_EPH_STATUS() & ES_LINK_OK) ? 1 : 0;
SMC_SELECT_BANK(2);
if (init || (old_carrier != new_carrier)) {
@ -1308,15 +1310,16 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (!status)
break;
if (status & IM_RCV_INT) {
DBG(3, "%s: RX irq\n", dev->name);
smc_rcv(dev);
} else if (status & IM_TX_INT) {
if (status & IM_TX_INT) {
/* do this before RX as it will free memory quickly */
DBG(3, "%s: TX int\n", dev->name);
smc_tx(dev);
SMC_ACK_INT(IM_TX_INT);
if (THROTTLE_TX_PKTS)
netif_wake_queue(dev);
} else if (status & IM_RCV_INT) {
DBG(3, "%s: RX irq\n", dev->name);
smc_rcv(dev);
} else if (status & IM_ALLOC_INT) {
DBG(3, "%s: Allocation irq\n", dev->name);
tasklet_hi_schedule(&lp->tx_task);
@ -1337,7 +1340,10 @@ static irqreturn_t smc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* multiple collisions */
lp->stats.collisions += card_stats & 0xF;
} else if (status & IM_RX_OVRN_INT) {
DBG(1, "%s: RX overrun\n", dev->name);
DBG(1, "%s: RX overrun (EPH_ST 0x%04x)\n", dev->name,
({ int eph_st; SMC_SELECT_BANK(0);
eph_st = SMC_GET_EPH_STATUS();
SMC_SELECT_BANK(2); eph_st; }) );
SMC_ACK_INT(IM_RX_OVRN_INT);
lp->stats.rx_errors++;
lp->stats.rx_fifo_errors++;
@ -1389,7 +1395,7 @@ static void smc_timeout(struct net_device *dev)
{
struct smc_local *lp = netdev_priv(dev);
void __iomem *ioaddr = lp->base;
int status, mask, meminfo, fifo;
int status, mask, eph_st, meminfo, fifo;
DBG(2, "%s: %s\n", dev->name, __FUNCTION__);
@ -1398,11 +1404,13 @@ static void smc_timeout(struct net_device *dev)
mask = SMC_GET_INT_MASK();
fifo = SMC_GET_FIFO();
SMC_SELECT_BANK(0);
eph_st = SMC_GET_EPH_STATUS();
meminfo = SMC_GET_MIR();
SMC_SELECT_BANK(2);
spin_unlock_irq(&lp->lock);
PRINTK( "%s: INT 0x%02x MASK 0x%02x MEM 0x%04x FIFO 0x%04x\n",
dev->name, status, mask, meminfo, fifo );
PRINTK( "%s: TX timeout (INT 0x%02x INTMASK 0x%02x "
"MEM 0x%04x FIFO 0x%04x EPH_ST 0x%04x)\n",
dev->name, status, mask, meminfo, fifo, eph_st );
smc_reset(dev);
smc_enable(dev);
@ -1863,7 +1871,7 @@ static int __init smc_probe(struct net_device *dev, void __iomem *ioaddr)
SMC_SELECT_BANK(1);
val = SMC_GET_BASE();
val = ((val & 0x1F00) >> 3) << SMC_IO_SHIFT;
if (((unsigned long)ioaddr & ((PAGE_SIZE-1)<<SMC_IO_SHIFT)) != val) { /*XXX: WTF? */
if (((unsigned int)ioaddr & (0x3e0 << SMC_IO_SHIFT)) != val) {
printk("%s: IOADDR %p doesn't match configuration (%x).\n",
CARDNAME, ioaddr, val);
}

View File

@ -151,7 +151,7 @@
/* We actually can't write halfwords properly if not word aligned */
static inline void
SMC_outw(u16 val, unsigned long ioaddr, int reg)
SMC_outw(u16 val, void __iomem *ioaddr, int reg)
{
if (reg & 2) {
unsigned int v = val << 16;
@ -317,7 +317,7 @@ static inline void SMC_outsw (unsigned long a, int r, unsigned char* p, int l)
#define SMC_insl(a, r, p, l) \
smc_pxa_dma_insl(a, lp->physaddr, r, dev->dma, p, l)
static inline void
smc_pxa_dma_insl(u_long ioaddr, u_long physaddr, int reg, int dma,
smc_pxa_dma_insl(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
u_char *buf, int len)
{
dma_addr_t dmabuf;
@ -355,7 +355,7 @@ smc_pxa_dma_insl(u_long ioaddr, u_long physaddr, int reg, int dma,
#define SMC_insw(a, r, p, l) \
smc_pxa_dma_insw(a, lp->physaddr, r, dev->dma, p, l)
static inline void
smc_pxa_dma_insw(u_long ioaddr, u_long physaddr, int reg, int dma,
smc_pxa_dma_insw(void __iomem *ioaddr, u_long physaddr, int reg, int dma,
u_char *buf, int len)
{
dma_addr_t dmabuf;
@ -680,14 +680,6 @@ static const char * chip_ids[ 16 ] = {
NULL, NULL, NULL};
/*
. Transmit status bits
*/
#define TS_SUCCESS 0x0001
#define TS_LOSTCAR 0x0400
#define TS_LATCOL 0x0200
#define TS_16COL 0x0010
/*
. Receive status bits
*/
@ -845,6 +837,7 @@ static const char * chip_ids[ 16 ] = {
#define SMC_GET_FIFO() SMC_inw( ioaddr, FIFO_REG )
#define SMC_GET_PTR() SMC_inw( ioaddr, PTR_REG )
#define SMC_SET_PTR(x) SMC_outw( x, ioaddr, PTR_REG )
#define SMC_GET_EPH_STATUS() SMC_inw( ioaddr, EPH_STATUS_REG )
#define SMC_GET_RCR() SMC_inw( ioaddr, RCR_REG )
#define SMC_SET_RCR(x) SMC_outw( x, ioaddr, RCR_REG )
#define SMC_GET_REV() SMC_inw( ioaddr, REV_REG )

View File

@ -2,7 +2,7 @@
/*
Written 1998-2000 by Donald Becker.
Current maintainer is Ion Badulescu <ionut@cs.columbia.edu>. Please
Current maintainer is Ion Badulescu <ionut ta badula tod org>. Please
send all bug reports to me, and not to Donald Becker, as this code
has been heavily modified from Donald's original version.
@ -129,12 +129,18 @@
- put the chip to a D3 slumber on driver unload
- added config option to enable/disable NAPI
TODO: bugfixes (no bugs known as of right now)
LK1.4.2 (Ion Badulescu)
- finally added firmware (GPL'ed by Adaptec)
- removed compatibility code for 2.2.x
TODO: - fix forced speed/duplexing code (broken a long time ago, when
somebody converted the driver to use the generic MII code)
- fix VLAN support
*/
#define DRV_NAME "starfire"
#define DRV_VERSION "1.03+LK1.4.1"
#define DRV_RELDATE "February 10, 2002"
#define DRV_VERSION "1.03+LK1.4.2"
#define DRV_RELDATE "January 19, 2005"
#include <linux/config.h>
#include <linux/version.h>
@ -145,25 +151,15 @@ TODO: bugfixes (no bugs known as of right now)
#include <linux/etherdevice.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/crc32.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/if_vlan.h>
#include <asm/processor.h> /* Processor type for cache alignment. */
#include <asm/uaccess.h>
#include <asm/io.h>
/*
* Adaptec's license for their drivers (which is where I got the
* firmware files) does not allow one to redistribute them. Thus, we can't
* include the firmware with this driver.
*
* However, should a legal-to-distribute firmware become available,
* the driver developer would need only to obtain the firmware in the
* form of a C header file.
* Once that's done, the #undef below must be changed into a #define
* for this driver to really use the firmware. Note that Rx/Tx
* hardware TCP checksumming is not possible without the firmware.
*
* WANTED: legal firmware to include with this GPL'd driver.
*/
#undef HAS_FIRMWARE
#include "starfire_firmware.h"
/*
* The current frame processor firmware fails to checksum a fragment
* of length 1. If and when this is fixed, the #define below can be removed.
@ -172,13 +168,7 @@ TODO: bugfixes (no bugs known as of right now)
/*
* Define this if using the driver with the zero-copy patch
*/
#if defined(HAS_FIRMWARE) && defined(MAX_SKB_FRAGS)
#define ZEROCOPY
#endif
#ifdef HAS_FIRMWARE
#include "starfire_firmware.h"
#endif /* HAS_FIRMWARE */
#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
#define VLAN_SUPPORT
@ -202,11 +192,7 @@ static int mtu;
The Starfire has a 512 element hash table based on the Ethernet CRC. */
static int multicast_filter_limit = 512;
/* Whether to do TCP/UDP checksums in hardware */
#ifdef HAS_FIRMWARE
static int enable_hw_cksum = 1;
#else
static int enable_hw_cksum = 0;
#endif
#define PKT_BUF_SZ 1536 /* Size of each temporary Rx buffer.*/
/*
@ -291,43 +277,15 @@ static int full_duplex[MAX_UNITS] = {0, };
#define RX_DESC_ADDR_SIZE RxDescAddr32bit
#endif
#ifdef MAX_SKB_FRAGS
#define skb_first_frag_len(skb) skb_headlen(skb)
#define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1)
#else /* not MAX_SKB_FRAGS */
#define skb_first_frag_len(skb) (skb->len)
#define skb_num_frags(skb) 1
#endif /* not MAX_SKB_FRAGS */
/* 2.2.x compatibility code */
#if LINUX_VERSION_CODE < 0x20300
#include "starfire-kcomp22.h"
#else /* LINUX_VERSION_CODE > 0x20300 */
#include <linux/crc32.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
#include <linux/if_vlan.h>
#define init_tx_timer(dev, func, timeout) \
dev->tx_timeout = func; \
dev->watchdog_timeo = timeout;
#define kick_tx_timer(dev, func, timeout)
#define netif_start_if(dev)
#define netif_stop_if(dev)
#define PCI_SLOT_NAME(pci_dev) pci_name(pci_dev)
#endif /* LINUX_VERSION_CODE > 0x20300 */
#ifdef HAVE_NETDEV_POLL
#define init_poll(dev) \
do { \
dev->poll = &netdev_poll; \
dev->weight = max_interrupt_work;
dev->weight = max_interrupt_work; \
} while (0)
#define netdev_rx(dev, ioaddr) \
do { \
u32 intr_enable; \
@ -341,7 +299,7 @@ do { \
/* Paranoia check */ \
intr_enable = readl(ioaddr + IntrEnable); \
if (intr_enable & (IntrRxDone | IntrRxEmpty)) { \
printk("%s: interrupt while in polling mode!\n", dev->name); \
printk(KERN_INFO "%s: interrupt while in polling mode!\n", dev->name); \
intr_enable &= ~(IntrRxDone | IntrRxEmpty); \
writel(intr_enable, ioaddr + IntrEnable); \
} \
@ -371,6 +329,7 @@ KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELD
MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
module_param(max_interrupt_work, int, 0);
module_param(mtu, int, 0);
@ -425,7 +384,7 @@ on the 32/64 bitness of the architecture), and relies on automatic
minimum-length padding. It does not use the completion queue
consumer index, but instead checks for non-zero status entries.
For receive this driver uses type 0/1/2/3 receive descriptors. The driver
For receive this driver uses type 2/3 receive descriptors. The driver
allocates full frame size skbuffs for the Rx ring buffers, so all frames
should fit in a single descriptor. The driver does not use the completion
queue consumer index, but instead checks for non-zero status entries.
@ -476,7 +435,7 @@ IVc. Errata
*/
enum chip_capability_flags {CanHaveMII=1, };
@ -670,7 +629,6 @@ struct full_rx_done_desc {
u32 timestamp;
};
/* XXX: this is ugly and I'm not sure it's worth the trouble -Ion */
#ifdef HAS_FIRMWARE
#ifdef VLAN_SUPPORT
typedef struct full_rx_done_desc rx_done_desc;
#define RxComplType RxComplType3
@ -678,15 +636,6 @@ typedef struct full_rx_done_desc rx_done_desc;
typedef struct csum_rx_done_desc rx_done_desc;
#define RxComplType RxComplType2
#endif /* not VLAN_SUPPORT */
#else /* not HAS_FIRMWARE */
#ifdef VLAN_SUPPORT
typedef struct basic_rx_done_desc rx_done_desc;
#define RxComplType RxComplType1
#else /* not VLAN_SUPPORT */
typedef struct short_rx_done_desc rx_done_desc;
#define RxComplType RxComplType0
#endif /* not VLAN_SUPPORT */
#endif /* not HAS_FIRMWARE */
enum rx_done_bits {
RxOK=0x20000000, RxFIFOErr=0x10000000, RxBufQ2=0x08000000,
@ -898,13 +847,10 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
/* enable MWI -- it vastly improves Rx performance on sparc64 */
pci_set_mwi(pdev);
#ifdef MAX_SKB_FRAGS
dev->features |= NETIF_F_SG;
#endif /* MAX_SKB_FRAGS */
#ifdef ZEROCOPY
/* Starfire can do TCP/UDP checksumming */
if (enable_hw_cksum)
dev->features |= NETIF_F_IP_CSUM;
dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
#endif /* ZEROCOPY */
#ifdef VLAN_SUPPORT
dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
@ -1008,7 +954,8 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
/* The chip-specific entries in the device structure. */
dev->open = &netdev_open;
dev->hard_start_xmit = &start_tx;
init_tx_timer(dev, tx_timeout, TX_TIMEOUT);
dev->tx_timeout = tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
init_poll(dev);
dev->stop = &netdev_close;
dev->get_stats = &get_stats;
@ -1039,7 +986,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
if ((mdio_read(dev, phy, MII_BMCR) & BMCR_RESET) == 0)
break;
if (boguscnt == 0) {
printk("%s: PHY reset never completed!\n", dev->name);
printk("%s: PHY#%d reset never completed!\n", dev->name, phy);
continue;
}
mii_status = mdio_read(dev, phy, MII_BMSR);
@ -1110,6 +1057,7 @@ static int netdev_open(struct net_device *dev)
size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size;
/* Do we ever need to reset the chip??? */
retval = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev);
if (retval)
return retval;
@ -1211,7 +1159,6 @@ static int netdev_open(struct net_device *dev)
writel(np->intr_timer_ctrl, ioaddr + IntrTimerCtrl);
netif_start_if(dev);
netif_start_queue(dev);
if (debug > 1)
@ -1238,13 +1185,11 @@ static int netdev_open(struct net_device *dev)
writel(ETH_P_8021Q, ioaddr + VlanType);
#endif /* VLAN_SUPPORT */
#ifdef HAS_FIRMWARE
/* Load Rx/Tx firmware into the frame processors */
for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++)
writel(firmware_rx[i], ioaddr + RxGfpMem + i * 4);
for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++)
writel(firmware_tx[i], ioaddr + TxGfpMem + i * 4);
#endif /* HAS_FIRMWARE */
if (enable_hw_cksum)
/* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
writel(TxEnable|TxGFPEnable|RxEnable|RxGFPEnable, ioaddr + GenCtrl);
@ -1378,8 +1323,6 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
u32 status;
int i;
kick_tx_timer(dev, tx_timeout, TX_TIMEOUT);
/*
* be cautious here, wrapping the queue has weird semantics
* and we may not have enough slots even when it seems we do.
@ -1404,7 +1347,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
}
if (has_bad_length)
skb_checksum_help(skb);
skb_checksum_help(skb, 0);
}
#endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
@ -1433,12 +1376,10 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
np->tx_info[entry].mapping =
pci_map_single(np->pci_dev, skb->data, skb_first_frag_len(skb), PCI_DMA_TODEVICE);
} else {
#ifdef MAX_SKB_FRAGS
skb_frag_t *this_frag = &skb_shinfo(skb)->frags[i - 1];
status |= this_frag->size;
np->tx_info[entry].mapping =
pci_map_single(np->pci_dev, page_address(this_frag->page) + this_frag->page_offset, this_frag->size, PCI_DMA_TODEVICE);
#endif /* MAX_SKB_FRAGS */
}
np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping);
@ -1531,7 +1472,6 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
np->tx_info[entry].mapping = 0;
np->dirty_tx += np->tx_info[entry].used_slots;
entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE;
#ifdef MAX_SKB_FRAGS
{
int i;
for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
@ -1543,7 +1483,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
entry++;
}
}
#endif /* MAX_SKB_FRAGS */
dev_kfree_skb_irq(skb);
}
np->tx_done_q[np->tx_done].status = 0;
@ -1603,7 +1543,7 @@ static int __netdev_rx(struct net_device *dev, int *quota)
if (debug > 4)
printk(KERN_DEBUG " netdev_rx() status of %d was %#8.8x.\n", np->rx_done, desc_status);
if (!(desc_status & RxOK)) {
/* There was a error. */
/* There was an error. */
if (debug > 2)
printk(KERN_DEBUG " netdev_rx() Rx error was %#8.8x.\n", desc_status);
np->stats.rx_errors++;
@ -1656,11 +1596,10 @@ static int __netdev_rx(struct net_device *dev, int *quota)
#endif
skb->protocol = eth_type_trans(skb, dev);
#if defined(HAS_FIRMWARE) || defined(VLAN_SUPPORT)
#ifdef VLAN_SUPPORT
if (debug > 4)
printk(KERN_DEBUG " netdev_rx() status2 of %d was %#4.4x.\n", np->rx_done, le16_to_cpu(desc->status2));
#endif
#ifdef HAS_FIRMWARE
if (le16_to_cpu(desc->status2) & 0x0100) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
np->stats.rx_compressed++;
@ -1679,7 +1618,6 @@ static int __netdev_rx(struct net_device *dev, int *quota)
skb->csum = le16_to_cpu(desc->csum);
printk(KERN_DEBUG "%s: checksum_hw, status2 = %#x\n", dev->name, le16_to_cpu(desc->status2));
}
#endif /* HAS_FIRMWARE */
#ifdef VLAN_SUPPORT
if (np->vlgrp && le16_to_cpu(desc->status2) & 0x0200) {
if (debug > 4)
@ -1900,9 +1838,6 @@ static struct net_device_stats *get_stats(struct net_device *dev)
}
/* Chips may use the upper or lower CRC bits, and may reverse and/or invert
them. Select the endian-ness that results in minimal calculations.
*/
static void set_rx_mode(struct net_device *dev)
{
struct netdev_private *np = netdev_priv(dev);
@ -1969,6 +1904,8 @@ static void set_rx_mode(struct net_device *dev)
memset(mc_filter, 0, sizeof(mc_filter));
for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
i++, mclist = mclist->next) {
/* The chip uses the upper 9 CRC bits
as index into the hash table */
int bit_nr = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 23;
__u32 *fptr = (__u32 *) &mc_filter[(bit_nr >> 4) & ~1];
@ -2001,7 +1938,7 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
struct netdev_private *np = netdev_priv(dev);
strcpy(info->driver, DRV_NAME);
strcpy(info->version, DRV_VERSION);
strcpy(info->bus_info, PCI_SLOT_NAME(np->pci_dev));
strcpy(info->bus_info, pci_name(np->pci_dev));
}
static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
@ -2083,7 +2020,6 @@ static int netdev_close(struct net_device *dev)
int i;
netif_stop_queue(dev);
netif_stop_if(dev);
if (debug > 1) {
printk(KERN_DEBUG "%s: Shutting down ethercard, Intr status %#8.8x.\n",
@ -2184,7 +2120,13 @@ static int __init starfire_init (void)
/* when a module, this is printed whether or not devices are found in probe */
#ifdef MODULE
printk(version);
#ifdef HAVE_NETDEV_POLL
printk(KERN_INFO DRV_NAME ": polling (NAPI) enabled\n");
#else
printk(KERN_INFO DRV_NAME ": polling (NAPI) disabled\n");
#endif
#endif
#ifndef ADDR_64BITS
/* we can do this test only at run-time... sigh */
if (sizeof(dma_addr_t) == sizeof(u64)) {
@ -2192,10 +2134,6 @@ static int __init starfire_init (void)
return -ENODEV;
}
#endif /* not ADDR_64BITS */
#ifndef HAS_FIRMWARE
/* unconditionally disable hw cksums if firmware is not present */
enable_hw_cksum = 0;
#endif /* not HAS_FIRMWARE */
return pci_module_init (&starfire_driver);
}

View File

@ -0,0 +1,346 @@
/*
* Copyright 2003 Adaptec, Inc.
*
* Please read the following license before using the Adaptec Software
* ("Program"). If you do not agree to the license terms, do not use the
* Program:
*
* You agree to be bound by version 2 of the General Public License ("GPL")
* dated June 1991, which can be found at http://www.fsf.org/licenses/gpl.html.
* If the link is broken, write to Free Software Foundation, 59 Temple Place,
* Boston, Massachusetts 02111-1307.
*
* BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE IT IS LICENSED "AS IS" AND
* THERE IS NO WARRANTY FOR THE PROGRAM, INCLUDING BUT NOT LIMITED TO THE
* IMPLIED WARRANTIES OF MERCHANTIBILITY OR FITNESS FOR A PARTICULAR PURPOSE
* (TO THE EXTENT PERMITTED BY APPLICABLE LAW). USE OF THE PROGRAM IS AT YOUR
* OWN RISK. IN NO EVENT WILL ADAPTEC OR ITS LICENSORS BE LIABLE TO YOU FOR
* DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
* ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM.
*
*/
static const u32 firmware_rx[] = {
0x010003dc, 0x00000000,
0x04000421, 0x00000086,
0x80000015, 0x0000180e,
0x81000015, 0x00006664,
0x1a0040ab, 0x00000b06,
0x14200011, 0x00000000,
0x14204022, 0x0000aaaa,
0x14204022, 0x00000300,
0x14204022, 0x00000000,
0x1a0040ab, 0x00000b14,
0x14200011, 0x00000000,
0x83000015, 0x00000002,
0x04000021, 0x00000000,
0x00000010, 0x00000000,
0x04000421, 0x00000087,
0x00000010, 0x00000000,
0x00000010, 0x00000000,
0x00008015, 0x00000000,
0x0000003e, 0x00000000,
0x00000010, 0x00000000,
0x82000015, 0x00004000,
0x009e8050, 0x00000000,
0x03008015, 0x00000000,
0x86008015, 0x00000000,
0x82000015, 0x00008000,
0x0100001c, 0x00000000,
0x000050a0, 0x0000010c,
0x4e20d011, 0x00006008,
0x1420d012, 0x00004008,
0x0000f090, 0x00007000,
0x0000c8b0, 0x00003000,
0x00004040, 0x00000000,
0x00108015, 0x00000000,
0x00a2c150, 0x00004000,
0x00a400b0, 0x00000014,
0x00000020, 0x00000000,
0x2500400d, 0x00002525,
0x00047220, 0x00003100,
0x00934070, 0x00000000,
0x00000020, 0x00000000,
0x00924460, 0x00000184,
0x2b20c011, 0x00000000,
0x0000c420, 0x00000540,
0x36014018, 0x0000422d,
0x14200011, 0x00000000,
0x00924460, 0x00000183,
0x3200001f, 0x00000034,
0x02ac0015, 0x00000002,
0x00a60110, 0x00000008,
0x42200011, 0x00000000,
0x00924060, 0x00000103,
0x0000001e, 0x00000000,
0x00000020, 0x00000100,
0x0000001e, 0x00000000,
0x00924460, 0x00000086,
0x00004080, 0x00000000,
0x0092c070, 0x00000000,
0x00924060, 0x00000100,
0x0000c890, 0x00005000,
0x00a6c110, 0x00000000,
0x00b0c090, 0x00000012,
0x021c0015, 0x00000000,
0x3200001f, 0x00000034,
0x00924460, 0x00000510,
0x44210011, 0x00000000,
0x42000011, 0x00000000,
0x83000015, 0x00000040,
0x00924460, 0x00000508,
0x45014018, 0x00004545,
0x00808050, 0x00000000,
0x62208012, 0x00000000,
0x82000015, 0x00000800,
0x15200011, 0x00000000,
0x00000010, 0x00000000,
0x00000010, 0x00000000,
0x00000010, 0x00000000,
0x00000010, 0x00000000,
0x00000010, 0x00000000,
0x80000015, 0x0000eea4,
0x81000015, 0x0000005f,
0x00000060, 0x00000000,
0x00004120, 0x00000000,
0x00004a00, 0x00004000,
0x00924460, 0x00000190,
0x5601401a, 0x00005956,
0x14000011, 0x00000000,
0x00934050, 0x00000018,
0x00930050, 0x00000018,
0x3601403a, 0x0000002d,
0x000643a9, 0x00000000,
0x0000c420, 0x00000140,
0x5601401a, 0x00005956,
0x14000011, 0x00000000,
0x00000010, 0x00000000,
0x00000010, 0x00000000,
0x000642a9, 0x00000000,
0x00024420, 0x00000183,
0x5601401a, 0x00005956,
0x82000015, 0x00002000,
0x15200011, 0x00000000,
0x82000015, 0x00000010,
0x15200011, 0x00000000,
0x82000015, 0x00000010,
0x15200011, 0x00000000,
}; /* 104 Rx instructions */
#define FIRMWARE_RX_SIZE 104
static const u32 firmware_tx[] = {
0x010003dc, 0x00000000,
0x04000421, 0x00000086,
0x80000015, 0x0000180e,
0x81000015, 0x00006664,
0x1a0040ab, 0x00000b06,
0x14200011, 0x00000000,
0x14204022, 0x0000aaaa,
0x14204022, 0x00000300,
0x14204022, 0x00000000,
0x1a0040ab, 0x00000b14,
0x14200011, 0x00000000,
0x83000015, 0x00000002,
0x04000021, 0x00000000,
0x00000010, 0x00000000,
0x04000421, 0x00000087,
0x00000010, 0x00000000,
0x00000010, 0x00000000,
0x00008015, 0x00000000,
0x0000003e, 0x00000000,
0x00000010, 0x00000000,
0x82000015, 0x00004000,
0x009e8050, 0x00000000,
0x03008015, 0x00000000,
0x86008015, 0x00000000,
0x82000015, 0x00008000,
0x0100001c, 0x00000000,
0x000050a0, 0x0000010c,
0x4e20d011, 0x00006008,
0x1420d012, 0x00004008,
0x0000f090, 0x00007000,
0x0000c8b0, 0x00003000,
0x00004040, 0x00000000,
0x00108015, 0x00000000,
0x00a2c150, 0x00004000,
0x00a400b0, 0x00000014,
0x00000020, 0x00000000,
0x2500400d, 0x00002525,
0x00047220, 0x00003100,
0x00934070, 0x00000000,
0x00000020, 0x00000000,
0x00924460, 0x00000184,
0x2b20c011, 0x00000000,
0x0000c420, 0x00000540,
0x36014018, 0x0000422d,
0x14200011, 0x00000000,
0x00924460, 0x00000183,
0x3200001f, 0x00000034,
0x02ac0015, 0x00000002,
0x00a60110, 0x00000008,
0x42200011, 0x00000000,
0x00924060, 0x00000103,
0x0000001e, 0x00000000,
0x00000020, 0x00000100,
0x0000001e, 0x00000000,
0x00924460, 0x00000086,
0x00004080, 0x00000000,
0x0092c070, 0x00000000,
0x00924060, 0x00000100,
0x0000c890, 0x00005000,
0x00a6c110, 0x00000000,
0x00b0c090, 0x00000012,
0x021c0015, 0x00000000,
0x3200001f, 0x00000034,
0x00924460, 0x00000510,
0x44210011, 0x00000000,
0x42000011, 0x00000000,
0x83000015, 0x00000040,
0x00924460, 0x00000508,
0x45014018, 0x00004545,
0x00808050, 0x00000000,
0x62208012, 0x00000000,
0x82000015, 0x00000800,
0x15200011, 0x00000000,
0x00000010, 0x00000000,
0x00000010, 0x00000000,
0x00000010, 0x00000000,
0x00000010, 0x00000000,
0x00000010, 0x00000000,
0x80000015, 0x0000eea4,
0x81000015, 0x0000005f,
0x00000060, 0x00000000,
0x00004120, 0x00000000,
0x00004a00, 0x00004000,
0x00924460, 0x00000190,
0x5601401a, 0x00005956,
0x14000011, 0x00000000,
0x00934050, 0x00000018,
0x00930050, 0x00000018,
0x3601403a, 0x0000002d,
0x000643a9, 0x00000000,
0x0000c420, 0x00000140,
0x5601401a, 0x00005956,
0x14000011, 0x00000000,
0x00000010, 0x00000000,
0x00000010, 0x00000000,
0x000642a9, 0x00000000,
0x00024420, 0x00000183,
0x5601401a, 0x00005956,
0x82000015, 0x00002000,
0x15200011, 0x00000000,
0x82000015, 0x00000010,
0x15200011, 0x00000000,
0x82000015, 0x00000010,
0x15200011, 0x00000000,
}; /* 104 Tx instructions */
#define FIRMWARE_TX_SIZE 104
#if 0
static const u32 firmware_wol[] = {
0x010003dc, 0x00000000,
0x19000421, 0x00000087,
0x80000015, 0x00001a1a,
0x81000015, 0x00001a1a,
0x1a0040ab, 0x00000b06,
0x15200011, 0x00000000,
0x15204022, 0x0000aaaa,
0x15204022, 0x00000300,
0x15204022, 0x00000000,
0x1a0040ab, 0x00000b15,
0x15200011, 0x00000000,
0x83000015, 0x00000002,
0x04000021, 0x00000000,
0x00000010, 0x00000000,
0x04000421, 0x00000087,
0x00000010, 0x00000000,
0x00000010, 0x00000000,
0x00008015, 0x00000000,
0x0000003e, 0x00000000,
0x00000010, 0x00000000,
0x00000010, 0x00000000,
0x82000015, 0x00004000,
0x82000015, 0x00008000,
0x0000000c, 0x00000000,
0x00000010, 0x00000000,
0x00004080, 0x00000100,
0x1f20c011, 0x00001122,
0x2720f011, 0x00003011,
0x19200071, 0x00000000,
0x1a200051, 0x00000000,
0x00000010, 0x00000000,
0x00000010, 0x00000000,
0x1d2040a4, 0x00003344,
0x1d2040a2, 0x00005566,
0x000040a0, 0x00000100,
0x00108050, 0x00000001,
0x1a208012, 0x00000006,
0x82000015, 0x00008080,
0x010003dc, 0x00000000,
0x1d2040a4, 0x00002233,
0x1d2040a4, 0x00004455,
0x2d208011, 0x00000005,
0x1d2040a4, 0x00006611,
0x00108050, 0x00000001,
0x27200011, 0x00000000,
0x1d2050a4, 0x00006600,
0x82000015, 0x00008080,
0x010003dc, 0x00000000,
0x00000050, 0x00000000,
0x1b200031, 0x00000000,
0x0000001e, 0x00000000,
0x0000001e, 0x00000000,
0x0000001e, 0x00000000,
0x0000001e, 0x00000000,
0x00924460, 0x00000086,
0x00004080, 0x00000000,
0x0092c070, 0x00000000,
0x00924060, 0x00000100,
0x0000c890, 0x00005000,
0x00a6c110, 0x00000000,
0x00b0c090, 0x00000012,
0x021c0015, 0x00000000,
0x3200001f, 0x00000034,
0x00924460, 0x00000510,
0x44210011, 0x00000000,
0x42000011, 0x00000000,
0x83000015, 0x00000040,
0x00924460, 0x00000508,
0x476a0012, 0x00000100,
0x83000015, 0x00000008,
0x16200011, 0x00000000,
0x001e8050, 0x00000000,
0x001e8050, 0x00000000,
0x00808050, 0x00000000,
0x03008015, 0x00000000,
0x62208012, 0x00000000,
0x82000015, 0x00000800,
0x16200011, 0x00000000,
0x80000015, 0x0000eea4,
0x81000015, 0x0000005f,
0x00000020, 0x00000000,
0x00004120, 0x00000000,
0x00004a00, 0x00004000,
0x00924460, 0x00000190,
0x5c01401a, 0x0000595c,
0x15000011, 0x00000000,
0x00934050, 0x00000018,
0x00930050, 0x00000018,
0x3601403a, 0x0000002d,
0x00064029, 0x00000000,
0x0000c420, 0x00000140,
0x5c01401a, 0x0000595c,
0x15000011, 0x00000000,
0x00000010, 0x00000000,
0x00000010, 0x00000000,
0x00064029, 0x00000000,
0x00024420, 0x00000183,
0x5c01401a, 0x0000595c,
0x82000015, 0x00002000,
0x16200011, 0x00000000,
0x82000015, 0x00000010,
0x16200011, 0x00000000,
0x82000015, 0x00000010,
0x16200011, 0x00000000,
}; /* 104 WoL instructions */
#define FIRMWARE_WOL_SIZE 104
#endif

View File

@ -2819,7 +2819,7 @@ void TLan_PhyMonitor( struct net_device *dev )
if (priv->link) {
priv->link = 0;
printk(KERN_DEBUG "TLAN: %s has lost link\n", dev->name);
dev->flags &= ~IFF_RUNNING;
netif_carrier_off(dev);
TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT );
return;
}
@ -2829,7 +2829,7 @@ void TLan_PhyMonitor( struct net_device *dev )
if ((phy_status & MII_GS_LINK) && !priv->link) {
priv->link = 1;
printk(KERN_DEBUG "TLAN: %s has reestablished link\n", dev->name);
dev->flags |= IFF_RUNNING;
netif_carrier_on(dev);
}
/* Setup a new monitor */

View File

@ -888,11 +888,6 @@ static int tok_open(struct net_device *dev)
ti->sap_status = CLOSED; /* CLOSED or OPEN */
ti->open_failure = NO; /* NO or YES */
ti->open_mode = MANUAL; /* MANUAL or AUTOMATIC */
/* 12/2000 not typical Linux, but we can use RUNNING to let us know when
the network has crapped out or cables are disconnected. Useful because
the IFF_UP flag stays up the whole time, until ifconfig tr0 down.
*/
dev->flags &= ~IFF_RUNNING;
ti->sram_phys &= ~1; /* to reverse what we do in tok_close */
/* init the spinlock */
@ -1242,7 +1237,7 @@ irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs)
ti->open_status = CLOSED;
ti->sap_status = CLOSED;
ti->open_mode = AUTOMATIC;
dev->flags &= ~IFF_RUNNING;
netif_carrier_off(dev);
netif_stop_queue(dev);
ti->open_action = RESTART;
outb(0, dev->base_addr + ADAPTRESET);
@ -1323,7 +1318,7 @@ irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs)
break;
}
netif_wake_queue(dev);
dev->flags |= IFF_RUNNING;/*BMS 12/2000*/
netif_carrier_on(dev);
break;
case DIR_INTERRUPT:
case DIR_MOD_OPEN_PARAMS:
@ -1427,7 +1422,7 @@ irqreturn_t tok_interrupt(int irq, void *dev_id, struct pt_regs *regs)
ring_status);
if(ring_status& (REMOVE_RECV|AUTO_REMOVAL|LOBE_FAULT)){
netif_stop_queue(dev);
dev->flags &= ~IFF_RUNNING;/*not typical Linux*/
netif_carrier_off(dev);
DPRINTK("Remove received, or Auto-removal error"
", or Lobe fault\n");
DPRINTK("We'll try to reopen the closed adapter"

View File

@ -2,7 +2,7 @@
* Generic HDLC support routines for Linux
* Frame Relay support
*
* Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
* Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@ -27,6 +27,10 @@
active = open and "link reliable"
exist = new = not used
CCITT LMI: ITU-T Q.933 Annex A
ANSI LMI: ANSI T1.617 Annex D
CISCO LMI: the original, aka "Gang of Four" LMI
*/
#include <linux/module.h>
@ -49,45 +53,41 @@
#undef DEBUG_ECN
#undef DEBUG_LINK
#define MAXLEN_LMISTAT 20 /* max size of status enquiry frame */
#define FR_UI 0x03
#define FR_PAD 0x00
#define PVC_STATE_NEW 0x01
#define PVC_STATE_ACTIVE 0x02
#define PVC_STATE_FECN 0x08 /* FECN condition */
#define PVC_STATE_BECN 0x10 /* BECN condition */
#define NLPID_IP 0xCC
#define NLPID_IPV6 0x8E
#define NLPID_SNAP 0x80
#define NLPID_PAD 0x00
#define NLPID_CCITT_ANSI_LMI 0x08
#define NLPID_CISCO_LMI 0x09
#define FR_UI 0x03
#define FR_PAD 0x00
#define LMI_CCITT_ANSI_DLCI 0 /* LMI DLCI */
#define LMI_CISCO_DLCI 1023
#define NLPID_IP 0xCC
#define NLPID_IPV6 0x8E
#define NLPID_SNAP 0x80
#define NLPID_PAD 0x00
#define NLPID_Q933 0x08
#define LMI_CALLREF 0x00 /* Call Reference */
#define LMI_ANSI_LOCKSHIFT 0x95 /* ANSI locking shift */
#define LMI_ANSI_CISCO_REPTYPE 0x01 /* report type */
#define LMI_CCITT_REPTYPE 0x51
#define LMI_ANSI_CISCO_ALIVE 0x03 /* keep alive */
#define LMI_CCITT_ALIVE 0x53
#define LMI_ANSI_CISCO_PVCSTAT 0x07 /* PVC status */
#define LMI_CCITT_PVCSTAT 0x57
#define LMI_FULLREP 0x00 /* full report */
#define LMI_INTEGRITY 0x01 /* link integrity report */
#define LMI_SINGLE 0x02 /* single PVC report */
#define LMI_DLCI 0 /* LMI DLCI */
#define LMI_PROTO 0x08
#define LMI_CALLREF 0x00 /* Call Reference */
#define LMI_ANSI_LOCKSHIFT 0x95 /* ANSI lockshift */
#define LMI_REPTYPE 1 /* report type */
#define LMI_CCITT_REPTYPE 0x51
#define LMI_ALIVE 3 /* keep alive */
#define LMI_CCITT_ALIVE 0x53
#define LMI_PVCSTAT 7 /* pvc status */
#define LMI_CCITT_PVCSTAT 0x57
#define LMI_FULLREP 0 /* full report */
#define LMI_INTEGRITY 1 /* link integrity report */
#define LMI_SINGLE 2 /* single pvc report */
#define LMI_STATUS_ENQUIRY 0x75
#define LMI_STATUS 0x7D /* reply */
#define LMI_REPT_LEN 1 /* report type element length */
#define LMI_INTEG_LEN 2 /* link integrity element length */
#define LMI_LENGTH 13 /* standard LMI frame length */
#define LMI_ANSI_LENGTH 14
#define LMI_CCITT_CISCO_LENGTH 13 /* LMI frame lengths */
#define LMI_ANSI_LENGTH 14
typedef struct {
@ -223,35 +223,24 @@ static inline struct net_device** get_dev_p(pvc_device *pvc, int type)
}
static inline u16 status_to_dlci(u8 *status, int *active, int *new)
{
*new = (status[2] & 0x08) ? 1 : 0;
*active = (status[2] & 0x02) ? 1 : 0;
return ((status[0] & 0x3F) << 4) | ((status[1] & 0x78) >> 3);
}
static inline void dlci_to_status(u16 dlci, u8 *status, int active, int new)
{
status[0] = (dlci >> 4) & 0x3F;
status[1] = ((dlci << 3) & 0x78) | 0x80;
status[2] = 0x80;
if (new)
status[2] |= 0x08;
else if (active)
status[2] |= 0x02;
}
static int fr_hard_header(struct sk_buff **skb_p, u16 dlci)
{
u16 head_len;
struct sk_buff *skb = *skb_p;
switch (skb->protocol) {
case __constant_ntohs(NLPID_CCITT_ANSI_LMI):
head_len = 4;
skb_push(skb, head_len);
skb->data[3] = NLPID_CCITT_ANSI_LMI;
break;
case __constant_ntohs(NLPID_CISCO_LMI):
head_len = 4;
skb_push(skb, head_len);
skb->data[3] = NLPID_CISCO_LMI;
break;
case __constant_ntohs(ETH_P_IP):
head_len = 4;
skb_push(skb, head_len);
@ -264,12 +253,6 @@ static int fr_hard_header(struct sk_buff **skb_p, u16 dlci)
skb->data[3] = NLPID_IPV6;
break;
case __constant_ntohs(LMI_PROTO):
head_len = 4;
skb_push(skb, head_len);
skb->data[3] = LMI_PROTO;
break;
case __constant_ntohs(ETH_P_802_3):
head_len = 10;
if (skb_headroom(skb) < head_len) {
@ -461,13 +444,14 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
hdlc_device *hdlc = dev_to_hdlc(dev);
struct sk_buff *skb;
pvc_device *pvc = hdlc->state.fr.first_pvc;
int len = (hdlc->state.fr.settings.lmi == LMI_ANSI) ? LMI_ANSI_LENGTH
: LMI_LENGTH;
int stat_len = 3;
int lmi = hdlc->state.fr.settings.lmi;
int dce = hdlc->state.fr.settings.dce;
int len = lmi == LMI_ANSI ? LMI_ANSI_LENGTH : LMI_CCITT_CISCO_LENGTH;
int stat_len = (lmi == LMI_CISCO) ? 6 : 3;
u8 *data;
int i = 0;
if (hdlc->state.fr.settings.dce && fullrep) {
if (dce && fullrep) {
len += hdlc->state.fr.dce_pvc_count * (2 + stat_len);
if (len > HDLC_MAX_MRU) {
printk(KERN_WARNING "%s: Too many PVCs while sending "
@ -484,29 +468,31 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
}
memset(skb->data, 0, len);
skb_reserve(skb, 4);
skb->protocol = __constant_htons(LMI_PROTO);
fr_hard_header(&skb, LMI_DLCI);
if (lmi == LMI_CISCO) {
skb->protocol = __constant_htons(NLPID_CISCO_LMI);
fr_hard_header(&skb, LMI_CISCO_DLCI);
} else {
skb->protocol = __constant_htons(NLPID_CCITT_ANSI_LMI);
fr_hard_header(&skb, LMI_CCITT_ANSI_DLCI);
}
data = skb->tail;
data[i++] = LMI_CALLREF;
data[i++] = hdlc->state.fr.settings.dce
? LMI_STATUS : LMI_STATUS_ENQUIRY;
if (hdlc->state.fr.settings.lmi == LMI_ANSI)
data[i++] = dce ? LMI_STATUS : LMI_STATUS_ENQUIRY;
if (lmi == LMI_ANSI)
data[i++] = LMI_ANSI_LOCKSHIFT;
data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT)
? LMI_CCITT_REPTYPE : LMI_REPTYPE;
data[i++] = lmi == LMI_CCITT ? LMI_CCITT_REPTYPE :
LMI_ANSI_CISCO_REPTYPE;
data[i++] = LMI_REPT_LEN;
data[i++] = fullrep ? LMI_FULLREP : LMI_INTEGRITY;
data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT)
? LMI_CCITT_ALIVE : LMI_ALIVE;
data[i++] = lmi == LMI_CCITT ? LMI_CCITT_ALIVE : LMI_ANSI_CISCO_ALIVE;
data[i++] = LMI_INTEG_LEN;
data[i++] = hdlc->state.fr.txseq =fr_lmi_nextseq(hdlc->state.fr.txseq);
data[i++] = hdlc->state.fr.rxseq;
if (hdlc->state.fr.settings.dce && fullrep) {
if (dce && fullrep) {
while (pvc) {
data[i++] = (hdlc->state.fr.settings.lmi == LMI_CCITT)
? LMI_CCITT_PVCSTAT : LMI_PVCSTAT;
data[i++] = lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT :
LMI_ANSI_CISCO_PVCSTAT;
data[i++] = stat_len;
/* LMI start/restart */
@ -523,8 +509,20 @@ static void fr_lmi_send(struct net_device *dev, int fullrep)
fr_log_dlci_active(pvc);
}
dlci_to_status(pvc->dlci, data + i,
pvc->state.active, pvc->state.new);
if (lmi == LMI_CISCO) {
data[i] = pvc->dlci >> 8;
data[i + 1] = pvc->dlci & 0xFF;
} else {
data[i] = (pvc->dlci >> 4) & 0x3F;
data[i + 1] = ((pvc->dlci << 3) & 0x78) | 0x80;
data[i + 2] = 0x80;
}
if (pvc->state.new)
data[i + 2] |= 0x08;
else if (pvc->state.active)
data[i + 2] |= 0x02;
i += stat_len;
pvc = pvc->next;
}
@ -569,6 +567,8 @@ static void fr_set_link_state(int reliable, struct net_device *dev)
pvc_carrier(0, pvc);
pvc->state.exist = pvc->state.active = 0;
pvc->state.new = 0;
if (!hdlc->state.fr.settings.dce)
pvc->state.bandwidth = 0;
pvc = pvc->next;
}
}
@ -583,11 +583,12 @@ static void fr_timer(unsigned long arg)
int i, cnt = 0, reliable;
u32 list;
if (hdlc->state.fr.settings.dce)
if (hdlc->state.fr.settings.dce) {
reliable = hdlc->state.fr.request &&
time_before(jiffies, hdlc->state.fr.last_poll +
hdlc->state.fr.settings.t392 * HZ);
else {
hdlc->state.fr.request = 0;
} else {
hdlc->state.fr.last_errors <<= 1; /* Shift the list */
if (hdlc->state.fr.request) {
if (hdlc->state.fr.reliable)
@ -634,65 +635,88 @@ static void fr_timer(unsigned long arg)
static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
{
hdlc_device *hdlc = dev_to_hdlc(dev);
int stat_len;
pvc_device *pvc;
int reptype = -1, error, no_ram;
u8 rxseq, txseq;
int i;
int lmi = hdlc->state.fr.settings.lmi;
int dce = hdlc->state.fr.settings.dce;
int stat_len = (lmi == LMI_CISCO) ? 6 : 3, reptype, error, no_ram, i;
if (skb->len < ((hdlc->state.fr.settings.lmi == LMI_ANSI)
? LMI_ANSI_LENGTH : LMI_LENGTH)) {
if (skb->len < (lmi == LMI_ANSI ? LMI_ANSI_LENGTH :
LMI_CCITT_CISCO_LENGTH)) {
printk(KERN_INFO "%s: Short LMI frame\n", dev->name);
return 1;
}
if (skb->data[5] != (!hdlc->state.fr.settings.dce ?
LMI_STATUS : LMI_STATUS_ENQUIRY)) {
printk(KERN_INFO "%s: LMI msgtype=%x, Not LMI status %s\n",
dev->name, skb->data[2],
hdlc->state.fr.settings.dce ? "enquiry" : "reply");
if (skb->data[3] != (lmi == LMI_CISCO ? NLPID_CISCO_LMI :
NLPID_CCITT_ANSI_LMI)) {
printk(KERN_INFO "%s: Received non-LMI frame with LMI"
" DLCI\n", dev->name);
return 1;
}
i = (hdlc->state.fr.settings.lmi == LMI_ANSI) ? 7 : 6;
if (skb->data[4] != LMI_CALLREF) {
printk(KERN_INFO "%s: Invalid LMI Call reference (0x%02X)\n",
dev->name, skb->data[4]);
return 1;
}
if (skb->data[i] !=
((hdlc->state.fr.settings.lmi == LMI_CCITT)
? LMI_CCITT_REPTYPE : LMI_REPTYPE)) {
printk(KERN_INFO "%s: Not a report type=%x\n",
if (skb->data[5] != (dce ? LMI_STATUS_ENQUIRY : LMI_STATUS)) {
printk(KERN_INFO "%s: Invalid LMI Message type (0x%02X)\n",
dev->name, skb->data[5]);
return 1;
}
if (lmi == LMI_ANSI) {
if (skb->data[6] != LMI_ANSI_LOCKSHIFT) {
printk(KERN_INFO "%s: Not ANSI locking shift in LMI"
" message (0x%02X)\n", dev->name, skb->data[6]);
return 1;
}
i = 7;
} else
i = 6;
if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_REPTYPE :
LMI_ANSI_CISCO_REPTYPE)) {
printk(KERN_INFO "%s: Not an LMI Report type IE (0x%02X)\n",
dev->name, skb->data[i]);
return 1;
}
i++;
i++; /* Skip length field */
if (skb->data[++i] != LMI_REPT_LEN) {
printk(KERN_INFO "%s: Invalid LMI Report type IE length"
" (%u)\n", dev->name, skb->data[i]);
return 1;
}
reptype = skb->data[i++];
reptype = skb->data[++i];
if (reptype != LMI_INTEGRITY && reptype != LMI_FULLREP) {
printk(KERN_INFO "%s: Unsupported LMI Report type (0x%02X)\n",
dev->name, reptype);
return 1;
}
if (skb->data[i]!=
((hdlc->state.fr.settings.lmi == LMI_CCITT)
? LMI_CCITT_ALIVE : LMI_ALIVE)) {
printk(KERN_INFO "%s: Unsupported status element=%x\n",
dev->name, skb->data[i]);
if (skb->data[++i] != (lmi == LMI_CCITT ? LMI_CCITT_ALIVE :
LMI_ANSI_CISCO_ALIVE)) {
printk(KERN_INFO "%s: Not an LMI Link integrity verification"
" IE (0x%02X)\n", dev->name, skb->data[i]);
return 1;
}
if (skb->data[++i] != LMI_INTEG_LEN) {
printk(KERN_INFO "%s: Invalid LMI Link integrity verification"
" IE length (%u)\n", dev->name, skb->data[i]);
return 1;
}
i++;
i++; /* Skip length field */
hdlc->state.fr.rxseq = skb->data[i++]; /* TX sequence from peer */
rxseq = skb->data[i++]; /* Should confirm our sequence */
txseq = hdlc->state.fr.txseq;
if (hdlc->state.fr.settings.dce) {
if (reptype != LMI_FULLREP && reptype != LMI_INTEGRITY) {
printk(KERN_INFO "%s: Unsupported report type=%x\n",
dev->name, reptype);
return 1;
}
if (dce)
hdlc->state.fr.last_poll = jiffies;
}
error = 0;
if (!hdlc->state.fr.reliable)
@ -703,7 +727,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
error = 1;
}
if (hdlc->state.fr.settings.dce) {
if (dce) {
if (hdlc->state.fr.fullrep_sent && !error) {
/* Stop sending full report - the last one has been confirmed by DTE */
hdlc->state.fr.fullrep_sent = 0;
@ -725,6 +749,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
hdlc->state.fr.dce_changed = 0;
}
hdlc->state.fr.request = 1; /* got request */
fr_lmi_send(dev, reptype == LMI_FULLREP ? 1 : 0);
return 0;
}
@ -739,7 +764,6 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
if (reptype != LMI_FULLREP)
return 0;
stat_len = 3;
pvc = hdlc->state.fr.first_pvc;
while (pvc) {
@ -750,24 +774,35 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
no_ram = 0;
while (skb->len >= i + 2 + stat_len) {
u16 dlci;
u32 bw;
unsigned int active, new;
if (skb->data[i] != ((hdlc->state.fr.settings.lmi == LMI_CCITT)
? LMI_CCITT_PVCSTAT : LMI_PVCSTAT)) {
printk(KERN_WARNING "%s: Invalid PVCSTAT ID: %x\n",
dev->name, skb->data[i]);
if (skb->data[i] != (lmi == LMI_CCITT ? LMI_CCITT_PVCSTAT :
LMI_ANSI_CISCO_PVCSTAT)) {
printk(KERN_INFO "%s: Not an LMI PVC status IE"
" (0x%02X)\n", dev->name, skb->data[i]);
return 1;
}
if (skb->data[++i] != stat_len) {
printk(KERN_INFO "%s: Invalid LMI PVC status IE length"
" (%u)\n", dev->name, skb->data[i]);
return 1;
}
i++;
if (skb->data[i] != stat_len) {
printk(KERN_WARNING "%s: Invalid PVCSTAT length: %x\n",
dev->name, skb->data[i]);
return 1;
new = !! (skb->data[i + 2] & 0x08);
active = !! (skb->data[i + 2] & 0x02);
if (lmi == LMI_CISCO) {
dlci = (skb->data[i] << 8) | skb->data[i + 1];
bw = (skb->data[i + 3] << 16) |
(skb->data[i + 4] << 8) |
(skb->data[i + 5]);
} else {
dlci = ((skb->data[i] & 0x3F) << 4) |
((skb->data[i + 1] & 0x78) >> 3);
bw = 0;
}
i++;
dlci = status_to_dlci(skb->data + i, &active, &new);
pvc = add_pvc(dev, dlci);
@ -783,9 +818,11 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
pvc->state.deleted = 0;
if (active != pvc->state.active ||
new != pvc->state.new ||
bw != pvc->state.bandwidth ||
!pvc->state.exist) {
pvc->state.new = new;
pvc->state.active = active;
pvc->state.bandwidth = bw;
pvc_carrier(active, pvc);
fr_log_dlci_active(pvc);
}
@ -801,6 +838,7 @@ static int fr_lmi_recv(struct net_device *dev, struct sk_buff *skb)
pvc_carrier(0, pvc);
pvc->state.active = pvc->state.new = 0;
pvc->state.exist = 0;
pvc->state.bandwidth = 0;
fr_log_dlci_active(pvc);
}
pvc = pvc->next;
@ -829,22 +867,15 @@ static int fr_rx(struct sk_buff *skb)
dlci = q922_to_dlci(skb->data);
if (dlci == LMI_DLCI) {
if (hdlc->state.fr.settings.lmi == LMI_NONE)
goto rx_error; /* LMI packet with no LMI? */
if (data[3] == LMI_PROTO) {
if (fr_lmi_recv(ndev, skb))
goto rx_error;
else {
dev_kfree_skb_any(skb);
return NET_RX_SUCCESS;
}
}
printk(KERN_INFO "%s: Received non-LMI frame with LMI DLCI\n",
ndev->name);
goto rx_error;
if ((dlci == LMI_CCITT_ANSI_DLCI &&
(hdlc->state.fr.settings.lmi == LMI_ANSI ||
hdlc->state.fr.settings.lmi == LMI_CCITT)) ||
(dlci == LMI_CISCO_DLCI &&
hdlc->state.fr.settings.lmi == LMI_CISCO)) {
if (fr_lmi_recv(ndev, skb))
goto rx_error;
dev_kfree_skb_any(skb);
return NET_RX_SUCCESS;
}
pvc = find_pvc(hdlc, dlci);
@ -1170,7 +1201,8 @@ int hdlc_fr_ioctl(struct net_device *dev, struct ifreq *ifr)
if ((new_settings.lmi != LMI_NONE &&
new_settings.lmi != LMI_ANSI &&
new_settings.lmi != LMI_CCITT) ||
new_settings.lmi != LMI_CCITT &&
new_settings.lmi != LMI_CISCO) ||
new_settings.t391 < 1 ||
new_settings.t392 < 2 ||
new_settings.n391 < 1 ||

View File

@ -1,7 +1,7 @@
/*
* Generic HDLC support routines for Linux
*
* Copyright (C) 1999 - 2003 Krzysztof Halasa <khc@pm.waw.pl>
* Copyright (C) 1999 - 2005 Krzysztof Halasa <khc@pm.waw.pl>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License
@ -38,7 +38,7 @@
#include <linux/hdlc.h>
static const char* version = "HDLC support module revision 1.17";
static const char* version = "HDLC support module revision 1.18";
#undef DEBUG_LINK
@ -126,10 +126,13 @@ void hdlc_set_carrier(int on, struct net_device *dev)
if (!hdlc->open)
goto carrier_exit;
if (hdlc->carrier)
if (hdlc->carrier) {
printk(KERN_INFO "%s: Carrier detected\n", dev->name);
__hdlc_set_carrier_on(dev);
else
} else {
printk(KERN_INFO "%s: Carrier lost\n", dev->name);
__hdlc_set_carrier_off(dev);
}
carrier_exit:
spin_unlock_irqrestore(&hdlc->state_lock, flags);
@ -157,8 +160,11 @@ int hdlc_open(struct net_device *dev)
spin_lock_irq(&hdlc->state_lock);
if (hdlc->carrier)
if (hdlc->carrier) {
printk(KERN_INFO "%s: Carrier detected\n", dev->name);
__hdlc_set_carrier_on(dev);
} else
printk(KERN_INFO "%s: No carrier\n", dev->name);
hdlc->open = 1;

View File

@ -723,7 +723,7 @@ static void lmc_watchdog (unsigned long data) /*fold00*/
/* lmc_reset (sc); Why reset??? The link can go down ok */
/* Inform the world that link has been lost */
dev->flags &= ~IFF_RUNNING;
netif_carrier_off(dev);
}
/*
@ -736,7 +736,7 @@ static void lmc_watchdog (unsigned long data) /*fold00*/
/* lmc_reset (sc); Again why reset??? */
/* Inform the world that link protocol is back up. */
dev->flags |= IFF_RUNNING;
netif_carrier_on(dev);
/* Now we have to tell the syncppp that we had an outage
* and that it should deal. Calling sppp_reopen here
@ -1168,8 +1168,6 @@ static void lmc_running_reset (struct net_device *dev) /*fold00*/
sc->lmc_media->set_link_status (sc, 1);
sc->lmc_media->set_status (sc, NULL);
//dev->flags |= IFF_RUNNING;
netif_wake_queue(dev);
sc->lmc_txfull = 0;
@ -1233,8 +1231,6 @@ static int lmc_ifdown (struct net_device *dev) /*fold00*/
csr6 &= ~LMC_DEC_SR; /* Turn off the Receive bit */
LMC_CSR_WRITE (sc, csr_command, csr6);
dev->flags &= ~IFF_RUNNING;
sc->stats.rx_missed_errors +=
LMC_CSR_READ (sc, csr_missed_frames) & 0xffff;

View File

@ -492,6 +492,9 @@ EXPORT_SYMBOL(orinoco_debug);
static int suppress_linkstatus; /* = 0 */
module_param(suppress_linkstatus, bool, 0644);
MODULE_PARM_DESC(suppress_linkstatus, "Don't log link status changes");
static int ignore_disconnect; /* = 0 */
module_param(ignore_disconnect, int, 0644);
MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer");
/********************************************************************/
/* Compile time configuration and compatibility stuff */
@ -604,7 +607,6 @@ struct hermes_rx_descriptor {
static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
static int __orinoco_program_rids(struct net_device *dev);
static void __orinoco_set_multicast_list(struct net_device *dev);
static int orinoco_debug_dump_recs(struct net_device *dev);
/********************************************************************/
/* Internal helper functions */
@ -655,7 +657,7 @@ static int orinoco_open(struct net_device *dev)
return err;
}
int orinoco_stop(struct net_device *dev)
static int orinoco_stop(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
int err = 0;
@ -686,7 +688,7 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
struct orinoco_private *priv = netdev_priv(dev);
hermes_t *hw = &priv->hw;
struct iw_statistics *wstats = &priv->wstats;
int err = 0;
int err;
unsigned long flags;
if (! netif_device_present(dev)) {
@ -695,9 +697,21 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
return NULL; /* FIXME: Can we do better than this? */
}
/* If busy, return the old stats. Returning NULL may cause
* the interface to disappear from /proc/net/wireless */
if (orinoco_lock(priv, &flags) != 0)
return NULL; /* FIXME: Erg, we've been signalled, how
* do we propagate this back up? */
return wstats;
/* We can't really wait for the tallies inquiry command to
* complete, so we just use the previous results and trigger
* a new tallies inquiry command for next time - Jean II */
/* FIXME: Really we should wait for the inquiry to come back -
* as it is the stats we give don't make a whole lot of sense.
* Unfortunately, it's not clear how to do that within the
* wireless extensions framework: I think we're in user
* context, but a lock seems to be held by the time we get in
* here so we're not safe to sleep here. */
hermes_inquire(hw, HERMES_INQ_TALLIES);
if (priv->iw_mode == IW_MODE_ADHOC) {
memset(&wstats->qual, 0, sizeof(wstats->qual));
@ -716,25 +730,16 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
err = HERMES_READ_RECORD(hw, USER_BAP,
HERMES_RID_COMMSQUALITY, &cq);
wstats->qual.qual = (int)le16_to_cpu(cq.qual);
wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
wstats->qual.updated = 7;
if (!err) {
wstats->qual.qual = (int)le16_to_cpu(cq.qual);
wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
wstats->qual.updated = 7;
}
}
/* We can't really wait for the tallies inquiry command to
* complete, so we just use the previous results and trigger
* a new tallies inquiry command for next time - Jean II */
/* FIXME: We're in user context (I think?), so we should just
wait for the tallies to come through */
err = hermes_inquire(hw, HERMES_INQ_TALLIES);
orinoco_unlock(priv, &flags);
if (err)
return NULL;
return wstats;
}
@ -1275,9 +1280,10 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
len = sizeof(tallies);
}
/* Read directly the data (no seek) */
hermes_read_words(hw, HERMES_DATA1, (void *) &tallies,
len / 2); /* FIXME: blech! */
err = hermes_bap_pread(hw, IRQ_BAP, &tallies, len,
infofid, sizeof(info));
if (err)
break;
/* Increment our various counters */
/* wstats->discard.nwid - no wrong BSSID stuff */
@ -1307,8 +1313,10 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
break;
}
hermes_read_words(hw, HERMES_DATA1, (void *) &linkstatus,
len / 2);
err = hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len,
infofid, sizeof(info));
if (err)
break;
newstatus = le16_to_cpu(linkstatus.linkstatus);
connected = (newstatus == HERMES_LINKSTATUS_CONNECTED)
@ -1317,7 +1325,7 @@ static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
if (connected)
netif_carrier_on(dev);
else
else if (!ignore_disconnect)
netif_carrier_off(dev);
if (newstatus != priv->last_linkstatus)
@ -1350,6 +1358,8 @@ int __orinoco_up(struct net_device *dev)
struct hermes *hw = &priv->hw;
int err;
netif_carrier_off(dev); /* just to make sure */
err = __orinoco_program_rids(dev);
if (err) {
printk(KERN_ERR "%s: Error %d configuring card\n",
@ -1413,7 +1423,7 @@ int orinoco_reinit_firmware(struct net_device *dev)
return err;
err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
if (err == -EIO) {
if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) {
/* Try workaround for old Symbol firmware bug */
printk(KERN_WARNING "%s: firmware ALLOC bug detected "
"(old Symbol firmware?). Trying to work around... ",
@ -1610,17 +1620,15 @@ static int __orinoco_program_rids(struct net_device *dev)
return err;
}
/* Set the channel/frequency */
if (priv->channel == 0) {
printk(KERN_DEBUG "%s: Channel is 0 in __orinoco_program_rids()\n", dev->name);
if (priv->createibss)
priv->channel = 10;
}
err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFOWNCHANNEL,
priv->channel);
if (err) {
printk(KERN_ERR "%s: Error %d setting channel\n",
dev->name, err);
return err;
if (priv->channel != 0 && priv->iw_mode != IW_MODE_INFRA) {
err = hermes_write_wordrec(hw, USER_BAP,
HERMES_RID_CNFOWNCHANNEL,
priv->channel);
if (err) {
printk(KERN_ERR "%s: Error %d setting channel %d\n",
dev->name, err, priv->channel);
return err;
}
}
if (priv->has_ibss) {
@ -1916,7 +1924,7 @@ static void orinoco_reset(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
struct hermes *hw = &priv->hw;
int err = 0;
int err;
unsigned long flags;
if (orinoco_lock(priv, &flags) != 0)
@ -1938,20 +1946,20 @@ static void orinoco_reset(struct net_device *dev)
orinoco_unlock(priv, &flags);
if (priv->hard_reset)
if (priv->hard_reset) {
err = (*priv->hard_reset)(priv);
if (err) {
printk(KERN_ERR "%s: orinoco_reset: Error %d "
"performing hard reset\n", dev->name, err);
/* FIXME: shutdown of some sort */
return;
if (err) {
printk(KERN_ERR "%s: orinoco_reset: Error %d "
"performing hard reset\n", dev->name, err);
goto disable;
}
}
err = orinoco_reinit_firmware(dev);
if (err) {
printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
dev->name, err);
return;
goto disable;
}
spin_lock_irq(&priv->lock); /* This has to be called from user context */
@ -1972,6 +1980,10 @@ static void orinoco_reset(struct net_device *dev)
spin_unlock_irq(&priv->lock);
return;
disable:
hermes_set_irqmask(hw, 0);
netif_device_detach(dev);
printk(KERN_ERR "%s: Device has been disabled!\n", dev->name);
}
/********************************************************************/
@ -2056,7 +2068,7 @@ irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (events & HERMES_EV_ALLOC)
__orinoco_ev_alloc(dev, hw);
hermes_write_regn(hw, EVACK, events);
hermes_write_regn(hw, EVACK, evstat);
evstat = hermes_read_regn(hw, EVSTAT);
events = evstat & hw->inten;
@ -2215,6 +2227,8 @@ static int determine_firmware(struct net_device *dev)
firmver >= 0x31000;
priv->has_preamble = (firmver >= 0x20000);
priv->ibss_port = 4;
priv->broken_disableport = (firmver == 0x25013) ||
(firmver >= 0x30000 && firmver <= 0x31000);
/* Tested with Intel firmware : 0x20015 => Jean II */
/* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */
break;
@ -2267,7 +2281,7 @@ static int orinoco_init(struct net_device *dev)
priv->nicbuf_size = IEEE802_11_FRAME_LEN + ETH_HLEN;
/* Initialize the firmware */
err = hermes_init(hw);
err = orinoco_reinit_firmware(dev);
if (err != 0) {
printk(KERN_ERR "%s: failed to initialize firmware (err = %d)\n",
dev->name, err);
@ -2400,31 +2414,12 @@ static int orinoco_init(struct net_device *dev)
/* By default use IEEE/IBSS ad-hoc mode if we have it */
priv->prefer_port3 = priv->has_port3 && (! priv->has_ibss);
set_port_type(priv);
priv->channel = 10; /* default channel, more-or-less arbitrary */
priv->channel = 0; /* use firmware default */
priv->promiscuous = 0;
priv->wep_on = 0;
priv->tx_key = 0;
err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
if (err == -EIO) {
/* Try workaround for old Symbol firmware bug */
printk(KERN_WARNING "%s: firmware ALLOC bug detected "
"(old Symbol firmware?). Trying to work around... ",
dev->name);
priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
if (err)
printk("failed!\n");
else
printk("ok.\n");
}
if (err) {
printk("%s: Error %d allocating Tx buffer\n", dev->name, err);
goto out;
}
/* Make the hardware available, as long as it hasn't been
* removed elsewhere (e.g. by PCMCIA hot unplug) */
spin_lock_irq(&priv->lock);
@ -2450,7 +2445,7 @@ struct net_device *alloc_orinocodev(int sizeof_card,
priv = netdev_priv(dev);
priv->ndev = dev;
if (sizeof_card)
priv->card = (void *)((unsigned long)netdev_priv(dev)
priv->card = (void *)((unsigned long)priv
+ sizeof(struct orinoco_private));
else
priv->card = NULL;
@ -2555,6 +2550,7 @@ static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
}
len = le16_to_cpu(essidbuf.len);
BUG_ON(len > IW_ESSID_MAX_SIZE);
memset(buf, 0, IW_ESSID_MAX_SIZE+1);
memcpy(buf, p, len);
@ -2923,13 +2919,14 @@ static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
memset(&essidbuf, 0, sizeof(essidbuf));
if (erq->flags) {
if (erq->length > IW_ESSID_MAX_SIZE)
/* iwconfig includes the NUL in the specified length */
if (erq->length > IW_ESSID_MAX_SIZE+1)
return -E2BIG;
if (copy_from_user(&essidbuf, erq->pointer, erq->length))
return -EFAULT;
essidbuf[erq->length] = '\0';
essidbuf[IW_ESSID_MAX_SIZE] = '\0';
}
if (orinoco_lock(priv, &flags) != 0)
@ -3855,7 +3852,6 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{ SIOCIWFIRSTPRIV + 0x7, 0,
IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
"get_ibssport" },
{ SIOCIWLASTPRIV, 0, 0, "dump_recs" },
};
wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]);
@ -3943,14 +3939,6 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
err = orinoco_ioctl_getibssport(dev, wrq);
break;
case SIOCIWLASTPRIV:
err = orinoco_debug_dump_recs(dev);
if (err)
printk(KERN_ERR "%s: Unable to dump records (%d)\n",
dev->name, err);
break;
default:
err = -EOPNOTSUPP;
}
@ -3964,187 +3952,6 @@ orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
return err;
}
struct {
u16 rid;
char *name;
int displaytype;
#define DISPLAY_WORDS 0
#define DISPLAY_BYTES 1
#define DISPLAY_STRING 2
#define DISPLAY_XSTRING 3
} record_table[] = {
#define DEBUG_REC(name,type) { HERMES_RID_##name, #name, DISPLAY_##type }
DEBUG_REC(CNFPORTTYPE,WORDS),
DEBUG_REC(CNFOWNMACADDR,BYTES),
DEBUG_REC(CNFDESIREDSSID,STRING),
DEBUG_REC(CNFOWNCHANNEL,WORDS),
DEBUG_REC(CNFOWNSSID,STRING),
DEBUG_REC(CNFOWNATIMWINDOW,WORDS),
DEBUG_REC(CNFSYSTEMSCALE,WORDS),
DEBUG_REC(CNFMAXDATALEN,WORDS),
DEBUG_REC(CNFPMENABLED,WORDS),
DEBUG_REC(CNFPMEPS,WORDS),
DEBUG_REC(CNFMULTICASTRECEIVE,WORDS),
DEBUG_REC(CNFMAXSLEEPDURATION,WORDS),
DEBUG_REC(CNFPMHOLDOVERDURATION,WORDS),
DEBUG_REC(CNFOWNNAME,STRING),
DEBUG_REC(CNFOWNDTIMPERIOD,WORDS),
DEBUG_REC(CNFMULTICASTPMBUFFERING,WORDS),
DEBUG_REC(CNFWEPENABLED_AGERE,WORDS),
DEBUG_REC(CNFMANDATORYBSSID_SYMBOL,WORDS),
DEBUG_REC(CNFWEPDEFAULTKEYID,WORDS),
DEBUG_REC(CNFDEFAULTKEY0,BYTES),
DEBUG_REC(CNFDEFAULTKEY1,BYTES),
DEBUG_REC(CNFMWOROBUST_AGERE,WORDS),
DEBUG_REC(CNFDEFAULTKEY2,BYTES),
DEBUG_REC(CNFDEFAULTKEY3,BYTES),
DEBUG_REC(CNFWEPFLAGS_INTERSIL,WORDS),
DEBUG_REC(CNFWEPKEYMAPPINGTABLE,WORDS),
DEBUG_REC(CNFAUTHENTICATION,WORDS),
DEBUG_REC(CNFMAXASSOCSTA,WORDS),
DEBUG_REC(CNFKEYLENGTH_SYMBOL,WORDS),
DEBUG_REC(CNFTXCONTROL,WORDS),
DEBUG_REC(CNFROAMINGMODE,WORDS),
DEBUG_REC(CNFHOSTAUTHENTICATION,WORDS),
DEBUG_REC(CNFRCVCRCERROR,WORDS),
DEBUG_REC(CNFMMLIFE,WORDS),
DEBUG_REC(CNFALTRETRYCOUNT,WORDS),
DEBUG_REC(CNFBEACONINT,WORDS),
DEBUG_REC(CNFAPPCFINFO,WORDS),
DEBUG_REC(CNFSTAPCFINFO,WORDS),
DEBUG_REC(CNFPRIORITYQUSAGE,WORDS),
DEBUG_REC(CNFTIMCTRL,WORDS),
DEBUG_REC(CNFTHIRTY2TALLY,WORDS),
DEBUG_REC(CNFENHSECURITY,WORDS),
DEBUG_REC(CNFGROUPADDRESSES,BYTES),
DEBUG_REC(CNFCREATEIBSS,WORDS),
DEBUG_REC(CNFFRAGMENTATIONTHRESHOLD,WORDS),
DEBUG_REC(CNFRTSTHRESHOLD,WORDS),
DEBUG_REC(CNFTXRATECONTROL,WORDS),
DEBUG_REC(CNFPROMISCUOUSMODE,WORDS),
DEBUG_REC(CNFBASICRATES_SYMBOL,WORDS),
DEBUG_REC(CNFPREAMBLE_SYMBOL,WORDS),
DEBUG_REC(CNFSHORTPREAMBLE,WORDS),
DEBUG_REC(CNFWEPKEYS_AGERE,BYTES),
DEBUG_REC(CNFEXCLUDELONGPREAMBLE,WORDS),
DEBUG_REC(CNFTXKEY_AGERE,WORDS),
DEBUG_REC(CNFAUTHENTICATIONRSPTO,WORDS),
DEBUG_REC(CNFBASICRATES,WORDS),
DEBUG_REC(CNFSUPPORTEDRATES,WORDS),
DEBUG_REC(CNFTICKTIME,WORDS),
DEBUG_REC(CNFSCANREQUEST,WORDS),
DEBUG_REC(CNFJOINREQUEST,WORDS),
DEBUG_REC(CNFAUTHENTICATESTATION,WORDS),
DEBUG_REC(CNFCHANNELINFOREQUEST,WORDS),
DEBUG_REC(MAXLOADTIME,WORDS),
DEBUG_REC(DOWNLOADBUFFER,WORDS),
DEBUG_REC(PRIID,WORDS),
DEBUG_REC(PRISUPRANGE,WORDS),
DEBUG_REC(CFIACTRANGES,WORDS),
DEBUG_REC(NICSERNUM,XSTRING),
DEBUG_REC(NICID,WORDS),
DEBUG_REC(MFISUPRANGE,WORDS),
DEBUG_REC(CFISUPRANGE,WORDS),
DEBUG_REC(CHANNELLIST,WORDS),
DEBUG_REC(REGULATORYDOMAINS,WORDS),
DEBUG_REC(TEMPTYPE,WORDS),
/* DEBUG_REC(CIS,BYTES), */
DEBUG_REC(STAID,WORDS),
DEBUG_REC(CURRENTSSID,STRING),
DEBUG_REC(CURRENTBSSID,BYTES),
DEBUG_REC(COMMSQUALITY,WORDS),
DEBUG_REC(CURRENTTXRATE,WORDS),
DEBUG_REC(CURRENTBEACONINTERVAL,WORDS),
DEBUG_REC(CURRENTSCALETHRESHOLDS,WORDS),
DEBUG_REC(PROTOCOLRSPTIME,WORDS),
DEBUG_REC(SHORTRETRYLIMIT,WORDS),
DEBUG_REC(LONGRETRYLIMIT,WORDS),
DEBUG_REC(MAXTRANSMITLIFETIME,WORDS),
DEBUG_REC(MAXRECEIVELIFETIME,WORDS),
DEBUG_REC(CFPOLLABLE,WORDS),
DEBUG_REC(AUTHENTICATIONALGORITHMS,WORDS),
DEBUG_REC(PRIVACYOPTIONIMPLEMENTED,WORDS),
DEBUG_REC(OWNMACADDR,BYTES),
DEBUG_REC(SCANRESULTSTABLE,WORDS),
DEBUG_REC(PHYTYPE,WORDS),
DEBUG_REC(CURRENTCHANNEL,WORDS),
DEBUG_REC(CURRENTPOWERSTATE,WORDS),
DEBUG_REC(CCAMODE,WORDS),
DEBUG_REC(SUPPORTEDDATARATES,WORDS),
DEBUG_REC(BUILDSEQ,BYTES),
DEBUG_REC(FWID,XSTRING)
#undef DEBUG_REC
};
#define DEBUG_LTV_SIZE 128
static int orinoco_debug_dump_recs(struct net_device *dev)
{
struct orinoco_private *priv = netdev_priv(dev);
hermes_t *hw = &priv->hw;
u8 *val8;
u16 *val16;
int i,j;
u16 length;
int err;
/* I'm not sure: we might have a lock here, so we'd better go
atomic, just in case. */
val8 = kmalloc(DEBUG_LTV_SIZE + 2, GFP_ATOMIC);
if (! val8)
return -ENOMEM;
val16 = (u16 *)val8;
for (i = 0; i < ARRAY_SIZE(record_table); i++) {
u16 rid = record_table[i].rid;
int len;
memset(val8, 0, DEBUG_LTV_SIZE + 2);
err = hermes_read_ltv(hw, USER_BAP, rid, DEBUG_LTV_SIZE,
&length, val8);
if (err) {
DEBUG(0, "Error %d reading RID 0x%04x\n", err, rid);
continue;
}
val16 = (u16 *)val8;
if (length == 0)
continue;
printk(KERN_DEBUG "%-15s (0x%04x): length=%d (%d bytes)\tvalue=",
record_table[i].name,
rid, length, (length-1)*2);
len = min(((int)length-1)*2, DEBUG_LTV_SIZE);
switch (record_table[i].displaytype) {
case DISPLAY_WORDS:
for (j = 0; j < len / 2; j++)
printk("%04X-", le16_to_cpu(val16[j]));
break;
case DISPLAY_BYTES:
default:
for (j = 0; j < len; j++)
printk("%02X:", val8[j]);
break;
case DISPLAY_STRING:
len = min(len, le16_to_cpu(val16[0])+2);
val8[len] = '\0';
printk("\"%s\"", (char *)&val16[1]);
break;
case DISPLAY_XSTRING:
printk("'%s'", (char *)val8);
}
printk("\n");
}
kfree(val8);
return 0;
}
/********************************************************************/
/* Debugging */
@ -4218,7 +4025,6 @@ EXPORT_SYMBOL(free_orinocodev);
EXPORT_SYMBOL(__orinoco_up);
EXPORT_SYMBOL(__orinoco_down);
EXPORT_SYMBOL(orinoco_stop);
EXPORT_SYMBOL(orinoco_reinit_firmware);
EXPORT_SYMBOL(orinoco_interrupt);

View File

@ -119,7 +119,6 @@ extern struct net_device *alloc_orinocodev(int sizeof_card,
extern void free_orinocodev(struct net_device *dev);
extern int __orinoco_up(struct net_device *dev);
extern int __orinoco_down(struct net_device *dev);
extern int orinoco_stop(struct net_device *dev);
extern int orinoco_reinit_firmware(struct net_device *dev);
extern irqreturn_t orinoco_interrupt(int irq, void * dev_id, struct pt_regs *regs);

View File

@ -396,7 +396,7 @@ int pci_register_driver(struct pci_driver *drv)
/* FIXME, once all of the existing PCI drivers have been fixed to set
* the pci shutdown function, this test can go away. */
if (!drv->driver.shutdown)
drv->driver.shutdown = pci_device_shutdown,
drv->driver.shutdown = pci_device_shutdown;
drv->driver.owner = drv->owner;
drv->driver.kobj.ktype = &pci_driver_kobj_type;
pci_init_dynids(&drv->dynids);

View File

@ -97,11 +97,6 @@ MODULE_PARM_DESC(loglevel,
"FC ERP QDIO CIO Config FSF SCSI Other, "
"levels: 0=none 1=normal 2=devel 3=trace");
#ifdef ZFCP_PRINT_FLAGS
u32 flags_dump = 0;
module_param(flags_dump, uint, 0);
#endif
/****************************************************************/
/************** Functions without logging ***********************/
/****************************************************************/
@ -223,13 +218,20 @@ zfcp_in_els_dbf_event(struct zfcp_adapter *adapter, const char *text,
* Parse "device=..." parameter string.
*/
static int __init
zfcp_device_setup(char *str)
zfcp_device_setup(char *devstr)
{
char *tmp;
char *tmp, *str;
size_t len;
if (!str)
if (!devstr)
return 0;
len = strlen(devstr) + 1;
str = (char *) kmalloc(len, GFP_KERNEL);
if (!str)
goto err_out;
memcpy(str, devstr, len);
tmp = strchr(str, ',');
if (!tmp)
goto err_out;
@ -246,10 +248,12 @@ zfcp_device_setup(char *str)
zfcp_data.init_fcp_lun = simple_strtoull(tmp, &tmp, 0);
if (*tmp != '\0')
goto err_out;
kfree(str);
return 1;
err_out:
ZFCP_LOG_NORMAL("Parse error for device parameter string %s\n", str);
kfree(str);
return 0;
}
@ -525,7 +529,7 @@ zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,
out:
if (fsf_req != NULL)
zfcp_fsf_req_cleanup(fsf_req);
zfcp_fsf_req_free(fsf_req);
if ((adapter != NULL) && (retval != -ENXIO))
zfcp_adapter_put(adapter);
@ -1154,7 +1158,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device)
INIT_LIST_HEAD(&adapter->port_remove_lh);
/* initialize list of fsf requests */
rwlock_init(&adapter->fsf_req_list_lock);
spin_lock_init(&adapter->fsf_req_list_lock);
INIT_LIST_HEAD(&adapter->fsf_req_list_head);
/* initialize abort lock */
@ -1239,9 +1243,9 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
dev_set_drvdata(&adapter->ccw_device->dev, NULL);
/* sanity check: no pending FSF requests */
read_lock_irqsave(&adapter->fsf_req_list_lock, flags);
spin_lock_irqsave(&adapter->fsf_req_list_lock, flags);
retval = !list_empty(&adapter->fsf_req_list_head);
read_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
spin_unlock_irqrestore(&adapter->fsf_req_list_lock, flags);
if (retval) {
ZFCP_LOG_NORMAL("bug: adapter %s (%p) still in use, "
"%i requests outstanding\n",
@ -1483,19 +1487,15 @@ zfcp_fsf_incoming_els_rscn(struct zfcp_adapter *adapter,
fcp_rscn_element++;
switch (fcp_rscn_element->addr_format) {
case ZFCP_PORT_ADDRESS:
ZFCP_LOG_FLAGS(1, "ZFCP_PORT_ADDRESS\n");
range_mask = ZFCP_PORTS_RANGE_PORT;
break;
case ZFCP_AREA_ADDRESS:
ZFCP_LOG_FLAGS(1, "ZFCP_AREA_ADDRESS\n");
range_mask = ZFCP_PORTS_RANGE_AREA;
break;
case ZFCP_DOMAIN_ADDRESS:
ZFCP_LOG_FLAGS(1, "ZFCP_DOMAIN_ADDRESS\n");
range_mask = ZFCP_PORTS_RANGE_DOMAIN;
break;
case ZFCP_FABRIC_ADDRESS:
ZFCP_LOG_FLAGS(1, "ZFCP_FABRIC_ADDRESS\n");
range_mask = ZFCP_PORTS_RANGE_FABRIC;
break;
default:
@ -1762,7 +1762,10 @@ static void zfcp_ns_gid_pn_handler(unsigned long data)
ct_iu_req = zfcp_sg_to_address(ct->req);
ct_iu_resp = zfcp_sg_to_address(ct->resp);
if ((ct->status != 0) || zfcp_check_ct_response(&ct_iu_resp->header)) {
if (ct->status != 0)
goto failed;
if (zfcp_check_ct_response(&ct_iu_resp->header)) {
/* FIXME: do we need some specific erp entry points */
atomic_set_mask(ZFCP_STATUS_PORT_INVALID_WWPN, &port->status);
goto failed;

View File

@ -62,9 +62,6 @@
#include <linux/syscalls.h>
#include <linux/ioctl.h>
/************************ DEBUG FLAGS *****************************************/
#define ZFCP_PRINT_FLAGS
/********************* GENERAL DEFINES *********************************/
@ -152,8 +149,10 @@ typedef u32 scsi_lun_t;
#define FSF_QTCB_UNSOLICITED_STATUS 0x6305
#define ZFCP_STATUS_READ_FAILED_THRESHOLD 3
#define ZFCP_STATUS_READS_RECOM FSF_STATUS_READS_RECOM
#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 6
#define ZFCP_EXCHANGE_CONFIG_DATA_SLEEP 50
/* Do 1st retry in 1 second, then double the timeout for each following retry */
#define ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP 100
#define ZFCP_EXCHANGE_CONFIG_DATA_RETRIES 7
/* timeout value for "default timer" for fsf requests */
#define ZFCP_FSF_REQUEST_TIMEOUT (60*HZ);
@ -472,17 +471,6 @@ do { \
ZFCP_LOG(ZFCP_LOG_LEVEL_TRACE, fmt , ##args)
#endif
#ifndef ZFCP_PRINT_FLAGS
# define ZFCP_LOG_FLAGS(level, fmt, args...)
#else
extern u32 flags_dump;
# define ZFCP_LOG_FLAGS(level, fmt, args...) \
do { \
if (level <= flags_dump) \
_ZFCP_LOG(fmt, ##args); \
} while (0)
#endif
/*************** ADAPTER/PORT/UNIT AND FSF_REQ STATUS FLAGS ******************/
/*
@ -502,6 +490,7 @@ do { \
#define ZFCP_STATUS_COMMON_CLOSING 0x02000000
#define ZFCP_STATUS_COMMON_ERP_INUSE 0x01000000
#define ZFCP_STATUS_COMMON_ACCESS_DENIED 0x00800000
#define ZFCP_STATUS_COMMON_ACCESS_BOXED 0x00400000
/* adapter status */
#define ZFCP_STATUS_ADAPTER_QDIOUP 0x00000002
@ -763,6 +752,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long);
/**
* struct zfcp_send_els - used to pass parameters to function zfcp_fsf_send_els
* @adapter: adapter where request is sent from
* @port: port where ELS is destinated (port reference count has to be increased)
* @d_id: destiniation id of port where request is sent to
* @req: scatter-gather list for request
* @resp: scatter-gather list for response
@ -777,6 +767,7 @@ typedef void (*zfcp_send_els_handler_t)(unsigned long);
*/
struct zfcp_send_els {
struct zfcp_adapter *adapter;
struct zfcp_port *port;
fc_id_t d_id;
struct scatterlist *req;
struct scatterlist *resp;
@ -871,7 +862,7 @@ struct zfcp_adapter {
u32 ports; /* number of remote ports */
struct timer_list scsi_er_timer; /* SCSI err recovery watch */
struct list_head fsf_req_list_head; /* head of FSF req list */
rwlock_t fsf_req_list_lock; /* lock for ops on list of
spinlock_t fsf_req_list_lock; /* lock for ops on list of
FSF requests */
atomic_t fsf_reqs_active; /* # active FSF reqs */
struct zfcp_qdio_queue request_queue; /* request queue */

View File

@ -35,7 +35,7 @@
#include "zfcp_ext.h"
static int zfcp_erp_adisc(struct zfcp_adapter *, fc_id_t);
static int zfcp_erp_adisc(struct zfcp_port *);
static void zfcp_erp_adisc_handler(unsigned long);
static int zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *, int);
@ -295,12 +295,12 @@ zfcp_erp_unit_shutdown(struct zfcp_unit *unit, int clear_mask)
/**
* zfcp_erp_adisc - send ADISC ELS command
* @adapter: adapter structure
* @d_id: d_id of port where ADISC is sent to
* @port: port structure
*/
int
zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
zfcp_erp_adisc(struct zfcp_port *port)
{
struct zfcp_adapter *adapter = port->adapter;
struct zfcp_send_els *send_els;
struct zfcp_ls_adisc *adisc;
void *address = NULL;
@ -332,7 +332,8 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
send_els->req_count = send_els->resp_count = 1;
send_els->adapter = adapter;
send_els->d_id = d_id;
send_els->port = port;
send_els->d_id = port->d_id;
send_els->handler = zfcp_erp_adisc_handler;
send_els->handler_data = (unsigned long) send_els;
@ -350,7 +351,7 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
ZFCP_LOG_INFO("ADISC request from s_id 0x%08x to d_id 0x%08x "
"(wwpn=0x%016Lx, wwnn=0x%016Lx, "
"hard_nport_id=0x%08x, nport_id=0x%08x)\n",
adapter->s_id, d_id, (wwn_t) adisc->wwpn,
adapter->s_id, send_els->d_id, (wwn_t) adisc->wwpn,
(wwn_t) adisc->wwnn, adisc->hard_nport_id,
adisc->nport_id);
@ -367,7 +368,7 @@ zfcp_erp_adisc(struct zfcp_adapter *adapter, fc_id_t d_id)
retval = zfcp_fsf_send_els(send_els);
if (retval != 0) {
ZFCP_LOG_NORMAL("error: initiation of Send ELS failed for port "
"0x%08x on adapter %s\n", d_id,
"0x%08x on adapter %s\n", send_els->d_id,
zfcp_get_busid_by_adapter(adapter));
del_timer(send_els->timer);
goto freemem;
@ -411,14 +412,9 @@ zfcp_erp_adisc_handler(unsigned long data)
del_timer(send_els->timer);
adapter = send_els->adapter;
port = send_els->port;
d_id = send_els->d_id;
read_lock(&zfcp_data.config_lock);
port = zfcp_get_port_by_did(send_els->adapter, send_els->d_id);
read_unlock(&zfcp_data.config_lock);
BUG_ON(port == NULL);
/* request rejected or timed out */
if (send_els->status != 0) {
ZFCP_LOG_NORMAL("ELS request rejected/timed out, "
@ -482,7 +478,7 @@ zfcp_test_link(struct zfcp_port *port)
int retval;
zfcp_port_get(port);
retval = zfcp_erp_adisc(port->adapter, port->d_id);
retval = zfcp_erp_adisc(port);
if (retval != 0) {
zfcp_port_put(port);
ZFCP_LOG_NORMAL("reopen needed for port 0x%016Lx "
@ -895,7 +891,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
if (erp_action->fsf_req) {
/* take lock to ensure that request is not being deleted meanwhile */
write_lock(&adapter->fsf_req_list_lock);
spin_lock(&adapter->fsf_req_list_lock);
/* check whether fsf req does still exist */
list_for_each_entry(fsf_req, &adapter->fsf_req_list_head, list)
if (fsf_req == erp_action->fsf_req)
@ -938,7 +934,7 @@ zfcp_erp_strategy_check_fsfreq(struct zfcp_erp_action *erp_action)
*/
erp_action->fsf_req = NULL;
}
write_unlock(&adapter->fsf_req_list_lock);
spin_unlock(&adapter->fsf_req_list_lock);
} else
debug_text_event(adapter->erp_dbf, 3, "a_ca_noreq");
@ -2286,12 +2282,12 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
{
int retval = ZFCP_ERP_SUCCEEDED;
int retries;
int sleep = ZFCP_EXCHANGE_CONFIG_DATA_FIRST_SLEEP;
struct zfcp_adapter *adapter = erp_action->adapter;
atomic_clear_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status);
retries = ZFCP_EXCHANGE_CONFIG_DATA_RETRIES;
do {
for (retries = ZFCP_EXCHANGE_CONFIG_DATA_RETRIES; retries; retries--) {
atomic_clear_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
&adapter->status);
ZFCP_LOG_DEBUG("Doing exchange config data\n");
@ -2329,16 +2325,17 @@ zfcp_erp_adapter_strategy_open_fsf_xconfig(struct zfcp_erp_action *erp_action)
zfcp_get_busid_by_adapter(adapter));
break;
}
if (atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
&adapter->status)) {
ZFCP_LOG_DEBUG("host connection still initialising... "
"waiting and retrying...\n");
/* sleep a little bit before retry */
msleep(jiffies_to_msecs(ZFCP_EXCHANGE_CONFIG_DATA_SLEEP));
}
} while ((retries--) &&
atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
&adapter->status));
if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_HOST_CON_INIT,
&adapter->status))
break;
ZFCP_LOG_DEBUG("host connection still initialising... "
"waiting and retrying...\n");
/* sleep a little bit before retry */
msleep(jiffies_to_msecs(sleep));
sleep *= 2;
}
if (!atomic_test_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK,
&adapter->status)) {
@ -3484,6 +3481,45 @@ zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action)
list_move(&erp_action->list, &erp_action->adapter->erp_ready_head);
}
/*
* function: zfcp_erp_port_boxed
*
* purpose:
*/
void
zfcp_erp_port_boxed(struct zfcp_port *port)
{
struct zfcp_adapter *adapter = port->adapter;
unsigned long flags;
debug_text_event(adapter->erp_dbf, 3, "p_access_boxed");
debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
read_lock_irqsave(&zfcp_data.config_lock, flags);
zfcp_erp_modify_port_status(port,
ZFCP_STATUS_COMMON_ACCESS_BOXED,
ZFCP_SET);
read_unlock_irqrestore(&zfcp_data.config_lock, flags);
zfcp_erp_port_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED);
}
/*
* function: zfcp_erp_unit_boxed
*
* purpose:
*/
void
zfcp_erp_unit_boxed(struct zfcp_unit *unit)
{
struct zfcp_adapter *adapter = unit->port->adapter;
debug_text_event(adapter->erp_dbf, 3, "u_access_boxed");
debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
zfcp_erp_modify_unit_status(unit,
ZFCP_STATUS_COMMON_ACCESS_BOXED,
ZFCP_SET);
zfcp_erp_unit_reopen(unit, ZFCP_STATUS_COMMON_ERP_FAILED);
}
/*
* function: zfcp_erp_port_access_denied
*
@ -3495,11 +3531,13 @@ zfcp_erp_port_access_denied(struct zfcp_port *port)
struct zfcp_adapter *adapter = port->adapter;
unsigned long flags;
debug_text_event(adapter->erp_dbf, 3, "p_access_block");
debug_text_event(adapter->erp_dbf, 3, "p_access_denied");
debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
read_lock_irqsave(&zfcp_data.config_lock, flags);
zfcp_erp_modify_port_status(port, ZFCP_STATUS_COMMON_ERP_FAILED |
ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
zfcp_erp_modify_port_status(port,
ZFCP_STATUS_COMMON_ERP_FAILED |
ZFCP_STATUS_COMMON_ACCESS_DENIED,
ZFCP_SET);
read_unlock_irqrestore(&zfcp_data.config_lock, flags);
}
@ -3513,10 +3551,12 @@ zfcp_erp_unit_access_denied(struct zfcp_unit *unit)
{
struct zfcp_adapter *adapter = unit->port->adapter;
debug_text_event(adapter->erp_dbf, 3, "u_access_block");
debug_text_event(adapter->erp_dbf, 3, "u_access_denied");
debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
zfcp_erp_modify_unit_status(unit, ZFCP_STATUS_COMMON_ERP_FAILED |
ZFCP_STATUS_COMMON_ACCESS_DENIED, ZFCP_SET);
zfcp_erp_modify_unit_status(unit,
ZFCP_STATUS_COMMON_ERP_FAILED |
ZFCP_STATUS_COMMON_ACCESS_DENIED,
ZFCP_SET);
}
/*
@ -3530,7 +3570,7 @@ zfcp_erp_adapter_access_changed(struct zfcp_adapter *adapter)
struct zfcp_port *port;
unsigned long flags;
debug_text_event(adapter->erp_dbf, 3, "a_access_unblock");
debug_text_event(adapter->erp_dbf, 3, "a_access_recover");
debug_event(adapter->erp_dbf, 3, &adapter->name, 8);
read_lock_irqsave(&zfcp_data.config_lock, flags);
@ -3553,10 +3593,12 @@ zfcp_erp_port_access_changed(struct zfcp_port *port)
struct zfcp_adapter *adapter = port->adapter;
struct zfcp_unit *unit;
debug_text_event(adapter->erp_dbf, 3, "p_access_unblock");
debug_text_event(adapter->erp_dbf, 3, "p_access_recover");
debug_event(adapter->erp_dbf, 3, &port->wwpn, sizeof(wwn_t));
if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED,
&port->status) &&
!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
&port->status)) {
if (!atomic_test_mask(ZFCP_STATUS_PORT_WKA, &port->status))
list_for_each_entry(unit, &port->unit_list_head, list)
@ -3583,10 +3625,13 @@ zfcp_erp_unit_access_changed(struct zfcp_unit *unit)
{
struct zfcp_adapter *adapter = unit->port->adapter;
debug_text_event(adapter->erp_dbf, 3, "u_access_unblock");
debug_text_event(adapter->erp_dbf, 3, "u_access_recover");
debug_event(adapter->erp_dbf, 3, &unit->fcp_lun, sizeof(fcp_lun_t));
if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED, &unit->status))
if (!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED,
&unit->status) &&
!atomic_test_mask(ZFCP_STATUS_COMMON_ACCESS_BOXED,
&unit->status))
return;
ZFCP_LOG_NORMAL("reopen of unit 0x%016Lx on port 0x%016Lx "

View File

@ -116,7 +116,7 @@ extern int zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *,
struct timer_list*, int);
extern int zfcp_fsf_req_complete(struct zfcp_fsf_req *);
extern void zfcp_fsf_incoming_els(struct zfcp_fsf_req *);
extern void zfcp_fsf_req_cleanup(struct zfcp_fsf_req *);
extern void zfcp_fsf_req_free(struct zfcp_fsf_req *);
extern struct zfcp_fsf_req *zfcp_fsf_send_fcp_command_task_management(
struct zfcp_adapter *, struct zfcp_unit *, u8, int);
extern struct zfcp_fsf_req *zfcp_fsf_abort_fcp_command(
@ -171,6 +171,8 @@ extern int zfcp_erp_async_handler(struct zfcp_erp_action *, unsigned long);
extern int zfcp_test_link(struct zfcp_port *);
extern void zfcp_erp_port_boxed(struct zfcp_port *);
extern void zfcp_erp_unit_boxed(struct zfcp_unit *);
extern void zfcp_erp_port_access_denied(struct zfcp_port *);
extern void zfcp_erp_unit_access_denied(struct zfcp_unit *);
extern void zfcp_erp_adapter_access_changed(struct zfcp_adapter *);

File diff suppressed because it is too large Load Diff

View File

@ -229,52 +229,14 @@ zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter,
ZFCP_LOG_TRACE("status is"
" QDIO_STATUS_OUTBOUND_INT \n");
}
} // if (ZFCP_LOG_CHECK(ZFCP_LOG_LEVEL_TRACE))
}
if (unlikely(status & QDIO_STATUS_LOOK_FOR_ERROR)) {
retval = -EIO;
ZFCP_LOG_FLAGS(1, "QDIO_STATUS_LOOK_FOR_ERROR \n");
ZFCP_LOG_INFO("QDIO problem occurred (status=0x%x, "
"qdio_error=0x%x, siga_error=0x%x)\n",
status, qdio_error, siga_error);
if (status & QDIO_STATUS_ACTIVATE_CHECK_CONDITION) {
ZFCP_LOG_FLAGS(2,
"QDIO_STATUS_ACTIVATE_CHECK_CONDITION\n");
}
if (status & QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR) {
ZFCP_LOG_FLAGS(2,
"QDIO_STATUS_MORE_THAN_ONE_QDIO_ERROR\n");
}
if (status & QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR) {
ZFCP_LOG_FLAGS(2,
"QDIO_STATUS_MORE_THAN_ONE_SIGA_ERROR\n");
}
if (siga_error & QDIO_SIGA_ERROR_ACCESS_EXCEPTION) {
ZFCP_LOG_FLAGS(2, "QDIO_SIGA_ERROR_ACCESS_EXCEPTION\n");
}
if (siga_error & QDIO_SIGA_ERROR_B_BIT_SET) {
ZFCP_LOG_FLAGS(2, "QDIO_SIGA_ERROR_B_BIT_SET\n");
}
switch (qdio_error) {
case 0:
ZFCP_LOG_FLAGS(3, "QDIO_OK");
break;
case SLSB_P_INPUT_ERROR:
ZFCP_LOG_FLAGS(1, "SLSB_P_INPUT_ERROR\n");
break;
case SLSB_P_OUTPUT_ERROR:
ZFCP_LOG_FLAGS(1, "SLSB_P_OUTPUT_ERROR\n");
break;
default:
ZFCP_LOG_NORMAL("bug: unknown QDIO error 0x%x\n",
qdio_error);
break;
}
/* Restarting IO on the failed adapter from scratch */
debug_text_event(adapter->erp_dbf, 1, "qdio_err");
/*
@ -484,37 +446,37 @@ int
zfcp_qdio_reqid_check(struct zfcp_adapter *adapter, void *sbale_addr)
{
struct zfcp_fsf_req *fsf_req;
int retval = 0;
/* invalid (per convention used in this driver) */
if (unlikely(!sbale_addr)) {
ZFCP_LOG_NORMAL("bug: invalid reqid\n");
retval = -EINVAL;
goto out;
return -EINVAL;
}
/* valid request id and thus (hopefully :) valid fsf_req address */
fsf_req = (struct zfcp_fsf_req *) sbale_addr;
/* serialize with zfcp_fsf_req_dismiss_all */
spin_lock(&adapter->fsf_req_list_lock);
if (list_empty(&adapter->fsf_req_list_head)) {
spin_unlock(&adapter->fsf_req_list_lock);
return 0;
}
list_del(&fsf_req->list);
atomic_dec(&adapter->fsf_reqs_active);
spin_unlock(&adapter->fsf_req_list_lock);
if (unlikely(adapter != fsf_req->adapter)) {
ZFCP_LOG_NORMAL("bug: invalid reqid (fsf_req=%p, "
"fsf_req->adapter=%p, adapter=%p)\n",
fsf_req, fsf_req->adapter, adapter);
retval = -EINVAL;
goto out;
}
ZFCP_LOG_TRACE("fsf_req at %p, QTCB at %p\n", fsf_req, fsf_req->qtcb);
if (likely(fsf_req->qtcb)) {
ZFCP_LOG_TRACE("hex dump of QTCB:\n");
ZFCP_HEX_DUMP(ZFCP_LOG_LEVEL_TRACE, (char *) fsf_req->qtcb,
sizeof(struct fsf_qtcb));
return -EINVAL;
}
/* finish the FSF request */
zfcp_fsf_req_complete(fsf_req);
out:
return retval;
return 0;
}
/**

View File

@ -433,7 +433,7 @@ zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id)
* FAILED - otherwise
*/
int
zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
__zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
{
int retval = SUCCESS;
struct zfcp_fsf_req *new_fsf_req, *old_fsf_req;
@ -575,7 +575,7 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
*(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[0];
dbf_fsf_qual[1] =
*(u64 *) & new_fsf_req->qtcb->header.fsf_status_qual.word[2];
zfcp_fsf_req_cleanup(new_fsf_req);
zfcp_fsf_req_free(new_fsf_req);
#else
retval = zfcp_fsf_req_wait_and_cleanup(new_fsf_req,
ZFCP_UNINTERRUPTIBLE, &status);
@ -611,6 +611,17 @@ zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
return retval;
}
int
zfcp_scsi_eh_abort_handler(struct scsi_cmnd *scpnt)
{
int rc;
struct Scsi_Host *scsi_host = scpnt->device->host;
spin_lock_irq(scsi_host->host_lock);
rc = __zfcp_scsi_eh_abort_handler(scpnt);
spin_unlock_irq(scsi_host->host_lock);
return rc;
}
/*
* function: zfcp_scsi_eh_device_reset_handler
*
@ -625,8 +636,6 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
struct zfcp_unit *unit = (struct zfcp_unit *) scpnt->device->hostdata;
struct Scsi_Host *scsi_host = scpnt->device->host;
spin_unlock_irq(scsi_host->host_lock);
if (!unit) {
ZFCP_LOG_NORMAL("bug: Tried reset for nonexistent unit\n");
retval = SUCCESS;
@ -669,7 +678,6 @@ zfcp_scsi_eh_device_reset_handler(struct scsi_cmnd *scpnt)
retval = SUCCESS;
}
out:
spin_lock_irq(scsi_host->host_lock);
return retval;
}
@ -723,8 +731,6 @@ zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt)
struct zfcp_unit *unit;
struct Scsi_Host *scsi_host = scpnt->device->host;
spin_unlock_irq(scsi_host->host_lock);
unit = (struct zfcp_unit *) scpnt->device->hostdata;
ZFCP_LOG_NORMAL("bus reset because of problems with "
"unit 0x%016Lx\n", unit->fcp_lun);
@ -732,7 +738,6 @@ zfcp_scsi_eh_bus_reset_handler(struct scsi_cmnd *scpnt)
zfcp_erp_wait(unit->port->adapter);
retval = SUCCESS;
spin_lock_irq(scsi_host->host_lock);
return retval;
}
@ -750,8 +755,6 @@ zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
struct zfcp_unit *unit;
struct Scsi_Host *scsi_host = scpnt->device->host;
spin_unlock_irq(scsi_host->host_lock);
unit = (struct zfcp_unit *) scpnt->device->hostdata;
ZFCP_LOG_NORMAL("host reset because of problems with "
"unit 0x%016Lx\n", unit->fcp_lun);
@ -759,7 +762,6 @@ zfcp_scsi_eh_host_reset_handler(struct scsi_cmnd *scpnt)
zfcp_erp_wait(unit->port->adapter);
retval = SUCCESS;
spin_lock_irq(scsi_host->host_lock);
return retval;
}

View File

@ -1695,8 +1695,6 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt)
tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
spin_unlock_irq(tw_dev->host->host_lock);
tw_dev->num_resets++;
printk(KERN_WARNING "3w-9xxx: scsi%d: WARNING: (0x%02X:0x%04X): Unit #%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, TW_DRIVER, 0x2c, SCpnt->device->id, SCpnt->cmnd[0]);
@ -1709,7 +1707,6 @@ static int twa_scsi_eh_reset(struct scsi_cmnd *SCpnt)
retval = SUCCESS;
out:
spin_lock_irq(tw_dev->host->host_lock);
return retval;
} /* End twa_scsi_eh_reset() */

View File

@ -1430,8 +1430,6 @@ static int tw_scsi_eh_reset(struct scsi_cmnd *SCpnt)
tw_dev = (TW_Device_Extension *)SCpnt->device->host->hostdata;
spin_unlock_irq(tw_dev->host->host_lock);
tw_dev->num_resets++;
printk(KERN_WARNING "3w-xxxx: scsi%d: WARNING: Unit #%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, SCpnt->device->id, SCpnt->cmnd[0]);
@ -1444,7 +1442,6 @@ static int tw_scsi_eh_reset(struct scsi_cmnd *SCpnt)
retval = SUCCESS;
out:
spin_lock_irq(tw_dev->host->host_lock);
return retval;
} /* End tw_scsi_eh_reset() */

View File

@ -170,7 +170,6 @@ MODULE_LICENSE("GPL");
STATIC int NCR_700_queuecommand(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *));
STATIC int NCR_700_abort(struct scsi_cmnd * SCpnt);
STATIC int NCR_700_bus_reset(struct scsi_cmnd * SCpnt);
STATIC int NCR_700_dev_reset(struct scsi_cmnd * SCpnt);
STATIC int NCR_700_host_reset(struct scsi_cmnd * SCpnt);
STATIC void NCR_700_chip_setup(struct Scsi_Host *host);
STATIC void NCR_700_chip_reset(struct Scsi_Host *host);
@ -330,7 +329,6 @@ NCR_700_detect(struct scsi_host_template *tpnt,
/* Fill in the missing routines from the host template */
tpnt->queuecommand = NCR_700_queuecommand;
tpnt->eh_abort_handler = NCR_700_abort;
tpnt->eh_device_reset_handler = NCR_700_dev_reset;
tpnt->eh_bus_reset_handler = NCR_700_bus_reset;
tpnt->eh_host_reset_handler = NCR_700_host_reset;
tpnt->can_queue = NCR_700_COMMAND_SLOTS_PER_HOST;
@ -1959,34 +1957,31 @@ NCR_700_bus_reset(struct scsi_cmnd * SCp)
printk(KERN_INFO "scsi%d (%d:%d) New error handler wants BUS reset, cmd %p\n\t",
SCp->device->host->host_no, SCp->device->id, SCp->device->lun, SCp);
scsi_print_command(SCp);
/* In theory, eh_complete should always be null because the
* eh is single threaded, but just in case we're handling a
* reset via sg or something */
while(hostdata->eh_complete != NULL) {
spin_lock_irq(SCp->device->host->host_lock);
while (hostdata->eh_complete != NULL) {
spin_unlock_irq(SCp->device->host->host_lock);
msleep_interruptible(100);
spin_lock_irq(SCp->device->host->host_lock);
}
hostdata->eh_complete = &complete;
NCR_700_internal_bus_reset(SCp->device->host);
spin_unlock_irq(SCp->device->host->host_lock);
wait_for_completion(&complete);
spin_lock_irq(SCp->device->host->host_lock);
hostdata->eh_complete = NULL;
/* Revalidate the transport parameters of the failing device */
if(hostdata->fast)
spi_schedule_dv_device(SCp->device);
return SUCCESS;
}
STATIC int
NCR_700_dev_reset(struct scsi_cmnd * SCp)
{
printk(KERN_INFO "scsi%d (%d:%d) New error handler wants device reset\n\t",
SCp->device->host->host_no, SCp->device->id, SCp->device->lun);
scsi_print_command(SCp);
return FAILED;
spin_unlock_irq(SCp->device->host->host_lock);
return SUCCESS;
}
STATIC int
@ -1996,8 +1991,13 @@ NCR_700_host_reset(struct scsi_cmnd * SCp)
SCp->device->host->host_no, SCp->device->id, SCp->device->lun);
scsi_print_command(SCp);
spin_lock_irq(SCp->device->host->host_lock);
NCR_700_internal_bus_reset(SCp->device->host);
NCR_700_chip_reset(SCp->device->host);
spin_unlock_irq(SCp->device->host->host_lock);
return SUCCESS;
}

View File

@ -2746,9 +2746,15 @@ static int BusLogic_host_reset(struct scsi_cmnd * SCpnt)
unsigned int id = SCpnt->device->id;
struct BusLogic_TargetStatistics *stats = &HostAdapter->TargetStatistics[id];
int rc;
spin_lock_irq(SCpnt->device->host->host_lock);
BusLogic_IncrementErrorCounter(&stats->HostAdapterResetsRequested);
return BusLogic_ResetHostAdapter(HostAdapter, false);
rc = BusLogic_ResetHostAdapter(HostAdapter, false);
spin_unlock_irq(SCpnt->device->host->host_lock);
return rc;
}
/*

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More