Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
bb8abfed
Commit
bb8abfed
authored
May 17, 2004
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Plain Diff
Merge kroah.com:/home/greg/linux/BK/bleed-2.6
into kroah.com:/home/greg/linux/BK/usb-2.6
parents
c7f22f7a
277c7105
Changes
13
Show whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
370 additions
and
4331 deletions
+370
-4331
drivers/net/Kconfig
drivers/net/Kconfig
+0
-10
drivers/net/Makefile
drivers/net/Makefile
+0
-3
drivers/net/fealnx.c
drivers/net/fealnx.c
+272
-197
drivers/net/rcif.h
drivers/net/rcif.h
+0
-292
drivers/net/rclanmtl.c
drivers/net/rclanmtl.c
+0
-2029
drivers/net/rclanmtl.h
drivers/net/rclanmtl.h
+0
-701
drivers/net/rcpci45.c
drivers/net/rcpci45.c
+0
-1049
drivers/scsi/libata-core.c
drivers/scsi/libata-core.c
+14
-28
drivers/scsi/libata-scsi.c
drivers/scsi/libata-scsi.c
+63
-11
drivers/scsi/libata.h
drivers/scsi/libata.h
+0
-2
drivers/scsi/sata_sil.c
drivers/scsi/sata_sil.c
+8
-2
include/linux/ata.h
include/linux/ata.h
+11
-0
include/linux/libata.h
include/linux/libata.h
+2
-7
No files found.
drivers/net/Kconfig
View file @
bb8abfed
...
...
@@ -2487,16 +2487,6 @@ config IPHASE5526
To compile this driver as a module, choose M here: the module
will be called iph5526.
config RCPCI
tristate "Red Creek Hardware VPN (EXPERIMENTAL)"
depends on NETDEVICES && EXPERIMENTAL && PCI && !64BIT
help
This is a driver for hardware which provides a Virtual Private
Network (VPN). Say Y if you have it.
To compile this driver as a module, choose M here: the module
will be called rcpci.
config SHAPER
tristate "Traffic Shaper (EXPERIMENTAL)"
depends on NETDEVICES && EXPERIMENTAL
...
...
drivers/net/Makefile
View file @
bb8abfed
...
...
@@ -2,8 +2,6 @@
# Makefile for the Linux network (ethercard) device drivers.
#
rcpci-objs
:=
rcpci45.o rclanmtl.o
ifeq
($(CONFIG_ISDN_PPP),y)
obj-$(CONFIG_ISDN)
+=
slhc.o
endif
...
...
@@ -32,7 +30,6 @@ obj-$(CONFIG_BMAC) += bmac.o
obj-$(CONFIG_OAKNET)
+=
oaknet.o 8390.o
obj-$(CONFIG_DGRS)
+=
dgrs.o
obj-$(CONFIG_RCPCI)
+=
rcpci.o
obj-$(CONFIG_VORTEX)
+=
3c59x.o
obj-$(CONFIG_TYPHOON)
+=
typhoon.o
obj-$(CONFIG_NE2K_PCI)
+=
ne2k-pci.o 8390.o
...
...
drivers/net/fealnx.c
View file @
bb8abfed
...
...
@@ -84,6 +84,7 @@ static int full_duplex[MAX_UNITS] = { -1, -1, -1, -1, -1, -1, -1, -1 };
#include <linux/mii.h>
#include <linux/ethtool.h>
#include <linux/crc32.h>
#include <linux/delay.h>
#include <asm/processor.h>
/* Processor type for cache alignment. */
#include <asm/bitops.h>
...
...
@@ -233,15 +234,29 @@ enum intr_status_bits {
RxErr
=
0x00000002
,
/* receive error */
};
/* Bits in the NetworkConfig register. */
/* Bits in the NetworkConfig register, W for writing, R for reading */
/* FIXME: some names are invented by me. Marked with (name?) */
/* If you have docs and know bit names, please fix 'em */
enum
rx_mode_bits
{
RxModeMask
=
0xe0
,
PROM
=
0x80
,
/* promiscuous mode */
AB
=
0x40
,
/* accept broadcast */
AM
=
0x20
,
/* accept mutlicast */
ARP
=
0x08
,
/* receive runt pkt */
ALP
=
0x04
,
/* receive long pkt */
SEP
=
0x02
,
/* receive error pkt */
CR_W_ENH
=
0x02000000
,
/* enhanced mode (name?) */
CR_W_FD
=
0x00100000
,
/* full duplex */
CR_W_PS10
=
0x00080000
,
/* 10 mbit */
CR_W_TXEN
=
0x00040000
,
/* tx enable (name?) */
CR_W_PS1000
=
0x00010000
,
/* 1000 mbit */
/* CR_W_RXBURSTMASK= 0x00000e00, Im unsure about this */
CR_W_RXMODEMASK
=
0x000000e0
,
CR_W_PROM
=
0x00000080
,
/* promiscuous mode */
CR_W_AB
=
0x00000040
,
/* accept broadcast */
CR_W_AM
=
0x00000020
,
/* accept mutlicast */
CR_W_ARP
=
0x00000008
,
/* receive runt pkt */
CR_W_ALP
=
0x00000004
,
/* receive long pkt */
CR_W_SEP
=
0x00000002
,
/* receive error pkt */
CR_W_RXEN
=
0x00000001
,
/* rx enable (unicast?) (name?) */
CR_R_TXSTOP
=
0x04000000
,
/* tx stopped (name?) */
CR_R_FD
=
0x00100000
,
/* full duplex detected */
CR_R_PS10
=
0x00080000
,
/* 10 mbit detected */
CR_R_RXSTOP
=
0x00008000
,
/* rx stopped (name?) */
};
/* The Tulip Rx and Tx buffer descriptors. */
...
...
@@ -375,10 +390,7 @@ enum tx_desc_control_bits {
#define LXT1000_Full 0x200
// 89/12/29 add, for phy specific status register, levelone phy, (end)
/* for 3-in-1 case */
#define PS10 0x00080000
#define FD 0x00100000
#define PS1000 0x00010000
/* for 3-in-1 case, BMCRSR register */
#define LinkIsUp2 0x00040000
/* for PHY */
...
...
@@ -400,6 +412,12 @@ struct netdev_private {
/* Media monitoring timer. */
struct
timer_list
timer
;
/* Reset timer */
struct
timer_list
reset_timer
;
int
reset_timer_armed
;
unsigned
long
crvalue_sv
;
unsigned
long
imrvalue_sv
;
/* Frequently used values: keep some adjacent for cache effect. */
int
flags
;
struct
pci_dev
*
pci_dev
;
...
...
@@ -435,49 +453,44 @@ static int netdev_open(struct net_device *dev);
static
void
getlinktype
(
struct
net_device
*
dev
);
static
void
getlinkstatus
(
struct
net_device
*
dev
);
static
void
netdev_timer
(
unsigned
long
data
);
static
void
reset_timer
(
unsigned
long
data
);
static
void
tx_timeout
(
struct
net_device
*
dev
);
static
void
init_ring
(
struct
net_device
*
dev
);
static
int
start_tx
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
);
static
irqreturn_t
intr_handler
(
int
irq
,
void
*
dev_instance
,
struct
pt_regs
*
regs
);
static
int
netdev_rx
(
struct
net_device
*
dev
);
static
void
set_rx_mode
(
struct
net_device
*
dev
);
static
void
__set_rx_mode
(
struct
net_device
*
dev
);
static
struct
net_device_stats
*
get_stats
(
struct
net_device
*
dev
);
static
int
mii_ioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
);
static
struct
ethtool_ops
netdev_ethtool_ops
;
static
int
netdev_close
(
struct
net_device
*
dev
);
static
void
reset_rx_descriptors
(
struct
net_device
*
dev
);
static
void
reset_tx_descriptors
(
struct
net_device
*
dev
);
void
stop_nic_t
x
(
long
ioaddr
,
long
crvalue
)
static
void
stop_nic_r
x
(
long
ioaddr
,
long
crvalue
)
{
writel
(
crvalue
&
(
~
0x40000
),
ioaddr
+
TCRRCR
);
/* wait for tx stop */
{
int
i
=
0
,
delay
=
0x1000
;
while
((
!
(
readl
(
ioaddr
+
TCRRCR
)
&
0x04000000
))
&&
(
i
<
delay
))
{
++
i
;
}
int
delay
=
0x1000
;
writel
(
crvalue
&
~
(
CR_W_RXEN
),
ioaddr
+
TCRRCR
);
while
(
--
delay
)
{
if
(
(
readl
(
ioaddr
+
TCRRCR
)
&
CR_R_RXSTOP
)
==
CR_R_RXSTOP
)
break
;
}
}
void
stop_nic_r
x
(
long
ioaddr
,
long
crvalue
)
static
void
stop_nic_rxt
x
(
long
ioaddr
,
long
crvalue
)
{
writel
(
crvalue
&
(
~
0x1
),
ioaddr
+
TCRRCR
);
/* wait for rx stop */
{
int
i
=
0
,
delay
=
0x1000
;
while
((
!
(
readl
(
ioaddr
+
TCRRCR
)
&
0x00008000
))
&&
(
i
<
delay
))
{
++
i
;
}
int
delay
=
0x1000
;
writel
(
crvalue
&
~
(
CR_W_RXEN
+
CR_W_TXEN
),
ioaddr
+
TCRRCR
);
while
(
--
delay
)
{
if
(
(
readl
(
ioaddr
+
TCRRCR
)
&
(
CR_R_RXSTOP
+
CR_R_TXSTOP
))
==
(
CR_R_RXSTOP
+
CR_R_TXSTOP
)
)
break
;
}
}
static
int
__devinit
fealnx_init_one
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
{
...
...
@@ -495,7 +508,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
#ifndef MODULE
static
int
printed_version
;
if
(
!
printed_version
++
)
printk
(
version
);
printk
(
version
);
#endif
card_idx
++
;
...
...
@@ -622,7 +635,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
np
->
phys
[
0
]
=
32
;
/* 89/6/23 add, (begin) */
/* get phy type */
if
(
readl
(
dev
->
base_
addr
+
PHYIDENTIFIER
)
==
MysonPHYID
)
if
(
readl
(
io
addr
+
PHYIDENTIFIER
)
==
MysonPHYID
)
np
->
PHYType
=
MysonPHY
;
else
np
->
PHYType
=
OtherPHY
;
...
...
@@ -657,7 +670,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
if
(
np
->
flags
==
HAS_MII_XCVR
)
mdio_write
(
dev
,
np
->
phys
[
0
],
MII_ADVERTISE
,
ADVERTISE_FULL
);
else
writel
(
ADVERTISE_FULL
,
dev
->
base_
addr
+
ANARANLPAR
);
writel
(
ADVERTISE_FULL
,
io
addr
+
ANARANLPAR
);
np
->
mii
.
force_media
=
1
;
}
...
...
@@ -669,7 +682,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
dev
->
set_multicast_list
=
&
set_rx_mode
;
dev
->
do_ioctl
=
&
mii_ioctl
;
dev
->
ethtool_ops
=
&
netdev_ethtool_ops
;
dev
->
tx_timeout
=
tx_timeout
;
dev
->
tx_timeout
=
&
tx_timeout
;
dev
->
watchdog_timeo
=
TX_TIMEOUT
;
err
=
register_netdev
(
dev
);
...
...
@@ -699,6 +712,7 @@ static int __devinit fealnx_init_one(struct pci_dev *pdev,
return
err
;
}
static
void
__devexit
fealnx_remove_one
(
struct
pci_dev
*
pdev
)
{
struct
net_device
*
dev
=
pci_get_drvdata
(
pdev
);
...
...
@@ -721,42 +735,6 @@ static void __devexit fealnx_remove_one(struct pci_dev *pdev)
printk
(
KERN_ERR
"fealnx: remove for unknown device
\n
"
);
}
unsigned
int
m80x_read_tick
(
void
)
/* function: Reads the Timer tick count register which decrements by 2 from */
/* 65536 to 0 every 1/36.414 of a second. Each 2 decrements of the *//* count represents 838 nsec's. */
/* input : none. */
/* output : none. */
{
unsigned
char
tmp
;
int
value
;
writeb
((
char
)
0x06
,
0x43
);
// Command 8254 to latch T0's count
// now read the count.
tmp
=
(
unsigned
char
)
readb
(
0x40
);
value
=
((
int
)
tmp
)
<<
8
;
tmp
=
(
unsigned
char
)
readb
(
0x40
);
value
|=
(((
int
)
tmp
)
&
0xff
);
return
(
value
);
}
void
m80x_delay
(
unsigned
int
interval
)
/* function: to wait for a specified time. */
/* input : interval ... the specified time. */
/* output : none. */
{
unsigned
int
interval1
,
interval2
,
i
=
0
;
interval1
=
m80x_read_tick
();
// get initial value
do
{
interval2
=
m80x_read_tick
();
if
(
interval1
<
interval2
)
interval1
=
interval2
;
++
i
;
}
while
(((
interval1
-
interval2
)
<
(
ushort
)
interval
)
&&
(
i
<
65535
));
}
static
ulong
m80x_send_cmd_to_phy
(
long
miiport
,
int
opcode
,
int
phyad
,
int
regad
)
{
...
...
@@ -796,7 +774,7 @@ static ulong m80x_send_cmd_to_phy(long miiport, int opcode, int phyad, int regad
/* high MDC */
miir
|=
MASK_MIIR_MII_MDC
;
writel
(
miir
,
miiport
);
m80x_
delay
(
30
);
u
delay
(
30
);
/* next */
mask
>>=
1
;
...
...
@@ -831,7 +809,7 @@ static int mdio_read(struct net_device *dev, int phyad, int regad)
/* high MDC, and wait */
miir
|=
MASK_MIIR_MII_MDC
;
writel
(
miir
,
miiport
);
m80x_delay
((
int
)
30
);
udelay
(
30
);
/* next */
mask
>>=
1
;
...
...
@@ -873,8 +851,6 @@ static void mdio_write(struct net_device *dev, int phyad, int regad, int data)
/* low MDC */
miir
&=
~
MASK_MIIR_MII_MDC
;
writel
(
miir
,
miiport
);
return
;
}
...
...
@@ -949,7 +925,7 @@ static int netdev_open(struct net_device *dev)
np
->
imrvalue
=
TUNF
|
CNTOVF
|
RBU
|
TI
|
RI
;
if
(
np
->
pci_dev
->
device
==
0x891
)
{
np
->
bcrvalue
|=
0x200
;
/* set PROG bit */
np
->
crvalue
|=
0x02000000
;
/* set enhanced bit */
np
->
crvalue
|=
CR_W_ENH
;
/* set enhanced bit */
np
->
imrvalue
|=
ETI
;
}
writel
(
np
->
bcrvalue
,
ioaddr
+
BCR
);
...
...
@@ -957,7 +933,7 @@ static int netdev_open(struct net_device *dev)
if
(
dev
->
if_port
==
0
)
dev
->
if_port
=
np
->
default_port
;
writel
(
0
,
dev
->
base_
addr
+
RXPDR
);
writel
(
0
,
io
addr
+
RXPDR
);
// 89/9/1 modify,
// np->crvalue = 0x00e40001; /* tx store and forward, tx/rx enable */
np
->
crvalue
|=
0x00e40001
;
/* tx store and forward, tx/rx enable */
...
...
@@ -965,7 +941,7 @@ static int netdev_open(struct net_device *dev)
getlinkstatus
(
dev
);
if
(
np
->
linkok
)
getlinktype
(
dev
);
set_rx_mode
(
dev
);
__
set_rx_mode
(
dev
);
netif_start_queue
(
dev
);
...
...
@@ -985,6 +961,11 @@ static int netdev_open(struct net_device *dev)
/* timer handler */
add_timer
(
&
np
->
timer
);
init_timer
(
&
np
->
reset_timer
);
np
->
reset_timer
.
data
=
(
unsigned
long
)
dev
;
np
->
reset_timer
.
function
=
&
reset_timer
;
np
->
reset_timer_armed
=
0
;
return
0
;
}
...
...
@@ -1005,8 +986,7 @@ static void getlinkstatus(struct net_device *dev)
np
->
linkok
=
1
;
return
;
}
// delay
m80x_delay
(
100
);
udelay
(
100
);
}
}
else
{
for
(
i
=
0
;
i
<
DelayTime
;
++
i
)
{
...
...
@@ -1014,8 +994,7 @@ static void getlinkstatus(struct net_device *dev)
np
->
linkok
=
1
;
return
;
}
// delay
m80x_delay
(
100
);
udelay
(
100
);
}
}
}
...
...
@@ -1026,11 +1005,11 @@ static void getlinktype(struct net_device *dev)
struct
netdev_private
*
np
=
dev
->
priv
;
if
(
np
->
PHYType
==
MysonPHY
)
{
/* 3-in-1 case */
if
(
readl
(
dev
->
base_addr
+
TCRRCR
)
&
FD
)
if
(
readl
(
dev
->
base_addr
+
TCRRCR
)
&
CR_R_
FD
)
np
->
duplexmode
=
2
;
/* full duplex */
else
np
->
duplexmode
=
1
;
/* half duplex */
if
(
readl
(
dev
->
base_addr
+
TCRRCR
)
&
PS10
)
if
(
readl
(
dev
->
base_addr
+
TCRRCR
)
&
CR_R_
PS10
)
np
->
line_speed
=
1
;
/* 10M */
else
np
->
line_speed
=
2
;
/* 100M */
...
...
@@ -1112,19 +1091,18 @@ static void getlinktype(struct net_device *dev)
else
np
->
line_speed
=
1
;
/* 10M */
}
// chage crvalue
// np->crvalue&=(~PS10)&(~FD);
np
->
crvalue
&=
(
~
PS10
)
&
(
~
FD
)
&
(
~
PS1000
);
np
->
crvalue
&=
(
~
CR_W_PS10
)
&
(
~
CR_W_FD
)
&
(
~
CR_W_PS1000
);
if
(
np
->
line_speed
==
1
)
np
->
crvalue
|=
PS10
;
np
->
crvalue
|=
CR_W_
PS10
;
else
if
(
np
->
line_speed
==
3
)
np
->
crvalue
|=
PS1000
;
np
->
crvalue
|=
CR_W_
PS1000
;
if
(
np
->
duplexmode
==
2
)
np
->
crvalue
|=
FD
;
np
->
crvalue
|=
CR_W_
FD
;
}
}
/* Take lock before calling this */
static
void
allocate_rx_buffers
(
struct
net_device
*
dev
)
{
struct
netdev_private
*
np
=
dev
->
priv
;
...
...
@@ -1134,15 +1112,17 @@ static void allocate_rx_buffers(struct net_device *dev)
struct
sk_buff
*
skb
;
skb
=
dev_alloc_skb
(
np
->
rx_buf_sz
);
np
->
lack_rxbuf
->
skbuff
=
skb
;
if
(
skb
==
NULL
)
break
;
/* Better luck next round. */
while
(
np
->
lack_rxbuf
->
skbuff
)
np
->
lack_rxbuf
=
np
->
lack_rxbuf
->
next_desc_logical
;
skb
->
dev
=
dev
;
/* Mark as being used by this device. */
np
->
lack_rxbuf
->
skbuff
=
skb
;
np
->
lack_rxbuf
->
buffer
=
pci_map_single
(
np
->
pci_dev
,
skb
->
tail
,
np
->
rx_buf_sz
,
PCI_DMA_FROMDEVICE
);
np
->
lack_rxbuf
=
np
->
lack_rxbuf
->
next_desc_logical
;
np
->
lack_rxbuf
->
status
=
RXOWN
;
++
np
->
really_rx_count
;
}
}
...
...
@@ -1153,22 +1133,23 @@ static void netdev_timer(unsigned long data)
struct
net_device
*
dev
=
(
struct
net_device
*
)
data
;
struct
netdev_private
*
np
=
dev
->
priv
;
long
ioaddr
=
dev
->
base_addr
;
int
next_tick
=
10
*
HZ
;
int
old_crvalue
=
np
->
crvalue
;
unsigned
int
old_linkok
=
np
->
linkok
;
unsigned
long
flags
;
if
(
debug
)
printk
(
KERN_DEBUG
"%s: Media selection timer tick, status %8.8x "
"config %8.8x.
\n
"
,
dev
->
name
,
readl
(
ioaddr
+
ISR
),
readl
(
ioaddr
+
TCRRCR
));
spin_lock_irqsave
(
&
np
->
lock
,
flags
);
if
(
np
->
flags
==
HAS_MII_XCVR
)
{
getlinkstatus
(
dev
);
if
((
old_linkok
==
0
)
&&
(
np
->
linkok
==
1
))
{
/* we need to detect the media type again */
getlinktype
(
dev
);
if
(
np
->
crvalue
!=
old_crvalue
)
{
stop_nic_tx
(
ioaddr
,
np
->
crvalue
);
stop_nic_rx
(
ioaddr
,
np
->
crvalue
&
(
~
0x40000
));
stop_nic_rxtx
(
ioaddr
,
np
->
crvalue
);
writel
(
np
->
crvalue
,
ioaddr
+
TCRRCR
);
}
}
...
...
@@ -1176,69 +1157,120 @@ static void netdev_timer(unsigned long data)
allocate_rx_buffers
(
dev
);
np
->
timer
.
expires
=
RUN_AT
(
next_tick
);
spin_unlock_irqrestore
(
&
np
->
lock
,
flags
);
np
->
timer
.
expires
=
RUN_AT
(
10
*
HZ
);
add_timer
(
&
np
->
timer
);
}
static
void
tx_timeout
(
struct
net_device
*
dev
)
/* Take lock before calling */
/* Reset chip and disable rx, tx and interrupts */
static
void
reset_and_disable_rxtx
(
struct
net_device
*
dev
)
{
struct
netdev_private
*
np
=
dev
->
priv
;
long
ioaddr
=
dev
->
base_addr
;
int
i
;
printk
(
KERN_WARNING
"%s: Transmit timed out, status %8.8x,"
" resetting...
\n
"
,
dev
->
name
,
readl
(
ioaddr
+
ISR
));
{
printk
(
KERN_DEBUG
" Rx ring %p: "
,
np
->
rx_ring
);
for
(
i
=
0
;
i
<
RX_RING_SIZE
;
i
++
)
printk
(
" %8.8x"
,
(
unsigned
int
)
np
->
rx_ring
[
i
].
status
);
printk
(
"
\n
"
KERN_DEBUG
" Tx ring %p: "
,
np
->
tx_ring
);
for
(
i
=
0
;
i
<
TX_RING_SIZE
;
i
++
)
printk
(
" %4.4x"
,
np
->
tx_ring
[
i
].
status
);
printk
(
"
\n
"
);
}
/* Reinit. Gross */
int
delay
=
51
;
/* Reset the chip's Tx and Rx processes. */
stop_nic_tx
(
ioaddr
,
0
);
reset_rx_descriptors
(
dev
);
stop_nic_rxtx
(
ioaddr
,
0
);
/* Disable interrupts by clearing the interrupt mask. */
writel
(
0
x0000
,
ioaddr
+
IMR
);
writel
(
0
,
ioaddr
+
IMR
);
/* Reset the chip to erase previous misconfiguration. */
writel
(
0x00000001
,
ioaddr
+
BCR
);
/* Ueimor: wait for 50 PCI cycles (and flush posted writes btw).
We surely wait too long (address+data phase). Who cares
? */
for
(
i
=
0
;
i
<
50
;
i
++
)
{
We surely wait too long (address+data phase). Who cares? */
while
(
--
delay
)
{
readl
(
ioaddr
+
BCR
);
rmb
();
}
}
/* Take lock before calling */
/* Restore chip after reset */
static
void
enable_rxtx
(
struct
net_device
*
dev
)
{
struct
netdev_private
*
np
=
dev
->
priv
;
long
ioaddr
=
dev
->
base_addr
;
writel
((
np
->
cur_tx
-
np
->
tx_ring
)
*
sizeof
(
struct
fealnx_desc
)
+
np
->
tx_ring_dma
,
ioaddr
+
TXLBA
);
writel
((
np
->
cur_rx
-
np
->
rx_ring
)
*
sizeof
(
struct
fealnx_desc
)
+
np
->
rx_ring_dma
,
ioaddr
+
RXLBA
);
reset_rx_descriptors
(
dev
);
writel
(
np
->
tx_ring_dma
+
((
char
*
)
np
->
cur_tx
-
(
char
*
)
np
->
tx_ring
),
ioaddr
+
TXLBA
);
writel
(
np
->
rx_ring_dma
+
((
char
*
)
np
->
cur_rx
-
(
char
*
)
np
->
rx_ring
),
ioaddr
+
RXLBA
);
writel
(
np
->
bcrvalue
,
ioaddr
+
BCR
);
writel
(
0
,
dev
->
base_addr
+
RXPDR
);
set_rx_mode
(
dev
);
writel
(
0
,
ioaddr
+
RXPDR
);
__set_rx_mode
(
dev
);
/* changes np->crvalue, writes it into TCRRCR */
/* Clear and Enable interrupts by setting the interrupt mask. */
writel
(
FBE
|
TUNF
|
CNTOVF
|
RBU
|
TI
|
RI
,
ioaddr
+
ISR
);
writel
(
np
->
imrvalue
,
ioaddr
+
IMR
);
writel
(
0
,
dev
->
base_addr
+
TXPDR
);
writel
(
0
,
ioaddr
+
TXPDR
);
}
static
void
reset_timer
(
unsigned
long
data
)
{
struct
net_device
*
dev
=
(
struct
net_device
*
)
data
;
struct
netdev_private
*
np
=
dev
->
priv
;
unsigned
long
flags
;
printk
(
KERN_WARNING
"%s: resetting tx and rx machinery
\n
"
,
dev
->
name
);
spin_lock_irqsave
(
&
np
->
lock
,
flags
);
np
->
crvalue
=
np
->
crvalue_sv
;
np
->
imrvalue
=
np
->
imrvalue_sv
;
reset_and_disable_rxtx
(
dev
);
/* works for me without this:
reset_tx_descriptors(dev); */
enable_rxtx
(
dev
);
netif_start_queue
(
dev
);
/* FIXME: or netif_wake_queue(dev); ? */
np
->
reset_timer_armed
=
0
;
spin_unlock_irqrestore
(
&
np
->
lock
,
flags
);
}
static
void
tx_timeout
(
struct
net_device
*
dev
)
{
struct
netdev_private
*
np
=
dev
->
priv
;
long
ioaddr
=
dev
->
base_addr
;
unsigned
long
flags
;
int
i
;
printk
(
KERN_WARNING
"%s: Transmit timed out, status %8.8x,"
" resetting...
\n
"
,
dev
->
name
,
readl
(
ioaddr
+
ISR
));
{
printk
(
KERN_DEBUG
" Rx ring %p: "
,
np
->
rx_ring
);
for
(
i
=
0
;
i
<
RX_RING_SIZE
;
i
++
)
printk
(
" %8.8x"
,
(
unsigned
int
)
np
->
rx_ring
[
i
].
status
);
printk
(
"
\n
"
KERN_DEBUG
" Tx ring %p: "
,
np
->
tx_ring
);
for
(
i
=
0
;
i
<
TX_RING_SIZE
;
i
++
)
printk
(
" %4.4x"
,
np
->
tx_ring
[
i
].
status
);
printk
(
"
\n
"
);
}
spin_lock_irqsave
(
&
np
->
lock
,
flags
);
reset_and_disable_rxtx
(
dev
);
reset_tx_descriptors
(
dev
);
enable_rxtx
(
dev
);
spin_unlock_irqrestore
(
&
np
->
lock
,
flags
);
dev
->
trans_start
=
jiffies
;
np
->
stats
.
tx_errors
++
;
return
;
netif_wake_queue
(
dev
);
/* or .._start_.. ?? */
}
...
...
@@ -1251,7 +1283,7 @@ static void init_ring(struct net_device *dev)
/* initialize rx variables */
np
->
rx_buf_sz
=
(
dev
->
mtu
<=
1500
?
PKT_BUF_SZ
:
dev
->
mtu
+
32
);
np
->
cur_rx
=
&
np
->
rx_ring
[
0
];
np
->
lack_rxbuf
=
NULL
;
np
->
lack_rxbuf
=
np
->
rx_ring
;
np
->
really_rx_count
=
0
;
/* initial rx descriptors. */
...
...
@@ -1294,6 +1326,7 @@ static void init_ring(struct net_device *dev)
for
(
i
=
0
;
i
<
TX_RING_SIZE
;
i
++
)
{
np
->
tx_ring
[
i
].
status
=
0
;
/* do we need np->tx_ring[i].control = XXX; ?? */
np
->
tx_ring
[
i
].
next_desc
=
np
->
tx_ring_dma
+
(
i
+
1
)
*
sizeof
(
struct
fealnx_desc
);
np
->
tx_ring
[
i
].
next_desc_logical
=
&
np
->
tx_ring
[
i
+
1
];
...
...
@@ -1341,7 +1374,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
np
->
cur_tx_copy
->
control
|=
(
BPT
<<
TBSShift
);
/* buffer size */
/* for the last descriptor */
next
=
(
struct
fealnx
*
)
np
->
cur_tx_copy
.
next_desc_logical
;
next
=
np
->
cur_tx_copy
->
next_desc_logical
;
next
->
skbuff
=
skb
;
next
->
control
=
TXIC
|
TXLD
|
CRCEnable
|
PADEnable
;
next
->
control
|=
(
skb
->
len
<<
PKTSShift
);
/* pkt size */
...
...
@@ -1383,35 +1416,59 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
}
void
free_one_rx_descriptor
(
struct
netdev_private
*
np
)
/* Take lock before calling */
/* Chip probably hosed tx ring. Clean up. */
static
void
reset_tx_descriptors
(
struct
net_device
*
dev
)
{
if
(
np
->
really_rx_count
==
RX_RING_SIZE
)
np
->
cur_rx
->
status
=
RXOWN
;
else
{
np
->
lack_rxbuf
->
skbuff
=
np
->
cur_rx
->
skbuff
;
np
->
lack_rxbuf
->
buffer
=
np
->
cur_rx
->
buffer
;
np
->
lack_rxbuf
->
status
=
RXOWN
;
++
np
->
really_rx_count
;
np
->
lack_rxbuf
=
np
->
lack_rxbuf
->
next_desc_logical
;
struct
netdev_private
*
np
=
dev
->
priv
;
struct
fealnx_desc
*
cur
;
int
i
;
/* initialize tx variables */
np
->
cur_tx
=
&
np
->
tx_ring
[
0
];
np
->
cur_tx_copy
=
&
np
->
tx_ring
[
0
];
np
->
really_tx_count
=
0
;
np
->
free_tx_count
=
TX_RING_SIZE
;
for
(
i
=
0
;
i
<
TX_RING_SIZE
;
i
++
)
{
cur
=
&
np
->
tx_ring
[
i
];
if
(
cur
->
skbuff
)
{
pci_unmap_single
(
np
->
pci_dev
,
cur
->
buffer
,
cur
->
skbuff
->
len
,
PCI_DMA_TODEVICE
);
dev_kfree_skb
(
cur
->
skbuff
);
/* or dev_kfree_skb_irq(cur->skbuff); ? */
cur
->
skbuff
=
NULL
;
}
cur
->
status
=
0
;
cur
->
control
=
0
;
/* needed? */
/* probably not needed. We do it for purely paranoid reasons */
cur
->
next_desc
=
np
->
tx_ring_dma
+
(
i
+
1
)
*
sizeof
(
struct
fealnx_desc
);
cur
->
next_desc_logical
=
&
np
->
tx_ring
[
i
+
1
];
}
np
->
cur_rx
=
np
->
cur_rx
->
next_desc_logical
;
/* for the last tx descriptor */
np
->
tx_ring
[
TX_RING_SIZE
-
1
].
next_desc
=
np
->
tx_ring_dma
;
np
->
tx_ring
[
TX_RING_SIZE
-
1
].
next_desc_logical
=
&
np
->
tx_ring
[
0
];
}
void
reset_rx_descriptors
(
struct
net_device
*
dev
)
/* Take lock and stop rx before calling this */
static
void
reset_rx_descriptors
(
struct
net_device
*
dev
)
{
struct
netdev_private
*
np
=
dev
->
priv
;
stop_nic_rx
(
dev
->
base_addr
,
np
->
crvalue
);
while
(
!
(
np
->
cur_rx
->
status
&
RXOWN
))
free_one_rx_descriptor
(
np
);
struct
fealnx_desc
*
cur
=
np
->
cur_rx
;
int
i
;
allocate_rx_buffers
(
dev
);
writel
(
np
->
rx_ring_dma
+
(
np
->
cur_rx
-
np
->
rx_ring
),
for
(
i
=
0
;
i
<
RX_RING_SIZE
;
i
++
)
{
if
(
cur
->
skbuff
)
cur
->
status
=
RXOWN
;
cur
=
cur
->
next_desc_logical
;
}
writel
(
np
->
rx_ring_dma
+
((
char
*
)
np
->
cur_rx
-
(
char
*
)
np
->
rx_ring
),
dev
->
base_addr
+
RXLBA
);
writel
(
np
->
crvalue
,
dev
->
base_addr
+
TCRRCR
);
}
...
...
@@ -1421,16 +1478,14 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
{
struct
net_device
*
dev
=
(
struct
net_device
*
)
dev_instance
;
struct
netdev_private
*
np
=
dev
->
priv
;
long
ioaddr
,
boguscnt
=
max_interrupt_work
;
long
ioaddr
=
dev
->
base_addr
;
long
boguscnt
=
max_interrupt_work
;
unsigned
int
num_tx
=
0
;
int
handled
=
0
;
spin_lock
(
&
np
->
lock
);
writel
(
0
,
dev
->
base_addr
+
IMR
);
ioaddr
=
dev
->
base_addr
;
np
=
dev
->
priv
;
writel
(
0
,
ioaddr
+
IMR
);
do
{
u32
intr_status
=
readl
(
ioaddr
+
ISR
);
...
...
@@ -1471,8 +1526,11 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
if
(
intr_status
&
(
RI
|
RBU
))
{
if
(
intr_status
&
RI
)
netdev_rx
(
dev
);
else
else
{
stop_nic_rx
(
ioaddr
,
np
->
crvalue
);
reset_rx_descriptors
(
dev
);
writel
(
np
->
crvalue
,
ioaddr
+
TCRRCR
);
}
}
while
(
np
->
really_tx_count
)
{
...
...
@@ -1490,7 +1548,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
if
(
tx_status
&
TXOWN
)
break
;
if
(
!
(
np
->
crvalue
&
0x02000000
))
{
if
(
!
(
np
->
crvalue
&
CR_W_ENH
))
{
if
(
tx_status
&
(
CSL
|
LC
|
EC
|
UDF
|
HF
))
{
np
->
stats
.
tx_errors
++
;
if
(
tx_status
&
EC
)
...
...
@@ -1539,7 +1597,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
netif_wake_queue
(
dev
);
/* read transmit status for enhanced mode only */
if
(
np
->
crvalue
&
0x02000000
)
{
if
(
np
->
crvalue
&
CR_W_ENH
)
{
long
data
;
data
=
readl
(
ioaddr
+
TSR
);
...
...
@@ -1552,6 +1610,20 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
if
(
--
boguscnt
<
0
)
{
printk
(
KERN_WARNING
"%s: Too much work at interrupt, "
"status=0x%4.4x.
\n
"
,
dev
->
name
,
intr_status
);
if
(
!
np
->
reset_timer_armed
)
{
np
->
reset_timer_armed
=
1
;
np
->
reset_timer
.
expires
=
RUN_AT
(
HZ
/
2
);
add_timer
(
&
np
->
reset_timer
);
stop_nic_rxtx
(
ioaddr
,
0
);
netif_stop_queue
(
dev
);
/* or netif_tx_disable(dev); ?? */
/* Prevent other paths from enabling tx,rx,intrs */
np
->
crvalue_sv
=
np
->
crvalue
;
np
->
imrvalue_sv
=
np
->
imrvalue
;
np
->
crvalue
&=
~
(
CR_W_TXEN
|
CR_W_RXEN
);
/* or simply = 0? */
np
->
imrvalue
=
0
;
}
break
;
}
}
while
(
1
);
...
...
@@ -1580,9 +1652,10 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
static
int
netdev_rx
(
struct
net_device
*
dev
)
{
struct
netdev_private
*
np
=
dev
->
priv
;
long
ioaddr
=
dev
->
base_addr
;
/* If EOP is set on the next entry, it's a new packet. Send it up. */
while
(
!
(
np
->
cur_rx
->
status
&
RXOWN
))
{
while
(
!
(
np
->
cur_rx
->
status
&
RXOWN
)
&&
np
->
cur_rx
->
skbuff
)
{
s32
rx_status
=
np
->
cur_rx
->
status
;
if
(
np
->
really_rx_count
==
0
)
...
...
@@ -1634,11 +1707,20 @@ static int netdev_rx(struct net_device *dev)
np
->
stats
.
rx_length_errors
++
;
/* free all rx descriptors related this long pkt */
for
(
i
=
0
;
i
<
desno
;
++
i
)
free_one_rx_descriptor
(
np
);
for
(
i
=
0
;
i
<
desno
;
++
i
)
{
if
(
!
np
->
cur_rx
->
skbuff
)
{
printk
(
KERN_DEBUG
"%s: I'm scared
\n
"
,
dev
->
name
);
break
;
}
np
->
cur_rx
->
status
=
RXOWN
;
np
->
cur_rx
=
np
->
cur_rx
->
next_desc_logical
;
}
continue
;
}
else
{
/* something error, need to reset this chip */
}
else
{
/* rx error, need to reset this chip */
stop_nic_rx
(
ioaddr
,
np
->
crvalue
);
reset_rx_descriptors
(
dev
);
writel
(
np
->
crvalue
,
ioaddr
+
TCRRCR
);
}
break
;
/* exit the while loop */
}
...
...
@@ -1685,8 +1767,6 @@ static int netdev_rx(struct net_device *dev)
PCI_DMA_FROMDEVICE
);
skb_put
(
skb
=
np
->
cur_rx
->
skbuff
,
pkt_len
);
np
->
cur_rx
->
skbuff
=
NULL
;
if
(
np
->
really_rx_count
==
RX_RING_SIZE
)
np
->
lack_rxbuf
=
np
->
cur_rx
;
--
np
->
really_rx_count
;
}
skb
->
protocol
=
eth_type_trans
(
skb
,
dev
);
...
...
@@ -1696,24 +1776,7 @@ static int netdev_rx(struct net_device *dev)
np
->
stats
.
rx_bytes
+=
pkt_len
;
}
if
(
np
->
cur_rx
->
skbuff
==
NULL
)
{
struct
sk_buff
*
skb
;
skb
=
dev_alloc_skb
(
np
->
rx_buf_sz
);
if
(
skb
!=
NULL
)
{
skb
->
dev
=
dev
;
/* Mark as being used by this device. */
np
->
cur_rx
->
buffer
=
pci_map_single
(
np
->
pci_dev
,
skb
->
tail
,
np
->
rx_buf_sz
,
PCI_DMA_FROMDEVICE
);
np
->
cur_rx
->
skbuff
=
skb
;
++
np
->
really_rx_count
;
}
}
if
(
np
->
cur_rx
->
skbuff
!=
NULL
)
free_one_rx_descriptor
(
np
);
np
->
cur_rx
=
np
->
cur_rx
->
next_desc_logical
;
}
/* end of while loop */
/* allocate skb for rx buffers */
...
...
@@ -1737,7 +1800,20 @@ static struct net_device_stats *get_stats(struct net_device *dev)
return
&
np
->
stats
;
}
/* for dev->set_multicast_list */
static
void
set_rx_mode
(
struct
net_device
*
dev
)
{
spinlock_t
*
lp
=
&
((
struct
netdev_private
*
)
dev
->
priv
)
->
lock
;
unsigned
long
flags
;
spin_lock_irqsave
(
lp
,
flags
);
__set_rx_mode
(
dev
);
spin_unlock_irqrestore
(
&
lp
,
flags
);
}
/* Take lock before calling */
static
void
__set_rx_mode
(
struct
net_device
*
dev
)
{
struct
netdev_private
*
np
=
dev
->
priv
;
long
ioaddr
=
dev
->
base_addr
;
...
...
@@ -1748,12 +1824,12 @@ static void set_rx_mode(struct net_device *dev)
/* Unconditionally log net taps. */
printk
(
KERN_NOTICE
"%s: Promiscuous mode enabled.
\n
"
,
dev
->
name
);
memset
(
mc_filter
,
0xff
,
sizeof
(
mc_filter
));
rx_mode
=
PROM
|
AB
|
AM
;
rx_mode
=
CR_W_PROM
|
CR_W_AB
|
CR_W_
AM
;
}
else
if
((
dev
->
mc_count
>
multicast_filter_limit
)
||
(
dev
->
flags
&
IFF_ALLMULTI
))
{
/* Too many to match, or accept all multicasts. */
memset
(
mc_filter
,
0xff
,
sizeof
(
mc_filter
));
rx_mode
=
AB
|
AM
;
rx_mode
=
CR_W_AB
|
CR_W_
AM
;
}
else
{
struct
dev_mc_list
*
mclist
;
int
i
;
...
...
@@ -1765,26 +1841,25 @@ static void set_rx_mode(struct net_device *dev)
bit
=
(
ether_crc
(
ETH_ALEN
,
mclist
->
dmi_addr
)
>>
26
)
^
0x3F
;
mc_filter
[
bit
>>
5
]
|=
(
1
<<
bit
);
}
rx_mode
=
AB
|
AM
;
rx_mode
=
CR_W_AB
|
CR_W_
AM
;
}
stop_nic_tx
(
ioaddr
,
np
->
crvalue
);
stop_nic_rx
(
ioaddr
,
np
->
crvalue
&
(
~
0x40000
));
stop_nic_rxtx
(
ioaddr
,
np
->
crvalue
);
writel
(
mc_filter
[
0
],
ioaddr
+
MAR0
);
writel
(
mc_filter
[
1
],
ioaddr
+
MAR1
);
np
->
crvalue
&=
~
RxModeMask
;
np
->
crvalue
&=
~
CR_W_RXMODEMASK
;
np
->
crvalue
|=
rx_mode
;
writel
(
np
->
crvalue
,
ioaddr
+
TCRRCR
);
}
static
void
netdev_get_drvinfo
(
struct
net_device
*
dev
,
struct
ethtool_drvinfo
*
info
)
static
void
netdev_get_drvinfo
(
struct
net_device
*
dev
,
struct
ethtool_drvinfo
*
info
)
{
struct
netdev_private
*
np
=
dev
->
priv
;
strcpy
(
info
->
driver
,
DRV_NAME
);
strcpy
(
info
->
version
,
DRV_VERSION
);
strcpy
(
info
->
bus_info
,
pci_name
(
np
->
pci_dev
));
strcpy
(
info
->
driver
,
DRV_NAME
);
strcpy
(
info
->
version
,
DRV_VERSION
);
strcpy
(
info
->
bus_info
,
pci_name
(
np
->
pci_dev
));
}
static
int
netdev_get_settings
(
struct
net_device
*
dev
,
struct
ethtool_cmd
*
cmd
)
...
...
@@ -1874,10 +1949,10 @@ static int netdev_close(struct net_device *dev)
writel
(
0x0000
,
ioaddr
+
IMR
);
/* Stop the chip's Tx and Rx processes. */
stop_nic_tx
(
ioaddr
,
0
);
stop_nic_rx
(
ioaddr
,
0
);
stop_nic_rxtx
(
ioaddr
,
0
);
del_timer_sync
(
&
np
->
timer
);
del_timer_sync
(
&
np
->
reset_timer
);
free_irq
(
dev
->
irq
,
dev
);
...
...
@@ -1928,7 +2003,7 @@ static int __init fealnx_init(void)
{
/* when a module, this is printed whether or not devices are found in probe */
#ifdef MODULE
printk
(
version
);
printk
(
version
);
#endif
return
pci_module_init
(
&
fealnx_driver
);
...
...
drivers/net/rcif.h
deleted
100644 → 0
View file @
c7f22f7a
/*
** *************************************************************************
**
**
** R C I F . H
**
**
** RedCreek InterFace include file.
**
** ---------------------------------------------------------------------
** --- Copyright (c) 1998-1999, RedCreek Communications Inc. ---
** --- All rights reserved. ---
** ---------------------------------------------------------------------
**
** File Description:
**
** Header file private ioctl commands.
**
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
** *************************************************************************
*/
#ifndef RCIF_H
#define RCIF_H
/* The following protocol revision # should be incremented every time
a new protocol or new structures are used in this file. */
int
USER_PROTOCOL_REV
=
2
;
/* used to track different protocol revisions */
/* define a single TCB & buffer */
typedef
struct
{
/* a single buffer */
U32
context
;
/* context */
U32
scount
;
/* segment count */
U32
size
;
/* segment size */
U32
addr
;
/* segment physical address */
}
__attribute__
((
packed
))
singleB
,
*
psingleB
;
typedef
struct
{
/* a single TCB */
/*
** +-----------------------+
** | 1 | one buffer in the TCB
** +-----------------------+
** | <user's Context> | user's buffer reference
** +-----------------------+
** | 1 | one segment buffer
** +-----------------------+ _
** | <buffer size> | size \
** +-----------------------+ \ segment descriptor
** | <physical address> | physical address of buffer /
** +-----------------------+ _/
*/
U32
bcount
;
/* buffer count */
singleB
b
;
/* buffer */
}
__attribute__
((
packed
))
singleTCB
,
*
psingleTCB
;
/*
When adding new entries, please add all 5 related changes, since
it helps keep everything consistent:
1) User structure entry
2) User data entry
3) Structure short-cut entry
4) Data short-cut entry
5) Command identifier entry
For Example ("GETSPEED"):
1) struct RCgetspeed_tag { U32 LinkSpeedCode; } RCgetspeed;
2) struct RCgetspeed_tag *getspeed;
3) #define RCUS_GETSPEED data.RCgetspeed;
4) #define RCUD_GETSPEED _RC_user_data.getspeed
5) #define RCUC_GETSPEED 0x02
Notes for the "GETSPEED" entry, above:
1) RCgetspeed - RC{name}
RCgetspeed_tag - RC{name}_tag
LinkSpeedCode - create any structure format desired (not too large,
since memory will be unioned with all other entries)
2) RCgetspeed_tag - RC{name}_tag chosen in #1
getspeed - arbitrary name (ptr to structure in #1)
3) RCUS_GETSPEED - RCUS_{NAME} ("NAME" & "name" do not have to the same)
data.RCgetspeed - data.RC{name} ("RC{name}" from #1)
4) RCUD_GETSPEED - _RC_user_data.getspeed ("getspeed" from #2)
5) RCUC_GETSPEED - unique hex identifier entry.
*/
typedef
struct
RC_user_tag
RCuser_struct
;
/* 1) User structure entry */
struct
RC_user_tag
{
int
cmd
;
union
{
/* GETINFO structure */
struct
RCgetinfo_tag
{
unsigned
long
int
mem_start
;
unsigned
long
int
mem_end
;
unsigned
long
int
base_addr
;
unsigned
char
irq
;
unsigned
char
dma
;
unsigned
char
port
;
}
RCgetinfo
;
/* <---- RCgetinfo */
/* GETSPEED structure */
struct
RCgetspeed_tag
{
U32
LinkSpeedCode
;
}
RCgetspeed
;
/* <---- RCgetspeed */
/* SETSPEED structure */
struct
RCsetspeed_tag
{
U16
LinkSpeedCode
;
}
RCsetspeed
;
/* <---- RCsetspeed */
/* GETPROM structure */
struct
RCgetprom_tag
{
U32
PromMode
;
}
RCgetprom
;
/* <---- RCgetprom */
/* SETPROM structure */
struct
RCsetprom_tag
{
U16
PromMode
;
}
RCsetprom
;
/* <---- RCsetprom */
/* GETBROADCAST structure */
struct
RCgetbroadcast_tag
{
U32
BroadcastMode
;
}
RCgetbroadcast
;
/* <---- RCgetbroadcast */
/* SETBROADCAST structure */
struct
RCsetbroadcast_tag
{
U16
BroadcastMode
;
}
RCsetbroadcast
;
/* <---- RCsetbroadcast */
/* GETFIRMWAREVER structure */
#define FirmStringLen 80
struct
RCgetfwver_tag
{
U8
FirmString
[
FirmStringLen
];
}
RCgetfwver
;
/* <---- RCgetfwver */
/* GETIPANDMASK structure */
struct
RCgetipnmask_tag
{
U32
IpAddr
;
U32
NetMask
;
}
RCgetipandmask
;
/* <---- RCgetipandmask */
/* SETIPANDMASK structure */
struct
RCsetipnmask_tag
{
U32
IpAddr
;
U32
NetMask
;
}
RCsetipandmask
;
/* <---- RCsetipandmask */
/* GETMAC structure */
#define MAC_SIZE 10
struct
RCgetmac_tag
{
U8
mac
[
MAC_SIZE
];
}
RCgetmac
;
/* <---- RCgetmac */
/* SETMAC structure */
struct
RCsetmac_tag
{
U8
mac
[
MAC_SIZE
];
}
RCsetmac
;
/* <---- RCsetmac */
/* GETLINKSTATUS structure */
struct
RCgetlnkstatus_tag
{
U32
ReturnStatus
;
}
RCgetlnkstatus
;
/* <---- RCgetlnkstatus */
/* GETLINKSTATISTICS structure */
struct
RCgetlinkstats_tag
{
RCLINKSTATS
StatsReturn
;
}
RCgetlinkstats
;
/* <---- RCgetlinkstats */
/* DEFAULT structure (when no command was recognized) */
struct
RCdefault_tag
{
int
rc
;
}
RCdefault
;
/* <---- RCdefault */
}
data
;
};
/* struct RC_user_tag { ... } */
/* 2) User data entry */
/* RCUD = RedCreek User Data */
union
RC_user_data_tag
{
/* structure tags used are taken from RC_user_tag structure above */
struct
RCgetinfo_tag
*
getinfo
;
struct
RCgetspeed_tag
*
getspeed
;
struct
RCgetprom_tag
*
getprom
;
struct
RCgetbroadcast_tag
*
getbroadcast
;
struct
RCgetfwver_tag
*
getfwver
;
struct
RCgetipnmask_tag
*
getipandmask
;
struct
RCgetmac_tag
*
getmac
;
struct
RCgetlnkstatus_tag
*
getlinkstatus
;
struct
RCgetlinkstats_tag
*
getlinkstatistics
;
struct
RCdefault_tag
*
rcdefault
;
struct
RCsetspeed_tag
*
setspeed
;
struct
RCsetprom_tag
*
setprom
;
struct
RCsetbroadcast_tag
*
setbroadcast
;
struct
RCsetipnmask_tag
*
setipandmask
;
struct
RCsetmac_tag
*
setmac
;
}
_RC_user_data
;
/* declare as a global, so the defines below will work */
/* 3) Structure short-cut entry */
/* define structure short-cuts *//* structure names are taken from RC_user_tag structure above */
#define RCUS_GETINFO data.RCgetinfo;
#define RCUS_GETSPEED data.RCgetspeed;
#define RCUS_GETPROM data.RCgetprom;
#define RCUS_GETBROADCAST data.RCgetbroadcast;
#define RCUS_GETFWVER data.RCgetfwver;
#define RCUS_GETIPANDMASK data.RCgetipandmask;
#define RCUS_GETMAC data.RCgetmac;
#define RCUS_GETLINKSTATUS data.RCgetlnkstatus;
#define RCUS_GETLINKSTATISTICS data.RCgetlinkstats;
#define RCUS_DEFAULT data.RCdefault;
#define RCUS_SETSPEED data.RCsetspeed;
#define RCUS_SETPROM data.RCsetprom;
#define RCUS_SETBROADCAST data.RCsetbroadcast;
#define RCUS_SETIPANDMASK data.RCsetipandmask;
#define RCUS_SETMAC data.RCsetmac;
/* 4) Data short-cut entry */
/* define data short-cuts *//* pointer names are from RC_user_data_tag union (just below RC_user_tag) */
#define RCUD_GETINFO _RC_user_data.getinfo
#define RCUD_GETSPEED _RC_user_data.getspeed
#define RCUD_GETPROM _RC_user_data.getprom
#define RCUD_GETBROADCAST _RC_user_data.getbroadcast
#define RCUD_GETFWVER _RC_user_data.getfwver
#define RCUD_GETIPANDMASK _RC_user_data.getipandmask
#define RCUD_GETMAC _RC_user_data.getmac
#define RCUD_GETLINKSTATUS _RC_user_data.getlinkstatus
#define RCUD_GETLINKSTATISTICS _RC_user_data.getlinkstatistics
#define RCUD_DEFAULT _RC_user_data.rcdefault
#define RCUD_SETSPEED _RC_user_data.setspeed
#define RCUD_SETPROM _RC_user_data.setprom
#define RCUD_SETBROADCAST _RC_user_data.setbroadcast
#define RCUD_SETIPANDMASK _RC_user_data.setipandmask
#define RCUD_SETMAC _RC_user_data.setmac
/* 5) Command identifier entry */
/* define command identifiers */
#define RCUC_GETINFO 0x01
#define RCUC_GETSPEED 0x02
#define RCUC_GETFWVER 0x03
#define RCUC_GETIPANDMASK 0x04
#define RCUC_GETMAC 0x05
#define RCUC_GETLINKSTATUS 0x06
#define RCUC_GETLINKSTATISTICS 0x07
#define RCUC_GETPROM 0x14
#define RCUC_GETBROADCAST 0x15
#define RCUC_DEFAULT 0xff
#define RCUC_SETSPEED 0x08
#define RCUC_SETIPANDMASK 0x09
#define RCUC_SETMAC 0x0a
#define RCUC_SETPROM 0x16
#define RCUC_SETBROADCAST 0x17
/* define ioctl commands to use, when talking to RC 45/PCI driver */
#define RCU_PROTOCOL_REV SIOCDEVPRIVATE
#define RCU_COMMAND SIOCDEVPRIVATE+1
/*
Intended use for the above defines is shown below (GETINFO, as this example):
RCuser_struct RCuser; // declare RCuser structure
struct ifreq ifr; // declare an interface request structure
RCuser.cmd = RCUC_GETINFO; // set user command to GETINFO
ifr->ifr_data = (caddr_t) &RCuser; // set point to user structure
sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); // get a socket
ioctl(sock, RCU_COMMAND, &ifr); // do ioctl on socket
RCUD_GETINFO = &RCuser.RCUS_GETINFO; // set data pointer for GETINFO
// print results
printf("memory 0x%lx-0x%lx, base address 0x%x, irq 0x%x\n",
RCUD_GETINFO->mem_start, RCUD_GETINFO->mem_end,
RCUD_GETINFO->base_addr, RCUD_GETINFO->irq);
*/
#endif
/* RCIF_H */
drivers/net/rclanmtl.c
deleted
100644 → 0
View file @
c7f22f7a
/*
** *************************************************************************
**
**
** R C L A N M T L . C $Revision: 6 $
**
**
** RedCreek I2O LAN Message Transport Layer program module.
**
** ---------------------------------------------------------------------
** --- Copyright (c) 1997-1999, RedCreek Communications Inc. ---
** --- All rights reserved. ---
** ---------------------------------------------------------------------
**
** File Description:
**
** Host side I2O (Intelligent I/O) LAN message transport layer.
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
** 1998-1999, LAN API was modified and enhanced by Alice Hennessy.
**
** Sometime in 1997, LAN API was written from scratch by Wendell Nichols.
** *************************************************************************
*/
#define DEBUG 1
#define RC_LINUX_MODULE
#include "rclanmtl.h"
/* RedCreek LAN device Target ID */
#define RC_LAN_TARGET_ID 0x10
/* RedCreek's OSM default LAN receive Initiator */
#define DEFAULT_RECV_INIT_CONTEXT 0xA17
/*
** I2O message structures
*/
#define I2O_TID_SZ 12
#define I2O_FUNCTION_SZ 8
/* Transaction Reply Lists (TRL) Control Word structure */
#define I2O_TRL_FLAGS_SINGLE_FIXED_LENGTH 0x00
#define I2O_TRL_FLAGS_SINGLE_VARIABLE_LENGTH 0x40
#define I2O_TRL_FLAGS_MULTIPLE_FIXED_LENGTH 0x80
/* LAN Class specific functions */
#define I2O_LAN_PACKET_SEND 0x3B
#define I2O_LAN_SDU_SEND 0x3D
#define I2O_LAN_RECEIVE_POST 0x3E
#define I2O_LAN_RESET 0x35
#define I2O_LAN_SHUTDOWN 0x37
/* Private Class specfic function */
#define I2O_PRIVATE 0xFF
/* I2O Executive Function Codes. */
#define I2O_EXEC_ADAPTER_ASSIGN 0xB3
#define I2O_EXEC_ADAPTER_READ 0xB2
#define I2O_EXEC_ADAPTER_RELEASE 0xB5
#define I2O_EXEC_BIOS_INFO_SET 0xA5
#define I2O_EXEC_BOOT_DEVICE_SET 0xA7
#define I2O_EXEC_CONFIG_VALIDATE 0xBB
#define I2O_EXEC_CONN_SETUP 0xCA
#define I2O_EXEC_DEVICE_ASSIGN 0xB7
#define I2O_EXEC_DEVICE_RELEASE 0xB9
#define I2O_EXEC_HRT_GET 0xA8
#define I2O_EXEC_IOP_CLEAR 0xBE
#define I2O_EXEC_IOP_CONNECT 0xC9
#define I2O_EXEC_IOP_RESET 0xBD
#define I2O_EXEC_LCT_NOTIFY 0xA2
#define I2O_EXEC_OUTBOUND_INIT 0xA1
#define I2O_EXEC_PATH_ENABLE 0xD3
#define I2O_EXEC_PATH_QUIESCE 0xC5
#define I2O_EXEC_PATH_RESET 0xD7
#define I2O_EXEC_STATIC_MF_CREATE 0xDD
#define I2O_EXEC_STATIC_MF_RELEASE 0xDF
#define I2O_EXEC_STATUS_GET 0xA0
#define I2O_EXEC_SW_DOWNLOAD 0xA9
#define I2O_EXEC_SW_UPLOAD 0xAB
#define I2O_EXEC_SW_REMOVE 0xAD
#define I2O_EXEC_SYS_ENABLE 0xD1
#define I2O_EXEC_SYS_MODIFY 0xC1
#define I2O_EXEC_SYS_QUIESCE 0xC3
#define I2O_EXEC_SYS_TAB_SET 0xA3
/* Init Outbound Q status */
#define I2O_EXEC_OUTBOUND_INIT_IN_PROGRESS 0x01
#define I2O_EXEC_OUTBOUND_INIT_REJECTED 0x02
#define I2O_EXEC_OUTBOUND_INIT_FAILED 0x03
#define I2O_EXEC_OUTBOUND_INIT_COMPLETE 0x04
#define I2O_UTIL_NOP 0x00
/* I2O Get Status State values */
#define I2O_IOP_STATE_INITIALIZING 0x01
#define I2O_IOP_STATE_RESET 0x02
#define I2O_IOP_STATE_HOLD 0x04
#define I2O_IOP_STATE_READY 0x05
#define I2O_IOP_STATE_OPERATIONAL 0x08
#define I2O_IOP_STATE_FAILED 0x10
#define I2O_IOP_STATE_FAULTED 0x11
/* Defines for Request Status Codes: Table 3-1 Reply Status Codes. */
#define I2O_REPLY_STATUS_SUCCESS 0x00
#define I2O_REPLY_STATUS_ABORT_DIRTY 0x01
#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02
#define I2O_REPLY_STATUS_ABORT_PARTIAL_TRANSFER 0x03
#define I2O_REPLY_STATUS_ERROR_DIRTY 0x04
#define I2O_REPLY_STATUS_ERROR_NO_DATA_TRANSFER 0x05
#define I2O_REPLY_STATUS_ERROR_PARTIAL_TRANSFER 0x06
#define I2O_REPLY_STATUS_PROCESS_ABORT_DIRTY 0x07
#define I2O_REPLY_STATUS_PROCESS_ABORT_NO_DATA_TRANSFER 0x08
#define I2O_REPLY_STATUS_PROCESS_ABORT_PARTIAL_TRANSFER 0x09
#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0A
#define I2O_REPLY_STATUS_PROGRESS_REPORT 0x80
/* DetailedStatusCode defines for ALL messages: Table 3-2 Detailed Status Codes.*/
#define I2O_DETAIL_STATUS_SUCCESS 0x0000
#define I2O_DETAIL_STATUS_BAD_KEY 0x0001
#define I2O_DETAIL_STATUS_CHAIN_BUFFER_TOO_LARGE 0x0002
#define I2O_DETAIL_STATUS_DEVICE_BUSY 0x0003
#define I2O_DETAIL_STATUS_DEVICE_LOCKED 0x0004
#define I2O_DETAIL_STATUS_DEVICE_NOT_AVAILABLE 0x0005
#define I2O_DETAIL_STATUS_DEVICE_RESET 0x0006
#define I2O_DETAIL_STATUS_INAPPROPRIATE_FUNCTION 0x0007
#define I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_HARD 0x0008
#define I2O_DETAIL_STATUS_INSUFFICIENT_RESOURCE_SOFT 0x0009
#define I2O_DETAIL_STATUS_INVALID_INITIATOR_ADDRESS 0x000A
#define I2O_DETAIL_STATUS_INVALID_MESSAGE_FLAGS 0x000B
#define I2O_DETAIL_STATUS_INVALID_OFFSET 0x000C
#define I2O_DETAIL_STATUS_INVALID_PARAMETER 0x000D
#define I2O_DETAIL_STATUS_INVALID_REQUEST 0x000E
#define I2O_DETAIL_STATUS_INVALID_TARGET_ADDRESS 0x000F
#define I2O_DETAIL_STATUS_MESSAGE_TOO_LARGE 0x0010
#define I2O_DETAIL_STATUS_MESSAGE_TOO_SMALL 0x0011
#define I2O_DETAIL_STATUS_MISSING_PARAMETER 0x0012
#define I2O_DETAIL_STATUS_NO_SUCH_PAGE 0x0013
#define I2O_DETAIL_STATUS_REPLY_BUFFER_FULL 0x0014
#define I2O_DETAIL_STATUS_TCL_ERROR 0x0015
#define I2O_DETAIL_STATUS_TIMEOUT 0x0016
#define I2O_DETAIL_STATUS_UNKNOWN_ERROR 0x0017
#define I2O_DETAIL_STATUS_UNKNOWN_FUNCTION 0x0018
#define I2O_DETAIL_STATUS_UNSUPPORTED_FUNCTION 0x0019
#define I2O_DETAIL_STATUS_UNSUPPORTED_VERSION 0x001A
/* I2O msg header defines for VersionOffset */
#define I2OMSGVER_1_5 0x0001
#define SGL_OFFSET_0 I2OMSGVER_1_5
#define SGL_OFFSET_4 (0x0040 | I2OMSGVER_1_5)
#define TRL_OFFSET_5 (0x0050 | I2OMSGVER_1_5)
#define TRL_OFFSET_6 (0x0060 | I2OMSGVER_1_5)
/* I2O msg header defines for MsgFlags */
#define MSG_STATIC 0x0100
#define MSG_64BIT_CNTXT 0x0200
#define MSG_MULTI_TRANS 0x1000
#define MSG_FAIL 0x2000
#define MSG_LAST 0x4000
#define MSG_REPLY 0x8000
/* normal LAN request message MsgFlags and VersionOffset (0x1041) */
#define LAN_MSG_REQST (MSG_MULTI_TRANS | SGL_OFFSET_4)
/* minimum size msg */
#define THREE_WORD_MSG_SIZE 0x00030000
#define FOUR_WORD_MSG_SIZE 0x00040000
#define FIVE_WORD_MSG_SIZE 0x00050000
#define SIX_WORD_MSG_SIZE 0x00060000
#define SEVEN_WORD_MSG_SIZE 0x00070000
#define EIGHT_WORD_MSG_SIZE 0x00080000
#define NINE_WORD_MSG_SIZE 0x00090000
/* Special TID Assignments */
#define I2O_IOP_TID 0
#define I2O_HOST_TID 0xB91
/* RedCreek I2O private message codes */
#define RC_PRIVATE_GET_MAC_ADDR 0x0001
/**/
/* OBSOLETE */
#define RC_PRIVATE_SET_MAC_ADDR 0x0002
#define RC_PRIVATE_GET_NIC_STATS 0x0003
#define RC_PRIVATE_GET_LINK_STATUS 0x0004
#define RC_PRIVATE_SET_LINK_SPEED 0x0005
#define RC_PRIVATE_SET_IP_AND_MASK 0x0006
/* #define RC_PRIVATE_GET_IP_AND_MASK 0x0007 *//* OBSOLETE */
#define RC_PRIVATE_GET_LINK_SPEED 0x0008
#define RC_PRIVATE_GET_FIRMWARE_REV 0x0009
/* #define RC_PRIVATE_GET_MAC_ADDR 0x000A */
#define RC_PRIVATE_GET_IP_AND_MASK 0x000B
#define RC_PRIVATE_DEBUG_MSG 0x000C
#define RC_PRIVATE_REPORT_DRIVER_CAPABILITY 0x000D
#define RC_PRIVATE_SET_PROMISCUOUS_MODE 0x000e
#define RC_PRIVATE_GET_PROMISCUOUS_MODE 0x000f
#define RC_PRIVATE_SET_BROADCAST_MODE 0x0010
#define RC_PRIVATE_GET_BROADCAST_MODE 0x0011
#define RC_PRIVATE_REBOOT 0x00FF
/* I2O message header */
typedef
struct
_I2O_MESSAGE_FRAME
{
U8
VersionOffset
;
U8
MsgFlags
;
U16
MessageSize
;
BF
TargetAddress
:
I2O_TID_SZ
;
BF
InitiatorAddress
:
I2O_TID_SZ
;
BF
Function
:
I2O_FUNCTION_SZ
;
U32
InitiatorContext
;
/* SGL[] */
}
I2O_MESSAGE_FRAME
,
*
PI2O_MESSAGE_FRAME
;
/* assumed a 16K minus 256 byte space for outbound queue message frames */
#define MSG_FRAME_SIZE 512
#define NMBR_MSG_FRAMES 30
/*
** in reserved space right after PAB in host memory is area for returning
** values from card
*/
/*
** typedef NICSTAT
**
** Data structure for NIC statistics retruned from PCI card. Data copied from
** here to user allocated RCLINKSTATS (see rclanmtl.h) structure.
*/
typedef
struct
tag_NicStat
{
unsigned
long
TX_good
;
unsigned
long
TX_maxcol
;
unsigned
long
TX_latecol
;
unsigned
long
TX_urun
;
unsigned
long
TX_crs
;
/* lost carrier sense */
unsigned
long
TX_def
;
/* transmit deferred */
unsigned
long
TX_singlecol
;
/* single collisions */
unsigned
long
TX_multcol
;
unsigned
long
TX_totcol
;
unsigned
long
Rcv_good
;
unsigned
long
Rcv_CRCerr
;
unsigned
long
Rcv_alignerr
;
unsigned
long
Rcv_reserr
;
/* rnr'd pkts */
unsigned
long
Rcv_orun
;
unsigned
long
Rcv_cdt
;
unsigned
long
Rcv_runt
;
unsigned
long
dump_status
;
/* last field directly from the chip */
}
NICSTAT
,
*
P_NICSTAT
;
#define DUMP_DONE 0x0000A005
/* completed statistical dump */
#define DUMP_CLEAR 0x0000A007
/* completed stat dump and clear counters */
static
volatile
int
msgFlag
;
/* local function prototypes */
static
void
ProcessOutboundI2OMsg
(
PPAB
pPab
,
U32
phyMsgAddr
);
static
int
FillI2OMsgSGLFromTCB
(
PU32
pMsg
,
PRCTCB
pXmitCntrlBlock
);
static
int
GetI2OStatus
(
PPAB
pPab
);
static
int
SendI2OOutboundQInitMsg
(
PPAB
pPab
);
static
int
SendEnableSysMsg
(
PPAB
pPab
);
/*
** =========================================================================
** RCInitI2OMsgLayer()
**
** Initialize the RedCreek I2O Module and adapter.
**
** Inputs: dev - the devices net_device struct
** TransmitCallbackFunction - address of transmit callback function
** ReceiveCallbackFunction - address of receive callback function
**
** private message block is allocated by user. It must be in locked pages.
** p_msgbuf and p_phymsgbuf point to the same location. Must be contigous
** memory block of a minimum of 16K byte and long word aligned.
** =========================================================================
*/
RC_RETURN
RCInitI2OMsgLayer
(
struct
net_device
*
dev
,
PFNTXCALLBACK
TransmitCallbackFunction
,
PFNRXCALLBACK
ReceiveCallbackFunction
,
PFNCALLBACK
RebootCallbackFunction
)
{
int
result
;
PPAB
pPab
;
U32
pciBaseAddr
=
dev
->
base_addr
;
PDPA
pDpa
=
dev
->
priv
;
PU8
p_msgbuf
=
pDpa
->
msgbuf
;
PU8
p_phymsgbuf
=
(
PU8
)
pDpa
->
msgbuf_dma
;
dprintk
(
"InitI2O: Adapter:0x%04ux ATU:0x%08ulx msgbuf:%p phymsgbuf:0x%08ulx
\n
"
"TransmitCallbackFunction:0x%08ulx ReceiveCallbackFunction:0x%08ulx
\n
"
,
pDpa
->
id
,
pciBaseAddr
,
p_msgbuf
,
(
u32
)
p_phymsgbuf
,
(
u32
)
TransmitCallbackFunction
,
(
u32
)
ReceiveCallbackFunction
);
/* Check if this interface already initialized - if so, shut it down */
if
(
pDpa
->
pPab
!=
NULL
)
{
printk
(
KERN_WARNING
"(rcpci45 driver:) pDpa->pPab [%d] != NULL
\n
"
,
pDpa
->
id
);
/* RCResetLANCard(pDpa->id, 0, (PU32)NULL, (PFNCALLBACK)NULL); */
pDpa
->
pPab
=
NULL
;
}
/* store adapter instance values in adapter block.
* Adapter block is at beginning of message buffer */
pPab
=
kmalloc
(
sizeof
(
*
pPab
),
GFP_KERNEL
);
if
(
!
pPab
)
{
printk
(
KERN_ERR
"(rcpci45 driver:) RCInitI2OMsgLayer: Could not allocate memory for PAB struct!
\n
"
);
result
=
RC_RTN_MALLOC_ERROR
;
goto
err_out
;
}
memset
(
pPab
,
0
,
sizeof
(
*
pPab
));
pDpa
->
pPab
=
pPab
;
pPab
->
p_atu
=
(
PATU
)
pciBaseAddr
;
pPab
->
pPci45LinBaseAddr
=
(
PU8
)
pciBaseAddr
;
/* Set outbound message frame addr */
pPab
->
outMsgBlockPhyAddr
=
(
U32
)
p_phymsgbuf
;
pPab
->
pLinOutMsgBlock
=
(
PU8
)
p_msgbuf
;
/* store callback function addresses */
pPab
->
pTransCallbackFunc
=
TransmitCallbackFunction
;
pPab
->
pRecvCallbackFunc
=
ReceiveCallbackFunction
;
pPab
->
pRebootCallbackFunc
=
RebootCallbackFunction
;
pPab
->
pCallbackFunc
=
(
PFNCALLBACK
)
NULL
;
/*
** Initialize I2O IOP
*/
result
=
GetI2OStatus
(
pPab
);
if
(
result
!=
RC_RTN_NO_ERROR
)
goto
err_out_dealloc
;
if
(
pPab
->
IOPState
==
I2O_IOP_STATE_OPERATIONAL
)
{
printk
(
KERN_INFO
"(rcpci45 driver:) pPab->IOPState == op: resetting adapter
\n
"
);
RCResetLANCard
(
dev
,
0
,
(
PU32
)
NULL
,
(
PFNCALLBACK
)
NULL
);
}
result
=
SendI2OOutboundQInitMsg
(
pPab
);
if
(
result
!=
RC_RTN_NO_ERROR
)
goto
err_out_dealloc
;
result
=
SendEnableSysMsg
(
pPab
);
if
(
result
!=
RC_RTN_NO_ERROR
)
goto
err_out_dealloc
;
return
RC_RTN_NO_ERROR
;
err_out_dealloc:
kfree
(
pPab
);
err_out:
return
result
;
}
/*
** =========================================================================
** Disable and Enable I2O interrupts. I2O interrupts are enabled at Init time
** but can be disabled and re-enabled through these two function calls.
** Packets will still be put into any posted received buffers and packets will
** be sent through RCI2OSendPacket() functions. Disabling I2O interrupts
** will prevent hardware interrupt to host even though the outbound I2O msg
** queue is not emtpy.
** =========================================================================
*/
#define i960_OUT_POST_Q_INT_BIT 0x0008
/* bit set masks interrupts */
RC_RETURN
RCDisableI2OInterrupts
(
struct
net_device
*
dev
)
{
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
if
(
pPab
==
NULL
)
return
RC_RTN_ADPTR_NOT_REGISTERED
;
pPab
->
p_atu
->
OutIntMask
|=
i960_OUT_POST_Q_INT_BIT
;
return
RC_RTN_NO_ERROR
;
}
RC_RETURN
RCEnableI2OInterrupts
(
struct
net_device
*
dev
)
{
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
if
(
pPab
==
NULL
)
return
RC_RTN_ADPTR_NOT_REGISTERED
;
pPab
->
p_atu
->
OutIntMask
&=
~
i960_OUT_POST_Q_INT_BIT
;
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** RCI2OSendPacket()
** =========================================================================
*/
RC_RETURN
RCI2OSendPacket
(
struct
net_device
*
dev
,
U32
InitiatorContext
,
PRCTCB
pTransCtrlBlock
)
{
U32
msgOffset
;
PU32
pMsg
;
int
size
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
dprintk
(
"RCI2OSendPacket()...
\n
"
);
if
(
pPab
==
NULL
)
return
RC_RTN_ADPTR_NOT_REGISTERED
;
/* get Inbound free Q entry - reading from In Q gets free Q entry */
/* offset to Msg Frame in PCI msg block */
msgOffset
=
pPab
->
p_atu
->
InQueue
;
if
(
msgOffset
==
0xFFFFFFFF
)
{
dprintk
(
"RCI2OSendPacket(): Inbound Free Q empty!
\n
"
);
return
RC_RTN_FREE_Q_EMPTY
;
}
/* calc virtual address of msg - virtual already mapped to physical */
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
msgOffset
);
size
=
FillI2OMsgSGLFromTCB
(
pMsg
+
4
,
pTransCtrlBlock
);
if
(
size
==
-
1
)
{
/* error processing TCB - send NOP msg */
dprintk
(
"RCI2OSendPacket(): Error Rrocess TCB!
\n
"
);
pMsg
[
0
]
=
THREE_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_UTIL_NOP
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
return
RC_RTN_TCB_ERROR
;
}
else
{
/* send over msg header */
pMsg
[
0
]
=
(
size
+
4
)
<<
16
|
LAN_MSG_REQST
;
/* send over message size and flags */
pMsg
[
1
]
=
I2O_LAN_PACKET_SEND
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
InitiatorContext
;
pMsg
[
3
]
=
0
;
/* batch reply */
/* post to Inbound Post Q */
pPab
->
p_atu
->
InQueue
=
msgOffset
;
return
RC_RTN_NO_ERROR
;
}
}
/*
** =========================================================================
** RCI2OPostRecvBuffer()
**
** inputs: pBufrCntrlBlock - pointer to buffer control block
**
** returns TRUE if successful in sending message, else FALSE.
** =========================================================================
*/
RC_RETURN
RCPostRecvBuffers
(
struct
net_device
*
dev
,
PRCTCB
pTransCtrlBlock
)
{
U32
msgOffset
;
PU32
pMsg
;
int
size
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
dprintk
(
"RCPostRecvBuffers()...
\n
"
);
/* search for DeviceHandle */
if
(
pPab
==
NULL
)
return
RC_RTN_ADPTR_NOT_REGISTERED
;
/* get Inbound free Q entry - reading from In Q gets free Q entry */
/* offset to Msg Frame in PCI msg block */
msgOffset
=
pPab
->
p_atu
->
InQueue
;
if
(
msgOffset
==
0xFFFFFFFF
)
{
dprintk
(
"RCPostRecvBuffers(): Inbound Free Q empty!
\n
"
);
return
RC_RTN_FREE_Q_EMPTY
;
}
/* calc virtual address of msg - virtual already mapped to physical */
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
msgOffset
);
size
=
FillI2OMsgSGLFromTCB
(
pMsg
+
4
,
pTransCtrlBlock
);
if
(
size
==
-
1
)
{
/* error prcessing TCB - send 3 DWORD private msg == NOP */
dprintk
(
"RCPostRecvBuffers(): Error Processing TCB! size = %d
\n
"
,
size
);
pMsg
[
0
]
=
THREE_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_UTIL_NOP
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
/* post to Post Q */
pPab
->
p_atu
->
InQueue
=
msgOffset
;
return
RC_RTN_TCB_ERROR
;
}
else
{
/* send over size msg header */
pMsg
[
0
]
=
(
size
+
4
)
<<
16
|
LAN_MSG_REQST
;
/* send over message size and flags */
pMsg
[
1
]
=
I2O_LAN_RECEIVE_POST
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
DEFAULT_RECV_INIT_CONTEXT
;
pMsg
[
3
]
=
*
(
PU32
)
pTransCtrlBlock
;
/* number of packet buffers */
/* post to Post Q */
pPab
->
p_atu
->
InQueue
=
msgOffset
;
return
RC_RTN_NO_ERROR
;
}
}
/*
** =========================================================================
** RCProcI2OMsgQ()
**
** Process I2O outbound message queue until empty.
** =========================================================================
*/
irqreturn_t
RCProcI2OMsgQ
(
struct
net_device
*
dev
)
{
U32
phyAddrMsg
;
PU8
p8Msg
;
PU32
p32
;
U16
count
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
unsigned
char
debug_msg
[
20
];
if
(
pPab
==
NULL
)
return
IRQ_NONE
;
phyAddrMsg
=
pPab
->
p_atu
->
OutQueue
;
while
(
phyAddrMsg
!=
0xFFFFFFFF
)
{
p8Msg
=
pPab
->
pLinOutMsgBlock
+
(
phyAddrMsg
-
pPab
->
outMsgBlockPhyAddr
);
p32
=
(
PU32
)
p8Msg
;
dprintk
(
"msg: 0x%x 0x%x
\n
"
,
p8Msg
[
7
],
p32
[
5
]);
/* Send Packet Reply Msg */
if
(
I2O_LAN_PACKET_SEND
==
p8Msg
[
7
])
{
/* function code byte */
count
=
*
(
PU16
)
(
p8Msg
+
2
);
count
-=
p8Msg
[
0
]
>>
4
;
/* status, count, context[], adapter */
(
*
pPab
->
pTransCallbackFunc
)
(
p8Msg
[
19
],
count
,
p32
+
5
,
dev
);
}
else
if
(
I2O_LAN_RECEIVE_POST
==
p8Msg
[
7
])
{
/* Receive Packet Reply Msg */
dprintk
(
"I2O_RECV_REPLY pPab:0x%08ulx p8Msg:0x%08ulx p32:0x%08ulx
\n
"
,
(
u32
)
pPab
,
(
u32
)
p8Msg
,
(
u32
)
p32
);
dprintk
(
"msg: 0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx
\n
"
,
p32
[
0
],
p32
[
1
],
p32
[
2
],
p32
[
3
]);
dprintk
(
" 0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx
\n
"
,
p32
[
4
],
p32
[
5
],
p32
[
6
],
p32
[
7
]);
dprintk
(
" 0x%08ulx:0X%08ulx:0x%08ulx:0x%08ulx
\n
"
,
p32
[
8
],
p32
[
9
],
p32
[
10
],
p32
[
11
]);
/* status, count, buckets remaining, packetParmBlock, adapter */
(
*
pPab
->
pRecvCallbackFunc
)
(
p8Msg
[
19
],
p8Msg
[
12
],
p32
[
5
],
p32
+
6
,
dev
);
}
else
if
(
I2O_LAN_RESET
==
p8Msg
[
7
]
||
I2O_LAN_SHUTDOWN
==
p8Msg
[
7
])
if
(
pPab
->
pCallbackFunc
)
(
*
pPab
->
pCallbackFunc
)
(
p8Msg
[
19
],
0
,
0
,
dev
);
else
pPab
->
pCallbackFunc
=
(
PFNCALLBACK
)
1
;
else
if
(
I2O_PRIVATE
==
p8Msg
[
7
])
{
dprintk
(
"i2o private 0x%x, 0x%x
\n
"
,
p8Msg
[
7
],
p32
[
5
]);
switch
(
p32
[
5
])
{
case
RC_PRIVATE_DEBUG_MSG
:
msgFlag
=
1
;
dprintk
(
"Received I2O_PRIVATE msg
\n
"
);
debug_msg
[
15
]
=
(
p32
[
6
]
&
0xff000000
)
>>
24
;
debug_msg
[
14
]
=
(
p32
[
6
]
&
0x00ff0000
)
>>
16
;
debug_msg
[
13
]
=
(
p32
[
6
]
&
0x0000ff00
)
>>
8
;
debug_msg
[
12
]
=
(
p32
[
6
]
&
0x000000ff
);
debug_msg
[
11
]
=
(
p32
[
7
]
&
0xff000000
)
>>
24
;
debug_msg
[
10
]
=
(
p32
[
7
]
&
0x00ff0000
)
>>
16
;
debug_msg
[
9
]
=
(
p32
[
7
]
&
0x0000ff00
)
>>
8
;
debug_msg
[
8
]
=
(
p32
[
7
]
&
0x000000ff
);
debug_msg
[
7
]
=
(
p32
[
8
]
&
0xff000000
)
>>
24
;
debug_msg
[
6
]
=
(
p32
[
8
]
&
0x00ff0000
)
>>
16
;
debug_msg
[
5
]
=
(
p32
[
8
]
&
0x0000ff00
)
>>
8
;
debug_msg
[
4
]
=
(
p32
[
8
]
&
0x000000ff
);
debug_msg
[
3
]
=
(
p32
[
9
]
&
0xff000000
)
>>
24
;
debug_msg
[
2
]
=
(
p32
[
9
]
&
0x00ff0000
)
>>
16
;
debug_msg
[
1
]
=
(
p32
[
9
]
&
0x0000ff00
)
>>
8
;
debug_msg
[
0
]
=
(
p32
[
9
]
&
0x000000ff
);
debug_msg
[
16
]
=
'\0'
;
dprintk
(
"%s"
,
debug_msg
);
break
;
case
RC_PRIVATE_REBOOT
:
dprintk
(
"Adapter reboot initiated...
\n
"
);
if
(
pPab
->
pRebootCallbackFunc
)
(
*
pPab
->
pRebootCallbackFunc
)
(
0
,
0
,
0
,
dev
);
break
;
default:
printk
(
KERN_WARNING
"(rcpci45 driver:) Unknown private I2O msg received: 0x%x
\n
"
,
p32
[
5
]);
break
;
}
}
/*
** Process other Msg's
*/
else
ProcessOutboundI2OMsg
(
pPab
,
phyAddrMsg
);
/* return MFA to outbound free Q */
pPab
->
p_atu
->
OutQueue
=
phyAddrMsg
;
/* any more msgs? */
phyAddrMsg
=
pPab
->
p_atu
->
OutQueue
;
}
return
IRQ_HANDLED
;
}
/*
** =========================================================================
** Returns LAN interface statistical counters to space provided by caller at
** StatsReturnAddr. Returns 0 if success, else RC_RETURN code.
** This function will call the WaitCallback function provided by
** user while waiting for card to respond.
** =========================================================================
*/
RC_RETURN
RCGetLinkStatistics
(
struct
net_device
*
dev
,
P_RCLINKSTATS
StatsReturnAddr
,
PFNWAITCALLBACK
WaitCallback
)
{
U32
msgOffset
;
volatile
U32
timeout
;
volatile
PU32
pMsg
;
volatile
PU32
p32
,
pReturnAddr
;
P_NICSTAT
pStats
;
int
i
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
/*dprintk("Get82558Stats() StatsReturnAddr:0x%08ulx\n", StatsReturnAddr); */
if
(
pPab
==
NULL
)
return
RC_RTN_ADPTR_NOT_REGISTERED
;
msgOffset
=
pPab
->
p_atu
->
InQueue
;
if
(
msgOffset
==
0xFFFFFFFF
)
{
dprintk
(
"Get8255XStats(): Inbound Free Q empty!
\n
"
);
return
RC_RTN_FREE_Q_EMPTY
;
}
/* calc virtual address of msg - virtual already mapped to physical */
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
msgOffset
);
/*dprintk("Get82558Stats - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
/*dprintk("Get82558Stats - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
pMsg
[
0
]
=
SIX_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_PRIVATE
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
DEFAULT_RECV_INIT_CONTEXT
;
pMsg
[
3
]
=
0x112
;
/* transaction context */
pMsg
[
4
]
=
RC_PCI45_VENDOR_ID
<<
16
|
RC_PRIVATE_GET_NIC_STATS
;
pMsg
[
5
]
=
pPab
->
outMsgBlockPhyAddr
;
p32
=
(
PU32
)
pPab
->
outMsgBlockPhyAddr
;
pStats
=
(
P_NICSTAT
)
pPab
->
pLinOutMsgBlock
;
pStats
->
dump_status
=
0xFFFFFFFF
;
/* post to Inbound Post Q */
pPab
->
p_atu
->
InQueue
=
msgOffset
;
timeout
=
100000
;
while
(
1
)
{
if
(
WaitCallback
)
(
*
WaitCallback
)
();
udelay
(
10
);
if
(
pStats
->
dump_status
!=
0xFFFFFFFF
)
break
;
if
(
!
timeout
--
)
{
dprintk
(
"RCGet82558Stats() Timeout waiting for NIC statistics
\n
"
);
return
RC_RTN_MSG_REPLY_TIMEOUT
;
}
}
pReturnAddr
=
(
PU32
)
StatsReturnAddr
;
/* copy Nic stats to user's structure */
for
(
i
=
0
;
i
<
(
int
)
sizeof
(
RCLINKSTATS
)
/
4
;
i
++
)
pReturnAddr
[
i
]
=
p32
[
i
];
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** Get82558LinkStatus()
** =========================================================================
*/
RC_RETURN
RCGetLinkStatus
(
struct
net_device
*
dev
,
PU32
ReturnAddr
,
PFNWAITCALLBACK
WaitCallback
)
{
U32
msgOffset
;
volatile
U32
timeout
;
volatile
PU32
pMsg
;
volatile
PU32
p32
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
dprintk
(
"Get82558LinkStatus() ReturnPhysAddr:0x%08ulx
\n
"
,
(
u32
)
ReturnAddr
);
if
(
pPab
==
NULL
)
return
RC_RTN_ADPTR_NOT_REGISTERED
;
msgOffset
=
pPab
->
p_atu
->
InQueue
;
if
(
msgOffset
==
0xFFFFFFFF
)
{
dprintk
(
"Get82558LinkStatus(): Inbound Free Q empty!
\n
"
);
return
RC_RTN_FREE_Q_EMPTY
;
}
/* calc virtual address of msg - virtual already mapped to physical */
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
msgOffset
);
/*dprintk("Get82558LinkStatus - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
/*dprintk("Get82558LinkStatus - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
pMsg
[
0
]
=
SIX_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_PRIVATE
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
DEFAULT_RECV_INIT_CONTEXT
;
pMsg
[
3
]
=
0x112
;
/* transaction context */
pMsg
[
4
]
=
RC_PCI45_VENDOR_ID
<<
16
|
RC_PRIVATE_GET_LINK_STATUS
;
pMsg
[
5
]
=
pPab
->
outMsgBlockPhyAddr
;
p32
=
(
PU32
)
pPab
->
pLinOutMsgBlock
;
*
p32
=
0xFFFFFFFF
;
/* post to Inbound Post Q */
pPab
->
p_atu
->
InQueue
=
msgOffset
;
timeout
=
100000
;
while
(
1
)
{
if
(
WaitCallback
)
(
*
WaitCallback
)
();
udelay
(
10
);
if
(
*
p32
!=
0xFFFFFFFF
)
break
;
if
(
!
timeout
--
)
{
dprintk
(
"Timeout waiting for link status
\n
"
);
return
RC_RTN_MSG_REPLY_TIMEOUT
;
}
}
*
ReturnAddr
=
*
p32
;
/* 1 = up 0 = down */
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** RCGetMAC()
**
** get the MAC address the adapter is listening for in non-promiscous mode.
** MAC address is in media format.
** =========================================================================
*/
RC_RETURN
RCGetMAC
(
struct
net_device
*
dev
,
PFNWAITCALLBACK
WaitCallback
)
{
unsigned
timeout
;
U32
off
;
PU8
mac
=
dev
->
dev_addr
;
PU32
p
;
U32
temp
[
2
];
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
PATU
p_atu
;
if
(
pPab
==
NULL
)
return
RC_RTN_ADPTR_NOT_REGISTERED
;
p_atu
=
pPab
->
p_atu
;
p_atu
->
EtherMacLow
=
0
;
/* first zero return data */
p_atu
->
EtherMacHi
=
0
;
off
=
p_atu
->
InQueue
;
/* get addresss of message */
if
(
0xFFFFFFFF
==
off
)
return
RC_RTN_FREE_Q_EMPTY
;
p
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
off
);
dprintk
(
"RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x
\n
"
,
(
uint
)
p_atu
,
(
uint
)
off
,
(
uint
)
p
);
/* setup private message */
p
[
0
]
=
FIVE_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
p
[
1
]
=
I2O_PRIVATE
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
p
[
2
]
=
0
;
/* initiator context */
p
[
3
]
=
0x218
;
/* transaction context */
p
[
4
]
=
RC_PCI45_VENDOR_ID
<<
16
|
RC_PRIVATE_GET_MAC_ADDR
;
p_atu
->
InQueue
=
off
;
/* send it to the I2O device */
dprintk
(
"RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x
\n
"
,
(
uint
)
p_atu
,
(
uint
)
off
,
(
uint
)
p
);
/* wait for the rcpci45 board to update the info */
timeout
=
1000000
;
while
(
0
==
p_atu
->
EtherMacLow
)
{
if
(
WaitCallback
)
(
*
WaitCallback
)
();
udelay
(
10
);
if
(
!
timeout
--
)
{
printk
(
"rc_getmac: Timeout
\n
"
);
return
RC_RTN_MSG_REPLY_TIMEOUT
;
}
}
/* read the mac address */
temp
[
0
]
=
p_atu
->
EtherMacLow
;
temp
[
1
]
=
p_atu
->
EtherMacHi
;
memcpy
((
char
*
)
mac
,
(
char
*
)
temp
,
6
);
dprintk
(
"rc_getmac: 0x%x
\n
"
,
(
u32
)
mac
);
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** RCSetMAC()
**
** set MAC address the adapter is listening for in non-promiscous mode.
** MAC address is in media format.
** =========================================================================
*/
RC_RETURN
RCSetMAC
(
struct
net_device
*
dev
,
PU8
mac
)
{
U32
off
;
PU32
pMsg
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
if
(
pPab
==
NULL
)
return
RC_RTN_ADPTR_NOT_REGISTERED
;
off
=
pPab
->
p_atu
->
InQueue
;
/* get addresss of message */
if
(
0xFFFFFFFF
==
off
)
return
RC_RTN_FREE_Q_EMPTY
;
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
off
);
/* setup private message */
pMsg
[
0
]
=
SEVEN_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_PRIVATE
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
0
;
/* initiator context */
pMsg
[
3
]
=
0x219
;
/* transaction context */
pMsg
[
4
]
=
RC_PCI45_VENDOR_ID
<<
16
|
RC_PRIVATE_SET_MAC_ADDR
;
pMsg
[
5
]
=
*
(
unsigned
*
)
mac
;
/* first four bytes */
pMsg
[
6
]
=
*
(
unsigned
*
)
(
mac
+
4
);
/* last two bytes */
pPab
->
p_atu
->
InQueue
=
off
;
/* send it to the I2O device */
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** RCSetLinkSpeed()
**
** set ethernet link speed.
** input: speedControl - determines action to take as follows
** 0 = reset and auto-negotiate (NWay)
** 1 = Full Duplex 100BaseT
** 2 = Half duplex 100BaseT
** 3 = Full Duplex 10BaseT
** 4 = Half duplex 10BaseT
** all other values are ignore (do nothing)
** =========================================================================
*/
RC_RETURN
RCSetLinkSpeed
(
struct
net_device
*
dev
,
U16
LinkSpeedCode
)
{
U32
off
;
PU32
pMsg
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
if
(
pPab
==
NULL
)
return
RC_RTN_ADPTR_NOT_REGISTERED
;
off
=
pPab
->
p_atu
->
InQueue
;
/* get addresss of message */
if
(
0xFFFFFFFF
==
off
)
return
RC_RTN_FREE_Q_EMPTY
;
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
off
);
/* setup private message */
pMsg
[
0
]
=
SIX_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_PRIVATE
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
0
;
/* initiator context */
pMsg
[
3
]
=
0x219
;
/* transaction context */
pMsg
[
4
]
=
RC_PCI45_VENDOR_ID
<<
16
|
RC_PRIVATE_SET_LINK_SPEED
;
pMsg
[
5
]
=
LinkSpeedCode
;
/* link speed code */
pPab
->
p_atu
->
InQueue
=
off
;
/* send it to the I2O device */
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** RCSetPromiscuousMode()
**
** Defined values for Mode:
** 0 - turn off promiscuous mode
** 1 - turn on promiscuous mode
**
** =========================================================================
*/
RC_RETURN
RCSetPromiscuousMode
(
struct
net_device
*
dev
,
U16
Mode
)
{
U32
off
;
PU32
pMsg
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
if
(
pPab
==
NULL
)
return
RC_RTN_ADPTR_NOT_REGISTERED
;
off
=
pPab
->
p_atu
->
InQueue
;
/* get addresss of message */
if
(
0xFFFFFFFF
==
off
)
return
RC_RTN_FREE_Q_EMPTY
;
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
off
);
/* setup private message */
pMsg
[
0
]
=
SIX_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_PRIVATE
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
0
;
/* initiator context */
pMsg
[
3
]
=
0x219
;
/* transaction context */
pMsg
[
4
]
=
RC_PCI45_VENDOR_ID
<<
16
|
RC_PRIVATE_SET_PROMISCUOUS_MODE
;
pMsg
[
5
]
=
Mode
;
/* promiscuous mode setting */
pPab
->
p_atu
->
InQueue
=
off
;
/* send it to the device */
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** RCGetPromiscuousMode()
**
** get promiscuous mode setting
**
** Possible return values placed in pMode:
** 0 = promisuous mode not set
** 1 = promisuous mode is set
**
** =========================================================================
*/
RC_RETURN
RCGetPromiscuousMode
(
struct
net_device
*
dev
,
PU32
pMode
,
PFNWAITCALLBACK
WaitCallback
)
{
U32
msgOffset
,
timeout
;
PU32
pMsg
;
volatile
PU32
p32
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
msgOffset
=
pPab
->
p_atu
->
InQueue
;
if
(
msgOffset
==
0xFFFFFFFF
)
{
printk
(
KERN_WARNING
"(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!
\n
"
);
return
RC_RTN_FREE_Q_EMPTY
;
}
/* calc virtual address of msg - virtual already mapped to physical */
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
msgOffset
);
/* virtual pointer to return buffer - clear first two dwords */
p32
=
(
volatile
PU32
)
pPab
->
pLinOutMsgBlock
;
p32
[
0
]
=
0xff
;
/* setup private message */
pMsg
[
0
]
=
SIX_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_PRIVATE
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
0
;
/* initiator context */
pMsg
[
3
]
=
0x219
;
/* transaction context */
pMsg
[
4
]
=
RC_PCI45_VENDOR_ID
<<
16
|
RC_PRIVATE_GET_PROMISCUOUS_MODE
;
/* phys address to return status - area right after PAB */
pMsg
[
5
]
=
pPab
->
outMsgBlockPhyAddr
;
/* post to Inbound Post Q */
pPab
->
p_atu
->
InQueue
=
msgOffset
;
/* wait for response */
timeout
=
1000000
;
while
(
1
)
{
if
(
WaitCallback
)
(
*
WaitCallback
)
();
udelay
(
10
);
/* please don't hog the bus!!! */
if
(
p32
[
0
]
!=
0xff
)
break
;
if
(
!
timeout
--
)
{
dprintk
(
"Timeout waiting for promiscuous mode from adapter
\n
"
);
dprintk
(
"0x%8x
\n
"
,
p32
[
0
]);
return
RC_RTN_NO_LINK_SPEED
;
}
}
/* get mode */
*
pMode
=
(
U8
)
((
volatile
PU8
)
p32
)[
0
]
&
0x0f
;
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** RCSetBroadcastMode()
**
** Defined values for Mode:
** 0 - turn off promiscuous mode
** 1 - turn on promiscuous mode
**
** =========================================================================
*/
RC_RETURN
RCSetBroadcastMode
(
struct
net_device
*
dev
,
U16
Mode
)
{
U32
off
;
PU32
pMsg
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
if
(
pPab
==
NULL
)
return
RC_RTN_ADPTR_NOT_REGISTERED
;
off
=
pPab
->
p_atu
->
InQueue
;
/* get addresss of message */
if
(
0xFFFFFFFF
==
off
)
return
RC_RTN_FREE_Q_EMPTY
;
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
off
);
/* setup private message */
pMsg
[
0
]
=
SIX_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_PRIVATE
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
0
;
/* initiator context */
pMsg
[
3
]
=
0x219
;
/* transaction context */
pMsg
[
4
]
=
RC_PCI45_VENDOR_ID
<<
16
|
RC_PRIVATE_SET_BROADCAST_MODE
;
pMsg
[
5
]
=
Mode
;
/* promiscuous mode setting */
pPab
->
p_atu
->
InQueue
=
off
;
/* send it to the device */
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** RCGetBroadcastMode()
**
** get promiscuous mode setting
**
** Possible return values placed in pMode:
** 0 = promisuous mode not set
** 1 = promisuous mode is set
**
** =========================================================================
*/
RC_RETURN
RCGetBroadcastMode
(
struct
net_device
*
dev
,
PU32
pMode
,
PFNWAITCALLBACK
WaitCallback
)
{
U32
msgOffset
,
timeout
;
PU32
pMsg
;
volatile
PU32
p32
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
msgOffset
=
pPab
->
p_atu
->
InQueue
;
if
(
msgOffset
==
0xFFFFFFFF
)
{
printk
(
KERN_WARNING
"(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!
\n
"
);
return
RC_RTN_FREE_Q_EMPTY
;
}
/* calc virtual address of msg - virtual already mapped to physical */
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
msgOffset
);
/* virtual pointer to return buffer - clear first two dwords */
p32
=
(
volatile
PU32
)
pPab
->
pLinOutMsgBlock
;
p32
[
0
]
=
0xff
;
/* setup private message */
pMsg
[
0
]
=
SIX_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_PRIVATE
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
0
;
/* initiator context */
pMsg
[
3
]
=
0x219
;
/* transaction context */
pMsg
[
4
]
=
RC_PCI45_VENDOR_ID
<<
16
|
RC_PRIVATE_GET_BROADCAST_MODE
;
/* phys address to return status - area right after PAB */
pMsg
[
5
]
=
pPab
->
outMsgBlockPhyAddr
;
/* post to Inbound Post Q */
pPab
->
p_atu
->
InQueue
=
msgOffset
;
/* wait for response */
timeout
=
1000000
;
while
(
1
)
{
if
(
WaitCallback
)
(
*
WaitCallback
)
();
udelay
(
10
);
/* please don't hog the bus!!! */
if
(
p32
[
0
]
!=
0xff
)
break
;
if
(
!
timeout
--
)
{
printk
(
KERN_WARNING
"(rcpci45 driver:) Timeout waiting for promiscuous mode from adapter
\n
"
);
printk
(
KERN_WARNING
"(rcpci45 driver:) 0x%8x
\n
"
,
p32
[
0
]);
return
RC_RTN_NO_LINK_SPEED
;
}
}
/* get mode */
*
pMode
=
(
U8
)
((
volatile
PU8
)
p32
)[
0
]
&
0x0f
;
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** RCGetLinkSpeed()
**
** get ethernet link speed.
**
** 0 = Unknown
** 1 = Full Duplex 100BaseT
** 2 = Half duplex 100BaseT
** 3 = Full Duplex 10BaseT
** 4 = Half duplex 10BaseT
**
** =========================================================================
*/
RC_RETURN
RCGetLinkSpeed
(
struct
net_device
*
dev
,
PU32
pLinkSpeedCode
,
PFNWAITCALLBACK
WaitCallback
)
{
U32
msgOffset
,
timeout
;
PU32
pMsg
;
volatile
PU32
p32
;
U8
IOPLinkSpeed
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
msgOffset
=
pPab
->
p_atu
->
InQueue
;
if
(
msgOffset
==
0xFFFFFFFF
)
{
printk
(
KERN_WARNING
"(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!
\n
"
);
return
RC_RTN_FREE_Q_EMPTY
;
}
/* calc virtual address of msg - virtual already mapped to physical */
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
msgOffset
);
/* virtual pointer to return buffer - clear first two dwords */
p32
=
(
volatile
PU32
)
pPab
->
pLinOutMsgBlock
;
p32
[
0
]
=
0xff
;
/* setup private message */
pMsg
[
0
]
=
SIX_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_PRIVATE
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
0
;
/* initiator context */
pMsg
[
3
]
=
0x219
;
/* transaction context */
pMsg
[
4
]
=
RC_PCI45_VENDOR_ID
<<
16
|
RC_PRIVATE_GET_LINK_SPEED
;
/* phys address to return status - area right after PAB */
pMsg
[
5
]
=
pPab
->
outMsgBlockPhyAddr
;
/* post to Inbound Post Q */
pPab
->
p_atu
->
InQueue
=
msgOffset
;
/* wait for response */
timeout
=
1000000
;
while
(
1
)
{
if
(
WaitCallback
)
(
*
WaitCallback
)
();
udelay
(
10
);
/* please don't hog the bus!!! */
if
(
p32
[
0
]
!=
0xff
)
break
;
if
(
!
timeout
--
)
{
dprintk
(
"Timeout waiting for link speed from IOP
\n
"
);
dprintk
(
"0x%8x
\n
"
,
p32
[
0
]);
return
RC_RTN_NO_LINK_SPEED
;
}
}
/* get Link speed */
IOPLinkSpeed
=
(
U8
)
((
volatile
PU8
)
p32
)[
0
]
&
0x0f
;
*
pLinkSpeedCode
=
IOPLinkSpeed
;
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** RCReportDriverCapability(struct net_device *dev, U32 capability)
**
** Currently defined bits:
** WARM_REBOOT_CAPABLE 0x01
**
** =========================================================================
*/
RC_RETURN
RCReportDriverCapability
(
struct
net_device
*
dev
,
U32
capability
)
{
U32
off
;
PU32
pMsg
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
if
(
pPab
==
NULL
)
return
RC_RTN_ADPTR_NOT_REGISTERED
;
off
=
pPab
->
p_atu
->
InQueue
;
/* get addresss of message */
if
(
0xFFFFFFFF
==
off
)
return
RC_RTN_FREE_Q_EMPTY
;
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
off
);
/* setup private message */
pMsg
[
0
]
=
SIX_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_PRIVATE
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
0
;
/* initiator context */
pMsg
[
3
]
=
0x219
;
/* transaction context */
pMsg
[
4
]
=
RC_PCI45_VENDOR_ID
<<
16
|
RC_PRIVATE_REPORT_DRIVER_CAPABILITY
;
pMsg
[
5
]
=
capability
;
pPab
->
p_atu
->
InQueue
=
off
;
/* send it to the I2O device */
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** RCGetFirmwareVer()
**
** Return firmware version in the form "SoftwareVersion : Bt BootVersion"
**
** =========================================================================
*/
RC_RETURN
RCGetFirmwareVer
(
struct
net_device
*
dev
,
PU8
pFirmString
,
PFNWAITCALLBACK
WaitCallback
)
{
U32
msgOffset
,
timeout
;
PU32
pMsg
;
volatile
PU32
p32
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
msgOffset
=
pPab
->
p_atu
->
InQueue
;
if
(
msgOffset
==
0xFFFFFFFF
)
{
dprintk
(
"RCGetFirmwareVer(): Inbound Free Q empty!
\n
"
);
return
RC_RTN_FREE_Q_EMPTY
;
}
/* calc virtual address of msg - virtual already mapped to physical */
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
msgOffset
);
/* virtual pointer to return buffer - clear first two dwords */
p32
=
(
volatile
PU32
)
pPab
->
pLinOutMsgBlock
;
p32
[
0
]
=
0xff
;
/* setup private message */
pMsg
[
0
]
=
SIX_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_PRIVATE
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
0
;
/* initiator context */
pMsg
[
3
]
=
0x219
;
/* transaction context */
pMsg
[
4
]
=
RC_PCI45_VENDOR_ID
<<
16
|
RC_PRIVATE_GET_FIRMWARE_REV
;
/* phys address to return status - area right after PAB */
pMsg
[
5
]
=
pPab
->
outMsgBlockPhyAddr
;
/* post to Inbound Post Q */
pPab
->
p_atu
->
InQueue
=
msgOffset
;
/* wait for response */
timeout
=
1000000
;
while
(
1
)
{
if
(
WaitCallback
)
(
*
WaitCallback
)
();
udelay
(
10
);
/* please don't hog the bus!!! */
if
(
p32
[
0
]
!=
0xff
)
break
;
if
(
!
timeout
--
)
{
dprintk
(
"Timeout waiting for link speed from IOP
\n
"
);
return
RC_RTN_NO_FIRM_VER
;
}
}
strcpy
(
pFirmString
,
(
PU8
)
p32
);
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** RCResetLANCard()
**
** ResourceFlags indicates whether to return buffer resource explicitly
** to host or keep and reuse.
** CallbackFunction (if not NULL) is the function to be called when
** reset is complete.
** If CallbackFunction is NULL, ReturnAddr will have a 1 placed in it when
** reset is done (if not NULL).
**
** =========================================================================
*/
RC_RETURN
RCResetLANCard
(
struct
net_device
*
dev
,
U16
ResourceFlags
,
PU32
ReturnAddr
,
PFNCALLBACK
CallbackFunction
)
{
unsigned
long
off
;
PU32
pMsg
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
long
timeout
=
0
;
if
(
pPab
==
NULL
)
return
RC_RTN_ADPTR_NOT_REGISTERED
;
off
=
pPab
->
p_atu
->
InQueue
;
/* get addresss of message */
if
(
0xFFFFFFFF
==
off
)
return
RC_RTN_FREE_Q_EMPTY
;
pPab
->
pCallbackFunc
=
CallbackFunction
;
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
off
);
/* setup message */
pMsg
[
0
]
=
FOUR_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_LAN_RESET
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
DEFAULT_RECV_INIT_CONTEXT
;
pMsg
[
3
]
=
ResourceFlags
<<
16
;
/* resource flags */
pPab
->
p_atu
->
InQueue
=
off
;
/* send it to the I2O device */
if
(
CallbackFunction
==
(
PFNCALLBACK
)
NULL
)
{
/* call RCProcI2OMsgQ() until something in pPab->pCallbackFunc
or until timer goes off */
while
(
pPab
->
pCallbackFunc
==
(
PFNCALLBACK
)
NULL
)
{
RCProcI2OMsgQ
(
dev
);
udelay
(
1000
);
/* please don't hog the bus!!! */
timeout
++
;
if
(
timeout
>
10000
)
{
break
;
}
}
if
(
ReturnAddr
!=
(
PU32
)
NULL
)
*
ReturnAddr
=
(
U32
)
pPab
->
pCallbackFunc
;
}
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** RCResetIOP()
**
** Send StatusGet Msg, wait for results return directly to buffer.
**
** =========================================================================
*/
RC_RETURN
RCResetIOP
(
struct
net_device
*
dev
)
{
U32
msgOffset
,
timeout
;
PU32
pMsg
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
volatile
PU32
p32
;
msgOffset
=
pPab
->
p_atu
->
InQueue
;
if
(
msgOffset
==
0xFFFFFFFF
)
{
return
RC_RTN_FREE_Q_EMPTY
;
}
/* calc virtual address of msg - virtual already mapped to physical */
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
msgOffset
);
pMsg
[
0
]
=
NINE_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_EXEC_IOP_RESET
<<
24
|
I2O_HOST_TID
<<
12
|
I2O_IOP_TID
;
pMsg
[
2
]
=
0
;
/* universal context */
pMsg
[
3
]
=
0
;
/* universal context */
pMsg
[
4
]
=
0
;
/* universal context */
pMsg
[
5
]
=
0
;
/* universal context */
/* phys address to return status - area right after PAB */
pMsg
[
6
]
=
pPab
->
outMsgBlockPhyAddr
;
pMsg
[
7
]
=
0
;
pMsg
[
8
]
=
1
;
/* return 1 byte */
/* virtual pointer to return buffer - clear first two dwords */
p32
=
(
volatile
PU32
)
pPab
->
pLinOutMsgBlock
;
p32
[
0
]
=
0
;
p32
[
1
]
=
0
;
/* post to Inbound Post Q */
pPab
->
p_atu
->
InQueue
=
msgOffset
;
/* wait for response */
timeout
=
1000000
;
while
(
1
)
{
udelay
(
10
);
/* please don't hog the bus!!! */
if
(
p32
[
0
]
||
p32
[
1
])
break
;
if
(
!
timeout
--
)
{
dprintk
(
"RCResetIOP timeout
\n
"
);
return
RC_RTN_MSG_REPLY_TIMEOUT
;
}
}
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** RCShutdownLANCard()
**
** ResourceFlags indicates whether to return buffer resource explicitly
** to host or keep and reuse.
** CallbackFunction (if not NULL) is the function to be called when
** shutdown is complete.
** If CallbackFunction is NULL, ReturnAddr will have a 1 placed in it when
** shutdown is done (if not NULL).
**
** =========================================================================
*/
RC_RETURN
RCShutdownLANCard
(
struct
net_device
*
dev
,
U16
ResourceFlags
,
PU32
ReturnAddr
,
PFNCALLBACK
CallbackFunction
)
{
volatile
PU32
pMsg
;
U32
off
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
long
timeout
=
0
;
if
(
pPab
==
NULL
)
return
RC_RTN_ADPTR_NOT_REGISTERED
;
off
=
pPab
->
p_atu
->
InQueue
;
/* get addresss of message */
if
(
0xFFFFFFFF
==
off
)
return
RC_RTN_FREE_Q_EMPTY
;
pPab
->
pCallbackFunc
=
CallbackFunction
;
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
off
);
/* setup message */
pMsg
[
0
]
=
FOUR_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_LAN_SHUTDOWN
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
DEFAULT_RECV_INIT_CONTEXT
;
pMsg
[
3
]
=
ResourceFlags
<<
16
;
/* resource flags */
pPab
->
p_atu
->
InQueue
=
off
;
/* send it to the I2O device */
if
(
CallbackFunction
==
(
PFNCALLBACK
)
NULL
)
{
/* call RCProcI2OMsgQ() until something in pPab->pCallbackFunc
or until timer goes off */
while
(
pPab
->
pCallbackFunc
==
(
PFNCALLBACK
)
NULL
)
{
RCProcI2OMsgQ
(
dev
);
udelay
(
1000
);
/* please don't hog the bus!!! */
timeout
++
;
if
(
timeout
>
10000
)
{
printk
(
KERN_WARNING
"(rcpci45 driver:) RCShutdownLANCard(): timeout
\n
"
);
break
;
}
}
if
(
ReturnAddr
!=
(
PU32
)
NULL
)
*
ReturnAddr
=
(
U32
)
pPab
->
pCallbackFunc
;
}
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** RCSetRavlinIPandMask()
**
** Set the Ravlin 45/PCI cards IP address and network mask.
**
** IP address and mask must be in network byte order.
** For example, IP address 1.2.3.4 and mask 255.255.255.0 would be
** 0x04030201 and 0x00FFFFFF on a little endian machine.
**
** =========================================================================
*/
RC_RETURN
RCSetRavlinIPandMask
(
struct
net_device
*
dev
,
U32
ipAddr
,
U32
netMask
)
{
volatile
PU32
pMsg
;
U32
off
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
if
(
pPab
==
NULL
)
return
RC_RTN_ADPTR_NOT_REGISTERED
;
off
=
pPab
->
p_atu
->
InQueue
;
/* get addresss of message */
if
(
0xFFFFFFFF
==
off
)
return
RC_RTN_FREE_Q_EMPTY
;
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
off
);
/* setup private message */
pMsg
[
0
]
=
SEVEN_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_PRIVATE
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
0
;
/* initiator context */
pMsg
[
3
]
=
0x219
;
/* transaction context */
pMsg
[
4
]
=
RC_PCI45_VENDOR_ID
<<
16
|
RC_PRIVATE_SET_IP_AND_MASK
;
pMsg
[
5
]
=
ipAddr
;
pMsg
[
6
]
=
netMask
;
pPab
->
p_atu
->
InQueue
=
off
;
/* send it to the I2O device */
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** RCGetRavlinIPandMask()
**
** get the IP address and MASK from the card
**
** =========================================================================
*/
RC_RETURN
RCGetRavlinIPandMask
(
struct
net_device
*
dev
,
PU32
pIpAddr
,
PU32
pNetMask
,
PFNWAITCALLBACK
WaitCallback
)
{
unsigned
timeout
;
U32
off
;
PU32
pMsg
,
p32
;
PPAB
pPab
=
((
PDPA
)
dev
->
priv
)
->
pPab
;
PATU
p_atu
;
dprintk
(
"RCGetRavlinIPandMask: pIpAddr is 0x%08ulx, *IpAddr is 0x%08ulx
\n
"
,
(
u32
)
pIpAddr
,
*
pIpAddr
);
if
(
pPab
==
NULL
)
return
RC_RTN_ADPTR_NOT_REGISTERED
;
p_atu
=
pPab
->
p_atu
;
off
=
p_atu
->
InQueue
;
/* get addresss of message */
if
(
0xFFFFFFFF
==
off
)
return
RC_RTN_FREE_Q_EMPTY
;
p32
=
(
volatile
PU32
)
pPab
->
pLinOutMsgBlock
;
*
p32
=
0xFFFFFFFF
;
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
off
);
dprintk
(
"RCGetRavlinIPandMask: p_atu 0x%08ulx, off 0x%08ulx, p32 0x%08ulx
\n
"
,
(
u32
)
p_atu
,
off
,
(
u32
)
p32
);
/* setup private message */
pMsg
[
0
]
=
FIVE_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_PRIVATE
<<
24
|
I2O_HOST_TID
<<
12
|
RC_LAN_TARGET_ID
;
pMsg
[
2
]
=
0
;
/* initiator context */
pMsg
[
3
]
=
0x218
;
/* transaction context */
pMsg
[
4
]
=
RC_PCI45_VENDOR_ID
<<
16
|
RC_PRIVATE_GET_IP_AND_MASK
;
pMsg
[
5
]
=
pPab
->
outMsgBlockPhyAddr
;
p_atu
->
InQueue
=
off
;
/* send it to the I2O device */
dprintk
(
"RCGetRavlinIPandMask: p_atu 0x%08ulx, off 0x%08ulx, p32 0x%08ulx
\n
"
,
(
u32
)
p_atu
,
off
,
(
u32
)
p32
);
/* wait for the rcpci45 board to update the info */
timeout
=
100000
;
while
(
0xffffffff
==
*
p32
)
{
if
(
WaitCallback
)
(
*
WaitCallback
)
();
udelay
(
10
);
if
(
!
timeout
--
)
{
dprintk
(
"RCGetRavlinIPandMask: Timeout
\n
"
);
return
RC_RTN_MSG_REPLY_TIMEOUT
;
}
}
dprintk
(
"RCGetRavlinIPandMask: after time out
\n
p32[0] (IpAddr) 0x%08ulx, p32[1] (IPmask) 0x%08ulx
\n
"
,
p32
[
0
],
p32
[
1
]);
/* send IP and mask to user's space */
*
pIpAddr
=
p32
[
0
];
*
pNetMask
=
p32
[
1
];
dprintk
(
"RCGetRavlinIPandMask: pIpAddr is 0x%08ulx, *IpAddr is 0x%08ulx
\n
"
,
(
u32
)
pIpAddr
,
*
pIpAddr
);
return
RC_RTN_NO_ERROR
;
}
/*
** /////////////////////////////////////////////////////////////////////////
** /////////////////////////////////////////////////////////////////////////
**
** local functions
**
** /////////////////////////////////////////////////////////////////////////
** /////////////////////////////////////////////////////////////////////////
*/
/*
** =========================================================================
** SendI2OOutboundQInitMsg()
**
** =========================================================================
*/
static
int
SendI2OOutboundQInitMsg
(
PPAB
pPab
)
{
U32
msgOffset
,
timeout
,
phyOutQFrames
,
i
;
volatile
PU32
pMsg
;
volatile
PU32
p32
;
msgOffset
=
pPab
->
p_atu
->
InQueue
;
if
(
msgOffset
==
0xFFFFFFFF
)
{
dprintk
(
"SendI2OOutboundQInitMsg(): Inbound Free Q empty!
\n
"
);
return
RC_RTN_FREE_Q_EMPTY
;
}
/* calc virtual address of msg - virtual already mapped to physical */
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
msgOffset
);
dprintk
(
"SendI2OOutboundQInitMsg - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx
\n
"
,
(
u32
)
pMsg
,
msgOffset
);
pMsg
[
0
]
=
EIGHT_WORD_MSG_SIZE
|
TRL_OFFSET_6
;
pMsg
[
1
]
=
I2O_EXEC_OUTBOUND_INIT
<<
24
|
I2O_HOST_TID
<<
12
|
I2O_IOP_TID
;
pMsg
[
2
]
=
DEFAULT_RECV_INIT_CONTEXT
;
pMsg
[
3
]
=
0x106
;
/* transaction context */
pMsg
[
4
]
=
4096
;
/* Host page frame size */
pMsg
[
5
]
=
MSG_FRAME_SIZE
<<
16
|
0x80
;
/* outbound msg frame size and Initcode */
pMsg
[
6
]
=
0xD0000004
;
/* simple sgl element LE, EOB */
/* phys address to return status - area right after PAB */
pMsg
[
7
]
=
pPab
->
outMsgBlockPhyAddr
;
/* virtual pointer to return buffer - clear first two dwords */
p32
=
(
PU32
)
pPab
->
pLinOutMsgBlock
;
p32
[
0
]
=
0
;
/* post to Inbound Post Q */
pPab
->
p_atu
->
InQueue
=
msgOffset
;
/* wait for response */
timeout
=
100000
;
while
(
1
)
{
udelay
(
10
);
/* please don't hog the bus!!! */
if
(
p32
[
0
])
break
;
if
(
!
timeout
--
)
{
dprintk
(
"Timeout wait for InitOutQ InPrgress status from IOP
\n
"
);
return
RC_RTN_NO_I2O_STATUS
;
}
}
timeout
=
100000
;
while
(
1
)
{
udelay
(
10
);
/* please don't hog the bus!!! */
if
(
p32
[
0
]
==
I2O_EXEC_OUTBOUND_INIT_COMPLETE
)
break
;
if
(
!
timeout
--
)
{
dprintk
(
"Timeout wait for InitOutQ Complete status from IOP
\n
"
);
return
RC_RTN_NO_I2O_STATUS
;
}
}
/* load PCI outbound free Q with MF physical addresses */
phyOutQFrames
=
pPab
->
outMsgBlockPhyAddr
;
for
(
i
=
0
;
i
<
NMBR_MSG_FRAMES
;
i
++
)
{
pPab
->
p_atu
->
OutQueue
=
phyOutQFrames
;
phyOutQFrames
+=
MSG_FRAME_SIZE
;
}
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** GetI2OStatus()
**
** Send StatusGet Msg, wait for results return directly to buffer.
**
** =========================================================================
*/
static
int
GetI2OStatus
(
PPAB
pPab
)
{
U32
msgOffset
,
timeout
;
PU32
pMsg
;
volatile
PU32
p32
;
msgOffset
=
pPab
->
p_atu
->
InQueue
;
dprintk
(
"GetI2OStatus: msg offset = 0x%x
\n
"
,
msgOffset
);
if
(
msgOffset
==
0xFFFFFFFF
)
{
dprintk
(
"GetI2OStatus(): Inbound Free Q empty!
\n
"
);
return
RC_RTN_FREE_Q_EMPTY
;
}
/* calc virtual address of msg - virtual already mapped to physical */
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
msgOffset
);
pMsg
[
0
]
=
NINE_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_EXEC_STATUS_GET
<<
24
|
I2O_HOST_TID
<<
12
|
I2O_IOP_TID
;
pMsg
[
2
]
=
0
;
/* universal context */
pMsg
[
3
]
=
0
;
/* universal context */
pMsg
[
4
]
=
0
;
/* universal context */
pMsg
[
5
]
=
0
;
/* universal context */
/* phys address to return status - area right after PAB */
pMsg
[
6
]
=
pPab
->
outMsgBlockPhyAddr
;
pMsg
[
7
]
=
0
;
pMsg
[
8
]
=
88
;
/* return 88 bytes */
/* virtual pointer to return buffer - clear first two dwords */
p32
=
(
volatile
PU32
)
pPab
->
pLinOutMsgBlock
;
p32
[
0
]
=
0
;
p32
[
1
]
=
0
;
dprintk
(
"GetI2OStatus - pMsg:0x%08ulx, msgOffset:0x%08ulx, [1]:0x%08ulx, [6]:0x%08ulx
\n
"
,
(
u32
)
pMsg
,
msgOffset
,
pMsg
[
1
],
pMsg
[
6
]);
/* post to Inbound Post Q */
pPab
->
p_atu
->
InQueue
=
msgOffset
;
dprintk
(
"Return status to p32 = 0x%08ulx
\n
"
,
(
u32
)
p32
);
/* wait for response */
timeout
=
1000000
;
while
(
1
)
{
udelay
(
10
);
/* please don't hog the bus!!! */
if
(
p32
[
0
]
&&
p32
[
1
])
break
;
if
(
!
timeout
--
)
{
dprintk
(
"Timeout waiting for status from IOP
\n
"
);
dprintk
(
"0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx
\n
"
,
p32
[
0
],
p32
[
1
],
p32
[
2
],
p32
[
3
]);
dprintk
(
"0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx
\n
"
,
p32
[
4
],
p32
[
5
],
p32
[
6
],
p32
[
7
]);
dprintk
(
"0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx
\n
"
,
p32
[
8
],
p32
[
9
],
p32
[
10
],
p32
[
11
]);
return
RC_RTN_NO_I2O_STATUS
;
}
}
dprintk
(
"0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx
\n
"
,
p32
[
0
],
p32
[
1
],
p32
[
2
],
p32
[
3
]);
dprintk
(
"0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx
\n
"
,
p32
[
4
],
p32
[
5
],
p32
[
6
],
p32
[
7
]);
dprintk
(
"0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx
\n
"
,
p32
[
8
],
p32
[
9
],
p32
[
10
],
p32
[
11
]);
/* get IOP state */
pPab
->
IOPState
=
((
volatile
PU8
)
p32
)[
10
];
pPab
->
InboundMFrameSize
=
((
volatile
PU16
)
p32
)[
6
];
dprintk
(
"IOP state 0x%02x InFrameSize = 0x%04x
\n
"
,
pPab
->
IOPState
,
pPab
->
InboundMFrameSize
);
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** SendEnableSysMsg()
**
**
** =========================================================================
*/
static
int
SendEnableSysMsg
(
PPAB
pPab
)
{
U32
msgOffset
;
volatile
PU32
pMsg
;
msgOffset
=
pPab
->
p_atu
->
InQueue
;
if
(
msgOffset
==
0xFFFFFFFF
)
{
dprintk
(
"SendEnableSysMsg(): Inbound Free Q empty!
\n
"
);
return
RC_RTN_FREE_Q_EMPTY
;
}
/* calc virtual address of msg - virtual already mapped to physical */
pMsg
=
(
PU32
)
(
pPab
->
pPci45LinBaseAddr
+
msgOffset
);
dprintk
(
"SendEnableSysMsg - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx
\n
"
,
(
u32
)
pMsg
,
msgOffset
);
pMsg
[
0
]
=
FOUR_WORD_MSG_SIZE
|
SGL_OFFSET_0
;
pMsg
[
1
]
=
I2O_EXEC_SYS_ENABLE
<<
24
|
I2O_HOST_TID
<<
12
|
I2O_IOP_TID
;
pMsg
[
2
]
=
DEFAULT_RECV_INIT_CONTEXT
;
pMsg
[
3
]
=
0x110
;
/* transaction context */
pMsg
[
4
]
=
0x50657465
;
/* RedCreek Private */
/* post to Inbound Post Q */
pPab
->
p_atu
->
InQueue
=
msgOffset
;
return
RC_RTN_NO_ERROR
;
}
/*
** =========================================================================
** FillI2OMsgFromTCB()
**
** inputs pMsgU32 - virtual pointer (mapped to physical) of message frame
** pXmitCntrlBlock - pointer to caller buffer control block.
**
** fills in LAN SGL after Transaction Control Word or Bucket Count.
** =========================================================================
*/
static
int
FillI2OMsgSGLFromTCB
(
PU32
pMsgFrame
,
PRCTCB
pTransCtrlBlock
)
{
unsigned
int
nmbrBuffers
,
nmbrSeg
,
nmbrDwords
,
context
,
flags
;
PU32
pTCB
,
pMsg
;
/* SGL element flags */
#define EOB 0x40000000
#define LE 0x80000000
#define SIMPLE_SGL 0x10000000
#define BC_PRESENT 0x01000000
pTCB
=
(
PU32
)
pTransCtrlBlock
;
pMsg
=
pMsgFrame
;
nmbrDwords
=
0
;
dprintk
(
"FillI2OMsgSGLFromTCBX
\n
"
);
dprintk
(
"TCB 0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx
\n
"
,
pTCB
[
0
],
pTCB
[
1
],
pTCB
[
2
],
pTCB
[
3
],
pTCB
[
4
]);
dprintk
(
"pTCB 0x%08ulx, pMsg 0x%08ulx
\n
"
,
(
u32
)
pTCB
,
(
u32
)
pMsg
);
nmbrBuffers
=
*
pTCB
++
;
if
(
!
nmbrBuffers
)
{
return
-
1
;
}
do
{
context
=
*
pTCB
++
;
/* buffer tag (context) */
nmbrSeg
=
*
pTCB
++
;
/* number of segments */
if
(
!
nmbrSeg
)
{
return
-
1
;
}
flags
=
SIMPLE_SGL
|
BC_PRESENT
;
if
(
1
==
nmbrSeg
)
{
flags
|=
EOB
;
if
(
1
==
nmbrBuffers
)
flags
|=
LE
;
}
/* 1st SGL buffer element has context */
pMsg
[
0
]
=
pTCB
[
0
]
|
flags
;
/* send over count (segment size) */
pMsg
[
1
]
=
context
;
pMsg
[
2
]
=
pTCB
[
1
];
/* send buffer segment physical address */
nmbrDwords
+=
3
;
pMsg
+=
3
;
pTCB
+=
2
;
if
(
--
nmbrSeg
)
{
do
{
flags
=
SIMPLE_SGL
;
if
(
1
==
nmbrSeg
)
{
flags
|=
EOB
;
if
(
1
==
nmbrBuffers
)
flags
|=
LE
;
}
pMsg
[
0
]
=
pTCB
[
0
]
|
flags
;
/* send over count */
pMsg
[
1
]
=
pTCB
[
1
];
/* send buffer segment physical address */
nmbrDwords
+=
2
;
pTCB
+=
2
;
pMsg
+=
2
;
}
while
(
--
nmbrSeg
);
}
}
while
(
--
nmbrBuffers
);
return
nmbrDwords
;
}
/*
** =========================================================================
** ProcessOutboundI2OMsg()
**
** process I2O reply message
** * change to msg structure *
** =========================================================================
*/
static
void
ProcessOutboundI2OMsg
(
PPAB
pPab
,
U32
phyAddrMsg
)
{
PU8
p8Msg
;
PU32
p32
;
/* U16 count; */
p8Msg
=
pPab
->
pLinOutMsgBlock
+
(
phyAddrMsg
-
pPab
->
outMsgBlockPhyAddr
);
p32
=
(
PU32
)
p8Msg
;
dprintk
(
"VXD: ProcessOutboundI2OMsg - pPab 0x%08ulx, phyAdr 0x%08ulx, linAdr 0x%08ulx
\n
"
,
(
u32
)
pPab
,
phyAddrMsg
,
(
u32
)
p8Msg
);
dprintk
(
"msg :0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx
\n
"
,
p32
[
0
],
p32
[
1
],
p32
[
2
],
p32
[
3
]);
dprintk
(
"msg :0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx
\n
"
,
p32
[
4
],
p32
[
5
],
p32
[
6
],
p32
[
7
]);
if
(
p32
[
4
]
>>
24
!=
I2O_REPLY_STATUS_SUCCESS
)
{
dprintk
(
"Message reply status not success
\n
"
);
return
;
}
switch
(
p8Msg
[
7
])
{
/* function code byte */
case
I2O_EXEC_SYS_TAB_SET
:
msgFlag
=
1
;
dprintk
(
"Received I2O_EXEC_SYS_TAB_SET reply
\n
"
);
break
;
case
I2O_EXEC_HRT_GET
:
msgFlag
=
1
;
dprintk
(
"Received I2O_EXEC_HRT_GET reply
\n
"
);
break
;
case
I2O_EXEC_LCT_NOTIFY
:
msgFlag
=
1
;
dprintk
(
"Received I2O_EXEC_LCT_NOTIFY reply
\n
"
);
break
;
case
I2O_EXEC_SYS_ENABLE
:
msgFlag
=
1
;
dprintk
(
"Received I2O_EXEC_SYS_ENABLE reply
\n
"
);
break
;
default:
dprintk
(
"Received UNKNOWN reply
\n
"
);
break
;
}
}
drivers/net/rclanmtl.h
deleted
100644 → 0
View file @
c7f22f7a
/*
** *************************************************************************
**
**
** R C L A N M T L . H $Revision: 6 $
**
**
** RedCreek I2O LAN Message Transport Layer header file.
**
** ---------------------------------------------------------------------
** --- Copyright (c) 1997-1999, RedCreek Communications Inc. ---
** --- All rights reserved. ---
** ---------------------------------------------------------------------
**
** File Description:
**
** Header file for host I2O (Intelligent I/O) LAN message transport layer
** API and data types.
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
** *************************************************************************
*/
#ifndef RCLANMTL_H
#define RCLANMTL_H
/* Linux specific includes */
#include <asm/types.h>
#ifdef RC_LINUX_MODULE
/* linux modules need non-library version of string functions */
#include <linux/string.h>
#else
#include <string.h>
#endif
#include <linux/delay.h>
/* for udelay() */
#include <linux/netdevice.h>
#include <linux/if_ether.h>
#include <linux/etherdevice.h>
#include <linux/skbuff.h>
#include <asm/io.h>
/* Debug stuff. Define for debug output */
#undef RCDEBUG
#ifdef RCDEBUG
#define dprintk(args...) printk(KERN_DEBUG "rc: " args)
#else
#define dprintk(args...) { }
#endif
/* Typedefs */
/* scalar data types */
typedef
__u8
U8
;
typedef
__u16
U16
;
typedef
__u32
U32
;
typedef
__u8
*
PU8
;
typedef
__u16
*
PU16
;
typedef
__u32
*
PU32
;
typedef
unsigned
long
BF
;
typedef
int
RC_RETURN
;
/*
** type PFNWAITCALLBACK
**
** pointer to void function - type used for WaitCallback in some functions
*/
typedef
void
(
*
PFNWAITCALLBACK
)
(
void
);
/* void argument avoids compiler complaint */
/*
** type PFNTXCALLBACK
**
** Pointer to user's transmit callback function. This user function is
** called from RCProcI2OMsgQ() when packet have been transmitted from buffers
** given in the RCI2OSendPacket() function. BufferContext is a pointer to
** an array of 32 bit context values. These are the values the user assigned
** and passed in the TCB to the RCI2OSendPacket() function. PcktCount
** indicates the number of buffer context values in the BufferContext[] array.
** The User's TransmitCallbackFunction should recover (put back in free queue)
** the packet buffers associated with the buffer context values.
*/
typedef
void
(
*
PFNTXCALLBACK
)
(
U32
Status
,
U16
PcktCount
,
PU32
BufferContext
,
struct
net_device
*
);
/*
** type PFNRXCALLBACK
**
** Pointer to user's receive callback function. This user function
** is called from RCProcI2OMsgQ() when packets have been received into
** previously posted packet buffers throught the RCPostRecvBuffers() function.
** The received callback function should process the Packet Descriptor Block
** pointed to by PacketDescBlock. See Packet Decription Block below.
*/
typedef
void
(
*
PFNRXCALLBACK
)
(
U32
Status
,
U8
PktCount
,
U32
BucketsRemain
,
PU32
PacketDescBlock
,
struct
net_device
*
);
/*
** type PFNCALLBACK
**
** Pointer to user's generic callback function. This user function
** can be passed to LANReset or LANShutdown and is called when the
** the reset or shutdown is complete.
** Param1 and Param2 are invalid for LANReset and LANShutdown.
*/
typedef
void
(
*
PFNCALLBACK
)
(
U32
Status
,
U32
Param1
,
U32
Param2
,
struct
net_device
*
dev
);
/*
** Message Unit CSR definitions for RedCreek PCI45 board
*/
typedef
struct
tag_rcatu
{
volatile
unsigned
long
APICRegSel
;
/* APIC Register Select */
volatile
unsigned
long
reserved0
;
volatile
unsigned
long
APICWinReg
;
/* APIC Window Register */
volatile
unsigned
long
reserved1
;
volatile
unsigned
long
InMsgReg0
;
/* inbound message register 0 */
volatile
unsigned
long
InMsgReg1
;
/* inbound message register 1 */
volatile
unsigned
long
OutMsgReg0
;
/* outbound message register 0 */
volatile
unsigned
long
OutMsgReg1
;
/* outbound message register 1 */
volatile
unsigned
long
InDoorReg
;
/* inbound doorbell register */
volatile
unsigned
long
InIntStat
;
/* inbound interrupt status register */
volatile
unsigned
long
InIntMask
;
/* inbound interrupt mask register */
volatile
unsigned
long
OutDoorReg
;
/* outbound doorbell register */
volatile
unsigned
long
OutIntStat
;
/* outbound interrupt status register */
volatile
unsigned
long
OutIntMask
;
/* outbound interrupt mask register */
volatile
unsigned
long
reserved2
;
volatile
unsigned
long
reserved3
;
volatile
unsigned
long
InQueue
;
/* inbound queue port */
volatile
unsigned
long
OutQueue
;
/* outbound queue port */
volatile
unsigned
long
reserved4
;
volatile
unsigned
long
reserver5
;
/* RedCreek extension */
volatile
unsigned
long
EtherMacLow
;
volatile
unsigned
long
EtherMacHi
;
volatile
unsigned
long
IPaddr
;
volatile
unsigned
long
IPmask
;
}
*
PATU
;
/*
** typedef PAB
**
** PCI Adapter Block - holds instance specific information.
*/
typedef
struct
{
PATU
p_atu
;
/* ptr to ATU register block */
PU8
pPci45LinBaseAddr
;
PU8
pLinOutMsgBlock
;
U32
outMsgBlockPhyAddr
;
PFNTXCALLBACK
pTransCallbackFunc
;
PFNRXCALLBACK
pRecvCallbackFunc
;
PFNCALLBACK
pRebootCallbackFunc
;
PFNCALLBACK
pCallbackFunc
;
U16
IOPState
;
U16
InboundMFrameSize
;
}
*
PPAB
;
/*
* Driver Private Area, DPA.
*/
typedef
struct
{
U8
id
;
/* the AdapterID */
/* These two field are basically for the RCioctl function.
* I could not determine if they could be avoided. (RAA)*/
U32
pci_addr
;
/* the pci address of the adapter */
U32
pci_addr_len
;
struct
pci_dev
*
pci_dev
;
struct
timer_list
timer
;
/* timer */
struct
net_device_stats
stats
;
/* the statistics structure */
unsigned
long
numOutRcvBuffers
;
/* number of outstanding receive buffers */
unsigned
char
shutdown
;
unsigned
char
reboot
;
unsigned
char
nexus
;
PU8
msgbuf
;
/* Pointer to Lan Api Private Area */
dma_addr_t
msgbuf_dma
;
PPAB
pPab
;
/* Pointer to the PCI Adapter Block */
}
*
PDPA
;
/* PCI/45 Configuration space values */
#define RC_PCI45_VENDOR_ID 0x4916
#define RC_PCI45_DEVICE_ID 0x1960
/* RedCreek API function return values */
#define RC_RTN_NO_ERROR 0
#define RC_RTN_I2O_NOT_INIT 1
#define RC_RTN_FREE_Q_EMPTY 2
#define RC_RTN_TCB_ERROR 3
#define RC_RTN_TRANSACTION_ERROR 4
#define RC_RTN_ADAPTER_ALREADY_INIT 5
#define RC_RTN_MALLOC_ERROR 6
#define RC_RTN_ADPTR_NOT_REGISTERED 7
#define RC_RTN_MSG_REPLY_TIMEOUT 8
#define RC_RTN_NO_I2O_STATUS 9
#define RC_RTN_NO_FIRM_VER 10
#define RC_RTN_NO_LINK_SPEED 11
/* Driver capability flags */
#define WARM_REBOOT_CAPABLE 0x01
/*
** Status - Transmit and Receive callback status word
**
** A 32 bit Status is returned to the TX and RX callback functions. This value
** contains both the reply status and the detailed status as follows:
**
** 32 24 16 0
** +------+------+------------+
** | Reply| | Detailed |
** |Status| 0 | Status |
** +------+------+------------+
**
** Reply Status and Detailed Status of zero indicates No Errors.
*/
/* reply message status defines */
#define I2O_REPLY_STATUS_SUCCESS 0x00
#define I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER 0x02
#define I2O_REPLY_STATUS_TRANSACTION_ERROR 0x0A
/* DetailedStatusCode defines */
#define I2O_LAN_DSC_SUCCESS 0x0000
#define I2O_LAN_DSC_DEVICE_FAILURE 0x0001
#define I2O_LAN_DSC_DESTINATION_NOT_FOUND 0x0002
#define I2O_LAN_DSC_TRANSMIT_ERROR 0x0003
#define I2O_LAN_DSC_TRANSMIT_ABORTED 0x0004
#define I2O_LAN_DSC_RECEIVE_ERROR 0x0005
#define I2O_LAN_DSC_RECEIVE_ABORTED 0x0006
#define I2O_LAN_DSC_DMA_ERROR 0x0007
#define I2O_LAN_DSC_BAD_PACKET_DETECTED 0x0008
#define I2O_LAN_DSC_OUT_OF_MEMORY 0x0009
#define I2O_LAN_DSC_BUCKET_OVERRUN 0x000A
#define I2O_LAN_DSC_IOP_INTERNAL_ERROR 0x000B
#define I2O_LAN_DSC_CANCELED 0x000C
#define I2O_LAN_DSC_INVALID_TRANSACTION_CONTEXT 0x000D
#define I2O_LAN_DSC_DESTINATION_ADDRESS_DETECTED 0x000E
#define I2O_LAN_DSC_DESTINATION_ADDRESS_OMITTED 0x000F
#define I2O_LAN_DSC_PARTIAL_PACKET_RETURNED 0x0010
/*
** Packet Description Block (Received packets)
**
** A pointer to this block structure is returned to the ReceiveCallback
** function. It contains the list of packet buffers which have either been
** filled with a packet or returned to host due to a LANReset function.
** Currently there will only be one packet per receive bucket (buffer) posted.
**
** 32 24 0
** +-----------------------+ -\
** | Buffer 1 Context | \
** +-----------------------+ \
** | 0xC0000000 | / First Bucket Descriptor
** +-----+-----------------+ /
** | 0 | packet 1 length | /
** +-----------------------+ -\
** | Buffer 2 Context | \
** +-----------------------+ \
** | 0xC0000000 | / Second Bucket Descriptor
** +-----+-----------------+ /
** | 0 | packet 2 length | /
** +-----+-----------------+ -
** | ... | ----- more bucket descriptors
** +-----------------------+ -\
** | Buffer n Context | \
** +-----------------------+ \
** | 0xC0000000 | / Last Bucket Descriptor
** +-----+-----------------+ /
** | 0 | packet n length | /
** +-----+-----------------+ -
**
** Buffer Context values are those given to adapter in the TCB on calls to
** RCPostRecvBuffers().
**
*/
/*
** Transaction Control Block (TCB) structure
**
** A structure like this is filled in by the user and passed by reference to
** RCI2OSendPacket() and RCPostRecvBuffers() functions. Minimum size is five
** 32-bit words for one buffer with one segment descriptor.
** MAX_NMBR_POST_BUFFERS_PER_MSG defines the maximum single segment buffers
** that can be described in a given TCB.
**
** 32 0
** +-----------------------+
** | Buffer Count | Number of buffers in the TCB
** +-----------------------+
** | Buffer 1 Context | first buffer reference
** +-----------------------+
** | Buffer 1 Seg Count | number of segments in buffer
** +-----------------------+
** | Buffer 1 Seg Desc 1 | first segment descriptor (size, physical address)
** +-----------------------+
** | ... | more segment descriptors (size, physical address)
** +-----------------------+
** | Buffer 1 Seg Desc n | last segment descriptor (size, physical address)
** +-----------------------+
** | Buffer 2 Context | second buffer reference
** +-----------------------+
** | Buffer 2 Seg Count | number of segments in buffer
** +-----------------------+
** | Buffer 2 Seg Desc 1 | segment descriptor (size, physical address)
** +-----------------------+
** | ... | more segment descriptors (size, physical address)
** +-----------------------+
** | Buffer 2 Seg Desc n |
** +-----------------------+
** | ... | more buffer descriptor blocks ...
** +-----------------------+
** | Buffer n Context |
** +-----------------------+
** | Buffer n Seg Count |
** +-----------------------+
** | Buffer n Seg Desc 1 |
** +-----------------------+
** | ... |
** +-----------------------+
** | Buffer n Seg Desc n |
** +-----------------------+
**
**
** A TCB for one contigous packet buffer would look like the following:
**
** 32 0
** +-----------------------+
** | 1 | one buffer in the TCB
** +-----------------------+
** | <user's Context> | user's buffer reference
** +-----------------------+
** | 1 | one segment buffer
** +-----------------------+ _
** | <buffer size> | size \
** +-----------------------+ \ segment descriptor
** | <physical address> | physical address of buffer /
** +-----------------------+ _/
**
*/
/* Buffer Segment Descriptor */
typedef
struct
{
U32
size
;
U32
phyAddress
;
}
BSD
,
*
PBSD
;
typedef
PU32
PRCTCB
;
/*
** -------------------------------------------------------------------------
** Exported functions comprising the API to the LAN I2O message transport layer
** -------------------------------------------------------------------------
*/
/*
** InitRCI2OMsgLayer()
**
** Called once prior to using the I2O LAN message transport layer. User
** provides both the physical and virual address of a locked page buffer
** that is used as a private buffer for the RedCreek I2O message
** transport layer. This buffer must be a contigous memory block of a
** minimum of 16K bytes and long word aligned. The user also must provide
** the base address of the RedCreek PCI adapter assigned by BIOS or operating
** system.
**
** Inputs: dev - the net_device struct for the device.
** TransmitCallbackFunction - address of user's TX callback function
** ReceiveCallbackFunction - address of user's RX callback function
** RebootCallbackFunction - address of user's reboot callback function
**
*/
RC_RETURN
RCInitI2OMsgLayer
(
struct
net_device
*
dev
,
PFNTXCALLBACK
TransmitCallbackFunction
,
PFNRXCALLBACK
ReceiveCallbackFunction
,
PFNCALLBACK
RebootCallbackFunction
);
/*
** RCSetRavlinIPandMask()
**
** Set the Ravlin 45/PCI cards IP address and network mask.
**
** IP address and mask must be in network byte order.
** For example, IP address 1.2.3.4 and mask 255.255.255.0 would be
** 0x04030201 and 0x00FFFFFF on a little endian machine.
**
*/
RC_RETURN
RCSetRavlinIPandMask
(
struct
net_device
*
dev
,
U32
ipAddr
,
U32
netMask
);
/*
** =========================================================================
** RCGetRavlinIPandMask()
**
** get the IP address and MASK from the card
**
** =========================================================================
*/
RC_RETURN
RCGetRavlinIPandMask
(
struct
net_device
*
dev
,
PU32
pIpAddr
,
PU32
pNetMask
,
PFNWAITCALLBACK
WaitCallback
);
/*
** RCProcI2OMsgQ()
**
** Called from user's polling loop or Interrupt Service Routine for a PCI
** interrupt from the RedCreek PCI adapter. User responsible for determining
** and hooking the PCI interrupt. This function will call the registered
** callback functions, TransmitCallbackFunction or ReceiveCallbackFunction,
** if a TX or RX transaction has completed.
*/
irqreturn_t
RCProcI2OMsgQ
(
struct
net_device
*
dev
);
/*
** Disable and Enable I2O interrupts. I2O interrupts are enabled at Init time
** but can be disabled and re-enabled through these two function calls.
** Packets will still be put into any posted received buffers and packets will
** be sent through RCI2OSendPacket() functions. Disabling I2O interrupts
** will prevent hardware interrupt to host even though the outbound I2O msg
** queue is not emtpy.
*/
RC_RETURN
RCEnableI2OInterrupts
(
struct
net_device
*
dev
);
RC_RETURN
RCDisableI2OInterrupts
(
struct
net_device
*
dev
);
/*
** RCPostRecvBuffers()
**
** Post user's page locked buffers for use by the PCI adapter to
** return ethernet packets received from the LAN. Transaction Control Block,
** provided by user, contains buffer descriptor(s) which includes a buffer
** context number along with buffer size and physical address. See TCB above.
** The buffer context and actual packet length are returned to the
** ReceiveCallbackFunction when packets have been received. Buffers posted
** to the RedCreek adapter are considered owned by the adapter until the
** context is return to user through the ReceiveCallbackFunction.
*/
RC_RETURN
RCPostRecvBuffers
(
struct
net_device
*
dev
,
PRCTCB
pTransactionCtrlBlock
);
#define MAX_NMBR_POST_BUFFERS_PER_MSG 32
/*
** RCI2OSendPacket()
**
** Send user's ethernet packet from a locked page buffer.
** Packet must have full MAC header, however without a CRC.
** Initiator context is a user provided value that is returned
** to the TransmitCallbackFunction when packet buffer is free.
** Transmit buffer are considered owned by the adapter until context's
** returned to user through the TransmitCallbackFunction.
*/
RC_RETURN
RCI2OSendPacket
(
struct
net_device
*
dev
,
U32
context
,
PRCTCB
pTransactionCtrlBlock
);
/* Ethernet Link Statistics structure */
typedef
struct
tag_RC_link_stats
{
U32
TX_good
;
/* good transmit frames */
U32
TX_maxcol
;
/* frames not TX due to MAX collisions */
U32
TX_latecol
;
/* frames not TX due to late collisions */
U32
TX_urun
;
/* frames not TX due to DMA underrun */
U32
TX_crs
;
/* frames TX with lost carrier sense */
U32
TX_def
;
/* frames deferred due to activity on link */
U32
TX_singlecol
;
/* frames TX with one and only on collision */
U32
TX_multcol
;
/* frames TX with more than one collision */
U32
TX_totcol
;
/* total collisions detected during TX */
U32
Rcv_good
;
/* good frames received */
U32
Rcv_CRCerr
;
/* frames RX and discarded with CRC errors */
U32
Rcv_alignerr
;
/* frames RX with alignment and CRC errors */
U32
Rcv_reserr
;
/* good frames discarded due to no RX buffer */
U32
Rcv_orun
;
/* RX frames lost due to FIFO overrun */
U32
Rcv_cdt
;
/* RX frames with collision during RX */
U32
Rcv_runt
;
/* RX frames shorter than 64 bytes */
}
RCLINKSTATS
,
*
P_RCLINKSTATS
;
/*
** RCGetLinkStatistics()
**
** Returns link statistics in user's structure at address StatsReturnAddr
** If given, not NULL, the function WaitCallback is called during the wait
** loop while waiting for the adapter to respond.
*/
RC_RETURN
RCGetLinkStatistics
(
struct
net_device
*
dev
,
P_RCLINKSTATS
StatsReturnAddr
,
PFNWAITCALLBACK
WaitCallback
);
/*
** RCGetLinkStatus()
**
** Return link status, up or down, to user's location addressed by ReturnAddr.
** If given, not NULL, the function WaitCallback is called during the wait
** loop while waiting for the adapter to respond.
*/
RC_RETURN
RCGetLinkStatus
(
struct
net_device
*
dev
,
PU32
pReturnStatus
,
PFNWAITCALLBACK
WaitCallback
);
/* Link Status defines - value returned in pReturnStatus */
#define RC_LAN_LINK_STATUS_DOWN 0
#define RC_LAN_LINK_STATUS_UP 1
/*
** RCGetMAC()
**
** Get the current MAC address assigned to user. RedCreek Ravlin 45/PCI
** has two MAC addresses. One which is private to the PCI Card, and
** another MAC which is given to the user as its link layer MAC address. The
** adapter runs in promiscous mode because of the dual address requirement.
** The MAC address is returned to the unsigned char array pointer to by mac.
*/
RC_RETURN
RCGetMAC
(
struct
net_device
*
dev
,
PFNWAITCALLBACK
WaitCallback
);
/*
** RCSetMAC()
**
** Set a new user port MAC address. This address will be returned on
** subsequent RCGetMAC() calls.
*/
RC_RETURN
RCSetMAC
(
struct
net_device
*
dev
,
PU8
mac
);
/*
** RCSetLinkSpeed()
**
** set adapter's link speed based on given input code.
*/
RC_RETURN
RCSetLinkSpeed
(
struct
net_device
*
dev
,
U16
LinkSpeedCode
);
/* Set link speed codes */
#define LNK_SPD_AUTO_NEG_NWAY 0
#define LNK_SPD_100MB_FULL 1
#define LNK_SPD_100MB_HALF 2
#define LNK_SPD_10MB_FULL 3
#define LNK_SPD_10MB_HALF 4
/*
** RCGetLinkSpeed()
**
** Return link speed code.
*/
/* Return link speed codes */
#define LNK_SPD_UNKNOWN 0
#define LNK_SPD_100MB_FULL 1
#define LNK_SPD_100MB_HALF 2
#define LNK_SPD_10MB_FULL 3
#define LNK_SPD_10MB_HALF 4
RC_RETURN
RCGetLinkSpeed
(
struct
net_device
*
dev
,
PU32
pLinkSpeedCode
,
PFNWAITCALLBACK
WaitCallback
);
/*
** =========================================================================
** RCSetPromiscuousMode(struct net_device *dev, U16 Mode)
**
** Defined values for Mode:
** 0 - turn off promiscuous mode
** 1 - turn on promiscuous mode
**
** =========================================================================
*/
#define PROMISCUOUS_MODE_OFF 0
#define PROMISCUOUS_MODE_ON 1
RC_RETURN
RCSetPromiscuousMode
(
struct
net_device
*
dev
,
U16
Mode
);
/*
** =========================================================================
** RCGetPromiscuousMode(struct net_device *dev, PU32 pMode, PFNWAITCALLBACK WaitCallback)
**
** get promiscuous mode setting
**
** Possible return values placed in pMode:
** 0 = promisuous mode not set
** 1 = promisuous mode is set
**
** =========================================================================
*/
RC_RETURN
RCGetPromiscuousMode
(
struct
net_device
*
dev
,
PU32
pMode
,
PFNWAITCALLBACK
WaitCallback
);
/*
** =========================================================================
** RCSetBroadcastMode(struct net_device *dev, U16 Mode)
**
** Defined values for Mode:
** 0 - turn off promiscuous mode
** 1 - turn on promiscuous mode
**
** =========================================================================
*/
#define BROADCAST_MODE_OFF 0
#define BROADCAST_MODE_ON 1
RC_RETURN
RCSetBroadcastMode
(
struct
net_device
*
dev
,
U16
Mode
);
/*
** =========================================================================
** RCGetBroadcastMode(struct net_device *dev, PU32 pMode, PFNWAITCALLBACK WaitCallback)
**
** get broadcast mode setting
**
** Possible return values placed in pMode:
** 0 = broadcast mode not set
** 1 = broadcast mode is set
**
** =========================================================================
*/
RC_RETURN
RCGetBroadcastMode
(
struct
net_device
*
dev
,
PU32
pMode
,
PFNWAITCALLBACK
WaitCallback
);
/*
** =========================================================================
** RCReportDriverCapability(struct net_device *dev, U32 capability)
**
** Currently defined bits:
** WARM_REBOOT_CAPABLE 0x01
**
** =========================================================================
*/
RC_RETURN
RCReportDriverCapability
(
struct
net_device
*
dev
,
U32
capability
);
/*
** RCGetFirmwareVer()
**
** Return firmware version in the form "SoftwareVersion : Bt BootVersion"
**
** WARNING: user's space pointed to by pFirmString should be at least 60 bytes.
*/
RC_RETURN
RCGetFirmwareVer
(
struct
net_device
*
dev
,
PU8
pFirmString
,
PFNWAITCALLBACK
WaitCallback
);
/*
** ----------------------------------------------
** LAN adapter Reset and Shutdown functions
** ----------------------------------------------
*/
/* resource flag bit assignments for RCResetLANCard() & RCShutdownLANCard() */
#define RC_RESOURCE_RETURN_POSTED_RX_BUCKETS 0x0001
#define RC_RESOURCE_RETURN_PEND_TX_BUFFERS 0x0002
/*
** RCResetLANCard()
**
** Reset LAN card operation. Causes a software reset of the ethernet
** controller and restarts the command and receive units. Depending on
** the ResourceFlags given, the buffers are either returned to the
** host with reply status of I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER and
** detailed status of I2O_LAN_DSC_CANCELED (new receive buffers must be
** posted after issuing this) OR the buffers are kept and reused by
** the ethernet controller. If CallbackFunction is not NULL, the function
** will be called when the reset is complete. If the CallbackFunction is
** NULL,a 1 will be put into the ReturnAddr after waiting for the reset
** to complete (please disable I2O interrupts during this method).
** Any outstanding transmit or receive buffers that are complete will be
** returned via the normal reply messages before the requested resource
** buffers are returned.
** A call to RCPostRecvBuffers() is needed to return the ethernet to full
** operation if the receive buffers were returned during LANReset.
** Note: The IOP status is not affected by a LAN reset.
*/
RC_RETURN
RCResetLANCard
(
struct
net_device
*
dev
,
U16
ResourceFlags
,
PU32
ReturnAddr
,
PFNCALLBACK
CallbackFunction
);
/*
** RCShutdownLANCard()
**
** Shutdown LAN card operation and put into an idle (suspended) state.
** The LAN card is restarted with RCResetLANCard() function.
** Depending on the ResourceFlags given, the buffers are either returned
** to the host with reply status of I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER
** and detailed status of I2O_LAN_DSC_CANCELED (new receive buffers must be
** posted after issuing this) OR the buffers are kept and reused by
** the ethernet controller. If CallbackFunction is not NULL, the function
** will be called when the reset is complete. If the CallbackFunction is
** NULL,a 1 will be put into the ReturnAddr after waiting for the reset
** to complete (please disable I2O interrupts during this method).
** Any outstanding transmit or receive buffers that are complete will be
** returned via the normal reply messages before the requested resource
** buffers are returned.
** Note: The IOP status is not affected by a LAN shutdown.
*/
RC_RETURN
RCShutdownLANCard
(
struct
net_device
*
dev
,
U16
ResourceFlags
,
PU32
ReturnAddr
,
PFNCALLBACK
CallbackFunction
);
/*
** RCResetIOP();
** Initializes IOPState to I2O_IOP_STATE_RESET.
** Stops access to outbound message Q.
** Discards any outstanding transmit or posted receive buffers.
** Clears outbound message Q.
*/
RC_RETURN
RCResetIOP
(
struct
net_device
*
dev
);
#endif
/* RCLANMTL_H */
drivers/net/rcpci45.c
deleted
100644 → 0
View file @
c7f22f7a
/*
**
** RCpci45.c
**
**
**
** ---------------------------------------------------------------------
** --- Copyright (c) 1998, 1999, RedCreek Communications Inc. ---
** --- All rights reserved. ---
** ---------------------------------------------------------------------
**
** Written by Pete Popov and Brian Moyle.
**
** Known Problems
**
** None known at this time.
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
** Francois Romieu, Apr 2003: Converted to pci DMA mapping API.
**
** Pete Popov, Oct 2001: Fixed a few bugs to make the driver functional
** again. Note that this card is not supported or manufactured by
** RedCreek anymore.
**
** Rasmus Andersen, December 2000: Converted to new PCI API and general
** cleanup.
**
** Pete Popov, January 11,99: Fixed a couple of 2.1.x problems
** (virt_to_bus() not called), tested it under 2.2pre5 (as a module), and
** added a #define(s) to enable the use of the same file for both, the 2.0.x
** kernels as well as the 2.1.x.
**
** Ported to 2.1.x by Alan Cox 1998/12/9.
**
** Sometime in mid 1998, written by Pete Popov and Brian Moyle.
**
***************************************************************************/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/in.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/timer.h>
#include <asm/irq.h>
/* For NR_IRQS only. */
#include <asm/bitops.h>
#include <asm/uaccess.h>
static
char
version
[]
__initdata
=
"RedCreek Communications PCI linux driver version 2.21
\n
"
;
#define RC_LINUX_MODULE
#include "rclanmtl.h"
#include "rcif.h"
#define RUN_AT(x) (jiffies + (x))
#define NEW_MULTICAST
#define MAX_ETHER_SIZE 1520
#define MAX_NMBR_RCV_BUFFERS 96
#define RC_POSTED_BUFFERS_LOW_MARK MAX_NMBR_RCV_BUFFERS-16
#define BD_SIZE 3
/* Bucket Descriptor size */
#define BD_LEN_OFFSET 2
/* Bucket Descriptor offset to length field */
/* RedCreek LAN device Target ID */
#define RC_LAN_TARGET_ID 0x10
/* RedCreek's OSM default LAN receive Initiator */
#define DEFAULT_RECV_INIT_CONTEXT 0xA17
/* minimum msg buffer size needed by the card
* Note that the size of this buffer is hard code in the
* ipsec card's firmware. Thus, the size MUST be a minimum
* of 16K. Otherwise the card will end up using memory
* that does not belong to it.
*/
#define MSG_BUF_SIZE 16384
/* 2003/04/20: I don't know about the hardware ability but the driver won't
* play safe with 64 bit addressing and DAC without NETIF_F_HIGHDMA doesn't
* really make sense anyway. Let's play safe - romieu.
*/
#define RCPCI45_DMA_MASK ((u64) 0xffffffff)
static
U32
DriverControlWord
;
static
void
rc_timer
(
unsigned
long
);
static
int
RCopen
(
struct
net_device
*
);
static
int
RC_xmit_packet
(
struct
sk_buff
*
,
struct
net_device
*
);
static
irqreturn_t
RCinterrupt
(
int
,
void
*
,
struct
pt_regs
*
);
static
int
RCclose
(
struct
net_device
*
dev
);
static
struct
net_device_stats
*
RCget_stats
(
struct
net_device
*
);
static
int
RCioctl
(
struct
net_device
*
,
struct
ifreq
*
,
int
);
static
int
RCconfig
(
struct
net_device
*
,
struct
ifmap
*
);
static
void
RCxmit_callback
(
U32
,
U16
,
PU32
,
struct
net_device
*
);
static
void
RCrecv_callback
(
U32
,
U8
,
U32
,
PU32
,
struct
net_device
*
);
static
void
RCreset_callback
(
U32
,
U32
,
U32
,
struct
net_device
*
);
static
void
RCreboot_callback
(
U32
,
U32
,
U32
,
struct
net_device
*
);
static
int
RC_allocate_and_post_buffers
(
struct
net_device
*
,
int
);
static
struct
pci_device_id
rcpci45_pci_table
[]
=
{
{
PCI_VENDOR_ID_REDCREEK
,
PCI_DEVICE_ID_RC45
,
PCI_ANY_ID
,
PCI_ANY_ID
,},
{}
};
MODULE_DEVICE_TABLE
(
pci
,
rcpci45_pci_table
);
MODULE_LICENSE
(
"GPL"
);
static
void
__devexit
rcpci45_remove_one
(
struct
pci_dev
*
pdev
)
{
struct
net_device
*
dev
=
pci_get_drvdata
(
pdev
);
PDPA
pDpa
=
dev
->
priv
;
RCResetIOP
(
dev
);
unregister_netdev
(
dev
);
free_irq
(
dev
->
irq
,
dev
);
iounmap
((
void
*
)
dev
->
base_addr
);
pci_release_regions
(
pdev
);
pci_free_consistent
(
pdev
,
MSG_BUF_SIZE
,
pDpa
->
msgbuf
,
pDpa
->
msgbuf_dma
);
if
(
pDpa
->
pPab
)
kfree
(
pDpa
->
pPab
);
free_netdev
(
dev
);
pci_set_drvdata
(
pdev
,
NULL
);
}
static
int
rcpci45_init_one
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
{
unsigned
long
*
vaddr
;
PDPA
pDpa
;
int
error
;
static
int
card_idx
=
-
1
;
struct
net_device
*
dev
;
unsigned
long
pci_start
,
pci_len
;
card_idx
++
;
/*
* Allocate and fill new device structure.
* We need enough for struct net_device plus DPA plus the LAN
* API private area, which requires a minimum of 16KB. The top
* of the allocated area will be assigned to struct net_device;
* the next chunk will be assigned to DPA; and finally, the rest
* will be assigned to the LAN API layer.
*/
dev
=
alloc_etherdev
(
sizeof
(
*
pDpa
));
if
(
!
dev
)
{
printk
(
KERN_ERR
"(rcpci45 driver:) alloc_etherdev alloc failed
\n
"
);
error
=
-
ENOMEM
;
goto
err_out
;
}
SET_MODULE_OWNER
(
dev
);
SET_NETDEV_DEV
(
dev
,
&
pdev
->
dev
);
error
=
pci_enable_device
(
pdev
);
if
(
error
)
{
printk
(
KERN_ERR
"(rcpci45 driver:) %d: pci enable device error
\n
"
,
card_idx
);
goto
err_out
;
}
pci_start
=
pci_resource_start
(
pdev
,
0
);
pci_len
=
pci_resource_len
(
pdev
,
0
);
printk
(
"pci_start %lx pci_len %lx
\n
"
,
pci_start
,
pci_len
);
pci_set_drvdata
(
pdev
,
dev
);
pDpa
=
dev
->
priv
;
pDpa
->
id
=
card_idx
;
pDpa
->
pci_dev
=
pdev
;
pDpa
->
pci_addr
=
pci_start
;
if
(
!
pci_start
||
!
(
pci_resource_flags
(
pdev
,
0
)
&
IORESOURCE_MEM
))
{
printk
(
KERN_ERR
"(rcpci45 driver:) No PCI mem resources! Aborting
\n
"
);
error
=
-
EBUSY
;
goto
err_out_free_dev
;
}
/*
* pDpa->msgbuf is where the card will dma the I2O
* messages. Thus, we need contiguous physical pages of memory.
* 2003/04/20: pci_alloc_consistent() provides well over the needed
* alignment on a 256 bytes boundary for the LAN API private area.
* Thus it isn't needed anymore to align it by hand.
*/
pDpa
->
msgbuf
=
pci_alloc_consistent
(
pdev
,
MSG_BUF_SIZE
,
&
pDpa
->
msgbuf_dma
);
if
(
!
pDpa
->
msgbuf
)
{
printk
(
KERN_ERR
"(rcpci45 driver:) \
Could not allocate %d byte memory for the \
private msgbuf!
\n
"
,
MSG_BUF_SIZE
);
error
=
-
ENOMEM
;
goto
err_out_free_dev
;
}
/* The adapter is accessible through memory-access read/write, not
* I/O read/write. Thus, we need to map it to some virtual address
* area in order to access the registers as normal memory.
*/
error
=
pci_request_regions
(
pdev
,
dev
->
name
);
if
(
error
)
goto
err_out_free_msgbuf
;
error
=
pci_set_dma_mask
(
pdev
,
RCPCI45_DMA_MASK
);
if
(
error
)
{
printk
(
KERN_ERR
"(rcpci45 driver:) pci_set_dma_mask failed!
\n
"
);
goto
err_out_free_region
;
}
vaddr
=
(
ulong
*
)
ioremap
(
pci_start
,
pci_len
);
if
(
!
vaddr
)
{
printk
(
KERN_ERR
"(rcpci45 driver:) \
Unable to remap address range from %lu to %lu
\n
"
,
pci_start
,
pci_start
+
pci_len
);
error
=
-
EIO
;
goto
err_out_free_region
;
}
dev
->
base_addr
=
(
unsigned
long
)
vaddr
;
dev
->
irq
=
pdev
->
irq
;
dev
->
open
=
&
RCopen
;
dev
->
hard_start_xmit
=
&
RC_xmit_packet
;
dev
->
stop
=
&
RCclose
;
dev
->
get_stats
=
&
RCget_stats
;
dev
->
do_ioctl
=
&
RCioctl
;
dev
->
set_config
=
&
RCconfig
;
if
((
error
=
register_netdev
(
dev
)))
goto
err_out_iounmap
;
return
0
;
/* success */
err_out_iounmap:
iounmap
((
void
*
)
dev
->
base_addr
);
err_out_free_region:
pci_release_regions
(
pdev
);
err_out_free_msgbuf:
pci_free_consistent
(
pdev
,
MSG_BUF_SIZE
,
pDpa
->
msgbuf
,
pDpa
->
msgbuf_dma
);
err_out_free_dev:
free_netdev
(
dev
);
err_out:
card_idx
--
;
return
error
;
}
static
struct
pci_driver
rcpci45_driver
=
{
.
name
=
"rcpci45"
,
.
id_table
=
rcpci45_pci_table
,
.
probe
=
rcpci45_init_one
,
.
remove
=
__devexit_p
(
rcpci45_remove_one
),
};
static
int
__init
rcpci_init_module
(
void
)
{
int
rc
=
pci_module_init
(
&
rcpci45_driver
);
if
(
!
rc
)
printk
(
KERN_ERR
"%s"
,
version
);
return
rc
;
}
static
int
RCopen
(
struct
net_device
*
dev
)
{
int
post_buffers
=
MAX_NMBR_RCV_BUFFERS
;
PDPA
pDpa
=
dev
->
priv
;
int
count
=
0
;
int
requested
=
0
;
int
error
;
if
(
pDpa
->
nexus
)
{
/* This is not the first time RCopen is called. Thus,
* the interface was previously opened and later closed
* by RCclose(). RCclose() does a Shutdown; to wake up
* the adapter, a reset is mandatory before we can post
* receive buffers. However, if the adapter initiated
* a reboot while the interface was closed -- and interrupts
* were turned off -- we need will need to reinitialize
* the adapter, rather than simply waking it up.
*/
printk
(
KERN_INFO
"Waking up adapter...
\n
"
);
RCResetLANCard
(
dev
,
0
,
0
,
0
);
}
else
{
pDpa
->
nexus
=
1
;
/*
* RCInitI2OMsgLayer is done only once, unless the
* adapter was sent a warm reboot
*/
error
=
RCInitI2OMsgLayer
(
dev
,
(
PFNTXCALLBACK
)
RCxmit_callback
,
(
PFNRXCALLBACK
)
RCrecv_callback
,
(
PFNCALLBACK
)
RCreboot_callback
);
if
(
error
)
{
printk
(
KERN_ERR
"%s: Unable to init msg layer (%x)
\n
"
,
dev
->
name
,
error
);
goto
err_out
;
}
if
((
error
=
RCGetMAC
(
dev
,
NULL
)))
{
printk
(
KERN_ERR
"%s: Unable to get adapter MAC
\n
"
,
dev
->
name
);
goto
err_out
;
}
}
/* Request a shared interrupt line. */
error
=
request_irq
(
dev
->
irq
,
RCinterrupt
,
SA_SHIRQ
,
dev
->
name
,
dev
);
if
(
error
)
{
printk
(
KERN_ERR
"%s: unable to get IRQ %d
\n
"
,
dev
->
name
,
dev
->
irq
);
goto
err_out
;
}
DriverControlWord
|=
WARM_REBOOT_CAPABLE
;
RCReportDriverCapability
(
dev
,
DriverControlWord
);
printk
(
KERN_INFO
"%s: RedCreek Communications IPSEC VPN adapter
\n
"
,
dev
->
name
);
RCEnableI2OInterrupts
(
dev
);
while
(
post_buffers
)
{
if
(
post_buffers
>
MAX_NMBR_POST_BUFFERS_PER_MSG
)
requested
=
MAX_NMBR_POST_BUFFERS_PER_MSG
;
else
requested
=
post_buffers
;
count
=
RC_allocate_and_post_buffers
(
dev
,
requested
);
if
(
count
<
requested
)
{
/*
* Check to see if we were able to post
* any buffers at all.
*/
if
(
post_buffers
==
MAX_NMBR_RCV_BUFFERS
)
{
printk
(
KERN_ERR
"%s: \
unable to allocate any buffers
\n
"
,
dev
->
name
);
goto
err_out_free_irq
;
}
printk
(
KERN_WARNING
"%s: \
unable to allocate all requested buffers
\n
"
,
dev
->
name
);
break
;
/* we'll try to post more buffers later */
}
else
post_buffers
-=
count
;
}
pDpa
->
numOutRcvBuffers
=
MAX_NMBR_RCV_BUFFERS
-
post_buffers
;
pDpa
->
shutdown
=
0
;
/* just in case */
netif_start_queue
(
dev
);
return
0
;
err_out_free_irq:
free_irq
(
dev
->
irq
,
dev
);
err_out:
return
error
;
}
static
int
RC_xmit_packet
(
struct
sk_buff
*
skb
,
struct
net_device
*
dev
)
{
PDPA
pDpa
=
dev
->
priv
;
singleTCB
tcb
;
psingleTCB
ptcb
=
&
tcb
;
RC_RETURN
status
=
0
;
netif_stop_queue
(
dev
);
if
(
pDpa
->
shutdown
||
pDpa
->
reboot
)
{
printk
(
"RC_xmit_packet: tbusy!
\n
"
);
return
1
;
}
/*
* The user is free to reuse the TCB after RCI2OSendPacket()
* returns, since the function copies the necessary info into its
* own private space. Thus, our TCB can be a local structure.
* The skb, on the other hand, will be freed up in our interrupt
* handler.
*/
ptcb
->
bcount
=
1
;
/*
* we'll get the context when the adapter interrupts us to tell us that
* the transmission is done. At that time, we can free skb.
*/
ptcb
->
b
.
context
=
(
U32
)
skb
;
ptcb
->
b
.
scount
=
1
;
ptcb
->
b
.
size
=
skb
->
len
;
ptcb
->
b
.
addr
=
pci_map_single
(
pDpa
->
pci_dev
,
skb
->
data
,
skb
->
len
,
PCI_DMA_TODEVICE
);
if
((
status
=
RCI2OSendPacket
(
dev
,
(
U32
)
NULL
,
(
PRCTCB
)
ptcb
))
!=
RC_RTN_NO_ERROR
)
{
printk
(
"%s: send error 0x%x
\n
"
,
dev
->
name
,
(
uint
)
status
);
return
1
;
}
else
{
dev
->
trans_start
=
jiffies
;
netif_wake_queue
(
dev
);
}
/*
* That's it!
*/
return
0
;
}
/*
* RCxmit_callback()
*
* The transmit callback routine. It's called by RCProcI2OMsgQ()
* because the adapter is done with one or more transmit buffers and
* it's returning them to us, or we asked the adapter to return the
* outstanding transmit buffers by calling RCResetLANCard() with
* RC_RESOURCE_RETURN_PEND_TX_BUFFERS flag.
* All we need to do is free the buffers.
*/
static
void
RCxmit_callback
(
U32
Status
,
U16
PcktCount
,
PU32
BufferContext
,
struct
net_device
*
dev
)
{
struct
sk_buff
*
skb
;
PDPA
pDpa
=
dev
->
priv
;
if
(
!
pDpa
)
{
printk
(
KERN_ERR
"%s: Fatal Error in xmit callback, !pDpa
\n
"
,
dev
->
name
);
return
;
}
if
(
Status
!=
I2O_REPLY_STATUS_SUCCESS
)
printk
(
KERN_INFO
"%s: xmit_callback: Status = 0x%x
\n
"
,
dev
->
name
,
(
uint
)
Status
);
if
(
pDpa
->
shutdown
||
pDpa
->
reboot
)
printk
(
KERN_INFO
"%s: xmit callback: shutdown||reboot
\n
"
,
dev
->
name
);
while
(
PcktCount
--
)
{
skb
=
(
struct
sk_buff
*
)
(
BufferContext
[
0
]);
BufferContext
++
;
pci_unmap_single
(
pDpa
->
pci_dev
,
BufferContext
[
1
],
skb
->
len
,
PCI_DMA_TODEVICE
);
dev_kfree_skb_irq
(
skb
);
}
netif_wake_queue
(
dev
);
}
static
void
RCreset_callback
(
U32
Status
,
U32
p1
,
U32
p2
,
struct
net_device
*
dev
)
{
PDPA
pDpa
=
dev
->
priv
;
printk
(
"RCreset_callback Status 0x%x
\n
"
,
(
uint
)
Status
);
/*
* Check to see why we were called.
*/
if
(
pDpa
->
shutdown
)
{
printk
(
KERN_INFO
"%s: shutting down interface
\n
"
,
dev
->
name
);
pDpa
->
shutdown
=
0
;
pDpa
->
reboot
=
0
;
}
else
if
(
pDpa
->
reboot
)
{
printk
(
KERN_INFO
"%s: reboot, shutdown adapter
\n
"
,
dev
->
name
);
/*
* We don't set any of the flags in RCShutdownLANCard()
* and we don't pass a callback routine to it.
* The adapter will have already initiated the reboot by
* the time the function returns.
*/
RCDisableI2OInterrupts
(
dev
);
RCShutdownLANCard
(
dev
,
0
,
0
,
0
);
printk
(
KERN_INFO
"%s: scheduling timer...
\n
"
,
dev
->
name
);
init_timer
(
&
pDpa
->
timer
);
pDpa
->
timer
.
expires
=
RUN_AT
((
40
*
HZ
)
/
10
);
/* 4 sec. */
pDpa
->
timer
.
data
=
(
unsigned
long
)
dev
;
pDpa
->
timer
.
function
=
&
rc_timer
;
/* timer handler */
add_timer
(
&
pDpa
->
timer
);
}
}
static
void
RCreboot_callback
(
U32
Status
,
U32
p1
,
U32
p2
,
struct
net_device
*
dev
)
{
PDPA
pDpa
=
dev
->
priv
;
printk
(
KERN_INFO
"%s: reboot: rcv buffers outstanding = %d
\n
"
,
dev
->
name
,
(
uint
)
pDpa
->
numOutRcvBuffers
);
if
(
pDpa
->
shutdown
)
{
printk
(
KERN_INFO
"%s: skip reboot, shutdown initiated
\n
"
,
dev
->
name
);
return
;
}
pDpa
->
reboot
=
1
;
/*
* OK, we reset the adapter and ask it to return all
* outstanding transmit buffers as well as the posted
* receive buffers. When the adapter is done returning
* those buffers, it will call our RCreset_callback()
* routine. In that routine, we'll call RCShutdownLANCard()
* to tell the adapter that it's OK to start the reboot and
* schedule a timer callback routine to execute 3 seconds
* later; this routine will reinitialize the adapter at that time.
*/
RCResetLANCard
(
dev
,
RC_RESOURCE_RETURN_POSTED_RX_BUCKETS
|
RC_RESOURCE_RETURN_PEND_TX_BUFFERS
,
0
,
(
PFNCALLBACK
)
RCreset_callback
);
}
/*
* RCrecv_callback()
*
* The receive packet callback routine. This is called by
* RCProcI2OMsgQ() after the adapter posts buffers which have been
* filled (one ethernet packet per buffer).
*/
static
void
RCrecv_callback
(
U32
Status
,
U8
PktCount
,
U32
BucketsRemain
,
PU32
PacketDescBlock
,
struct
net_device
*
dev
)
{
U32
len
,
count
;
PDPA
pDpa
=
dev
->
priv
;
struct
sk_buff
*
skb
;
singleTCB
tcb
;
psingleTCB
ptcb
=
&
tcb
;
ptcb
->
bcount
=
1
;
if
((
pDpa
->
shutdown
||
pDpa
->
reboot
)
&&
!
Status
)
printk
(
KERN_INFO
"%s: shutdown||reboot && !Status (%d)
\n
"
,
dev
->
name
,
PktCount
);
if
((
Status
!=
I2O_REPLY_STATUS_SUCCESS
)
||
pDpa
->
shutdown
)
{
/*
* Free whatever buffers the adapter returned, but don't
* pass them to the kernel.
*/
if
(
!
pDpa
->
shutdown
&&
!
pDpa
->
reboot
)
printk
(
KERN_INFO
"%s: recv error status = 0x%x
\n
"
,
dev
->
name
,
(
uint
)
Status
);
else
printk
(
KERN_DEBUG
"%s: Returning %d buffs stat 0x%x
\n
"
,
dev
->
name
,
PktCount
,
(
uint
)
Status
);
/*
* TO DO: check the nature of the failure and put the
* adapter in failed mode if it's a hard failure.
* Send a reset to the adapter and free all outstanding memory.
*/
if
(
PacketDescBlock
)
{
while
(
PktCount
--
)
{
skb
=
(
struct
sk_buff
*
)
PacketDescBlock
[
0
];
dev_kfree_skb
(
skb
);
pDpa
->
numOutRcvBuffers
--
;
/* point to next context field */
PacketDescBlock
+=
BD_SIZE
;
}
}
return
;
}
else
{
while
(
PktCount
--
)
{
skb
=
(
struct
sk_buff
*
)
PacketDescBlock
[
0
];
len
=
PacketDescBlock
[
2
];
skb
->
dev
=
dev
;
skb_put
(
skb
,
len
);
/* adjust length and tail */
skb
->
protocol
=
eth_type_trans
(
skb
,
dev
);
netif_rx
(
skb
);
/* send the packet to the kernel */
dev
->
last_rx
=
jiffies
;
pDpa
->
numOutRcvBuffers
--
;
/* point to next context field */
PacketDescBlock
+=
BD_SIZE
;
}
}
/*
* Replenish the posted receive buffers.
* DO NOT replenish buffers if the driver has already
* initiated a reboot or shutdown!
*/
if
(
!
pDpa
->
shutdown
&&
!
pDpa
->
reboot
)
{
count
=
RC_allocate_and_post_buffers
(
dev
,
MAX_NMBR_RCV_BUFFERS
-
pDpa
->
numOutRcvBuffers
);
pDpa
->
numOutRcvBuffers
+=
count
;
}
}
/*
* RCinterrupt()
*
* Interrupt handler.
* This routine sets up a couple of pointers and calls
* RCProcI2OMsgQ(), which in turn process the message and
* calls one of our callback functions.
*/
static
irqreturn_t
RCinterrupt
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
PDPA
pDpa
;
struct
net_device
*
dev
=
dev_id
;
pDpa
=
dev
->
priv
;
if
(
pDpa
->
shutdown
)
printk
(
KERN_DEBUG
"%s: shutdown, service irq
\n
"
,
dev
->
name
);
return
RCProcI2OMsgQ
(
dev
);
}
#define REBOOT_REINIT_RETRY_LIMIT 4
static
void
rc_timer
(
unsigned
long
data
)
{
struct
net_device
*
dev
=
(
struct
net_device
*
)
data
;
PDPA
pDpa
=
dev
->
priv
;
int
init_status
;
static
int
retry
;
int
post_buffers
=
MAX_NMBR_RCV_BUFFERS
;
int
count
=
0
;
int
requested
=
0
;
if
(
pDpa
->
reboot
)
{
init_status
=
RCInitI2OMsgLayer
(
dev
,
(
PFNTXCALLBACK
)
RCxmit_callback
,
(
PFNRXCALLBACK
)
RCrecv_callback
,
(
PFNCALLBACK
)
RCreboot_callback
);
switch
(
init_status
)
{
case
RC_RTN_NO_ERROR
:
pDpa
->
reboot
=
0
;
pDpa
->
shutdown
=
0
;
/* just in case */
RCReportDriverCapability
(
dev
,
DriverControlWord
);
RCEnableI2OInterrupts
(
dev
);
if
(
!
(
dev
->
flags
&
IFF_UP
))
{
retry
=
0
;
return
;
}
while
(
post_buffers
)
{
if
(
post_buffers
>
MAX_NMBR_POST_BUFFERS_PER_MSG
)
requested
=
MAX_NMBR_POST_BUFFERS_PER_MSG
;
else
requested
=
post_buffers
;
count
=
RC_allocate_and_post_buffers
(
dev
,
requested
);
post_buffers
-=
count
;
if
(
count
<
requested
)
break
;
}
pDpa
->
numOutRcvBuffers
=
MAX_NMBR_RCV_BUFFERS
-
post_buffers
;
printk
(
"Initialization done.
\n
"
);
netif_wake_queue
(
dev
);
retry
=
0
;
return
;
case
RC_RTN_FREE_Q_EMPTY
:
retry
++
;
printk
(
KERN_WARNING
"%s inbound free q empty
\n
"
,
dev
->
name
);
break
;
default:
retry
++
;
printk
(
KERN_WARNING
"%s bad stat after reboot: %d
\n
"
,
dev
->
name
,
init_status
);
break
;
}
if
(
retry
>
REBOOT_REINIT_RETRY_LIMIT
)
{
printk
(
KERN_WARNING
"%s unable to reinitialize adapter after reboot
\n
"
,
dev
->
name
);
printk
(
KERN_WARNING
"%s shutting down interface
\n
"
,
dev
->
name
);
RCDisableI2OInterrupts
(
dev
);
dev
->
flags
&=
~
IFF_UP
;
}
else
{
printk
(
KERN_INFO
"%s: rescheduling timer...
\n
"
,
dev
->
name
);
init_timer
(
&
pDpa
->
timer
);
pDpa
->
timer
.
expires
=
RUN_AT
((
40
*
HZ
)
/
10
);
pDpa
->
timer
.
data
=
(
unsigned
long
)
dev
;
pDpa
->
timer
.
function
=
&
rc_timer
;
add_timer
(
&
pDpa
->
timer
);
}
}
else
printk
(
KERN_WARNING
"%s: unexpected timer irq
\n
"
,
dev
->
name
);
}
static
int
RCclose
(
struct
net_device
*
dev
)
{
PDPA
pDpa
=
dev
->
priv
;
printk
(
"RCclose
\n
"
);
netif_stop_queue
(
dev
);
if
(
pDpa
->
reboot
)
{
printk
(
KERN_INFO
"%s skipping reset -- adapter already in reboot mode
\n
"
,
dev
->
name
);
dev
->
flags
&=
~
IFF_UP
;
pDpa
->
shutdown
=
1
;
return
0
;
}
pDpa
->
shutdown
=
1
;
/*
* We can't allow the driver to be unloaded until the adapter returns
* all posted receive buffers. It doesn't hurt to tell the adapter
* to return all posted receive buffers and outstanding xmit buffers,
* even if there are none.
*/
RCShutdownLANCard
(
dev
,
RC_RESOURCE_RETURN_POSTED_RX_BUCKETS
|
RC_RESOURCE_RETURN_PEND_TX_BUFFERS
,
0
,
(
PFNCALLBACK
)
RCreset_callback
);
dev
->
flags
&=
~
IFF_UP
;
return
0
;
}
static
struct
net_device_stats
*
RCget_stats
(
struct
net_device
*
dev
)
{
RCLINKSTATS
RCstats
;
PDPA
pDpa
=
dev
->
priv
;
if
(
!
pDpa
)
{
return
0
;
}
else
if
(
!
(
dev
->
flags
&
IFF_UP
))
{
return
0
;
}
memset
(
&
RCstats
,
0
,
sizeof
(
RCLINKSTATS
));
if
((
RCGetLinkStatistics
(
dev
,
&
RCstats
,
(
void
*
)
0
))
==
RC_RTN_NO_ERROR
)
{
/* total packets received */
pDpa
->
stats
.
rx_packets
=
RCstats
.
Rcv_good
/* total packets transmitted */
;
pDpa
->
stats
.
tx_packets
=
RCstats
.
TX_good
;
pDpa
->
stats
.
rx_errors
=
RCstats
.
Rcv_CRCerr
+
RCstats
.
Rcv_alignerr
+
RCstats
.
Rcv_reserr
+
RCstats
.
Rcv_orun
+
RCstats
.
Rcv_cdt
+
RCstats
.
Rcv_runt
;
pDpa
->
stats
.
tx_errors
=
RCstats
.
TX_urun
+
RCstats
.
TX_crs
+
RCstats
.
TX_def
+
RCstats
.
TX_totcol
;
/*
* This needs improvement.
*/
pDpa
->
stats
.
rx_dropped
=
0
;
/* no space in linux buffers */
pDpa
->
stats
.
tx_dropped
=
0
;
/* no space available in linux */
pDpa
->
stats
.
multicast
=
0
;
/* multicast packets received */
pDpa
->
stats
.
collisions
=
RCstats
.
TX_totcol
;
/* detailed rx_errors: */
pDpa
->
stats
.
rx_length_errors
=
0
;
pDpa
->
stats
.
rx_over_errors
=
RCstats
.
Rcv_orun
;
pDpa
->
stats
.
rx_crc_errors
=
RCstats
.
Rcv_CRCerr
;
pDpa
->
stats
.
rx_frame_errors
=
0
;
pDpa
->
stats
.
rx_fifo_errors
=
0
;
pDpa
->
stats
.
rx_missed_errors
=
0
;
/* detailed tx_errors */
pDpa
->
stats
.
tx_aborted_errors
=
0
;
pDpa
->
stats
.
tx_carrier_errors
=
0
;
pDpa
->
stats
.
tx_fifo_errors
=
0
;
pDpa
->
stats
.
tx_heartbeat_errors
=
0
;
pDpa
->
stats
.
tx_window_errors
=
0
;
return
((
struct
net_device_stats
*
)
&
(
pDpa
->
stats
));
}
return
0
;
}
static
int
RCioctl
(
struct
net_device
*
dev
,
struct
ifreq
*
rq
,
int
cmd
)
{
RCuser_struct
RCuser
;
PDPA
pDpa
=
dev
->
priv
;
if
(
!
capable
(
CAP_NET_ADMIN
))
return
-
EPERM
;
switch
(
cmd
)
{
case
RCU_PROTOCOL_REV
:
/*
* Assign user protocol revision, to tell user-level
* controller program whether or not it's in sync.
*/
rq
->
ifr_ifru
.
ifru_data
=
(
caddr_t
)
USER_PROTOCOL_REV
;
break
;
case
RCU_COMMAND
:
{
if
(
copy_from_user
(
&
RCuser
,
rq
->
ifr_data
,
sizeof
(
RCuser
)))
return
-
EFAULT
;
dprintk
(
"RCioctl: RCuser_cmd = 0x%x
\n
"
,
RCuser
.
cmd
);
switch
(
RCuser
.
cmd
)
{
case
RCUC_GETFWVER
:
RCUD_GETFWVER
=
&
RCuser
.
RCUS_GETFWVER
;
RCGetFirmwareVer
(
dev
,
(
PU8
)
&
RCUD_GETFWVER
->
FirmString
,
NULL
);
break
;
case
RCUC_GETINFO
:
RCUD_GETINFO
=
&
RCuser
.
RCUS_GETINFO
;
RCUD_GETINFO
->
mem_start
=
dev
->
base_addr
;
RCUD_GETINFO
->
mem_end
=
dev
->
base_addr
+
pDpa
->
pci_addr_len
;
RCUD_GETINFO
->
base_addr
=
pDpa
->
pci_addr
;
RCUD_GETINFO
->
irq
=
dev
->
irq
;
break
;
case
RCUC_GETIPANDMASK
:
RCUD_GETIPANDMASK
=
&
RCuser
.
RCUS_GETIPANDMASK
;
RCGetRavlinIPandMask
(
dev
,
(
PU32
)
&
RCUD_GETIPANDMASK
->
IpAddr
,
(
PU32
)
&
RCUD_GETIPANDMASK
->
NetMask
,
NULL
);
break
;
case
RCUC_GETLINKSTATISTICS
:
RCUD_GETLINKSTATISTICS
=
&
RCuser
.
RCUS_GETLINKSTATISTICS
;
RCGetLinkStatistics
(
dev
,
(
P_RCLINKSTATS
)
&
RCUD_GETLINKSTATISTICS
->
StatsReturn
,
NULL
);
break
;
case
RCUC_GETLINKSTATUS
:
RCUD_GETLINKSTATUS
=
&
RCuser
.
RCUS_GETLINKSTATUS
;
RCGetLinkStatus
(
dev
,
(
PU32
)
&
RCUD_GETLINKSTATUS
->
ReturnStatus
,
NULL
);
break
;
case
RCUC_GETMAC
:
RCUD_GETMAC
=
&
RCuser
.
RCUS_GETMAC
;
RCGetMAC
(
dev
,
NULL
);
memcpy
(
RCUD_GETMAC
,
dev
->
dev_addr
,
8
);
break
;
case
RCUC_GETPROM
:
RCUD_GETPROM
=
&
RCuser
.
RCUS_GETPROM
;
RCGetPromiscuousMode
(
dev
,
(
PU32
)
&
RCUD_GETPROM
->
PromMode
,
NULL
);
break
;
case
RCUC_GETBROADCAST
:
RCUD_GETBROADCAST
=
&
RCuser
.
RCUS_GETBROADCAST
;
RCGetBroadcastMode
(
dev
,
(
PU32
)
&
RCUD_GETBROADCAST
->
BroadcastMode
,
NULL
);
break
;
case
RCUC_GETSPEED
:
if
(
!
(
dev
->
flags
&
IFF_UP
))
{
return
-
ENODATA
;
}
RCUD_GETSPEED
=
&
RCuser
.
RCUS_GETSPEED
;
RCGetLinkSpeed
(
dev
,
(
PU32
)
&
RCUD_GETSPEED
->
LinkSpeedCode
,
NULL
);
break
;
case
RCUC_SETIPANDMASK
:
RCUD_SETIPANDMASK
=
&
RCuser
.
RCUS_SETIPANDMASK
;
RCSetRavlinIPandMask
(
dev
,
(
U32
)
RCUD_SETIPANDMASK
->
IpAddr
,
(
U32
)
RCUD_SETIPANDMASK
->
NetMask
);
break
;
case
RCUC_SETMAC
:
RCSetMAC
(
dev
,
(
PU8
)
&
RCUD_SETMAC
->
mac
);
break
;
case
RCUC_SETSPEED
:
RCUD_SETSPEED
=
&
RCuser
.
RCUS_SETSPEED
;
RCSetLinkSpeed
(
dev
,
(
U16
)
RCUD_SETSPEED
->
LinkSpeedCode
);
break
;
case
RCUC_SETPROM
:
RCUD_SETPROM
=
&
RCuser
.
RCUS_SETPROM
;
RCSetPromiscuousMode
(
dev
,
(
U16
)
RCUD_SETPROM
->
PromMode
);
break
;
case
RCUC_SETBROADCAST
:
RCUD_SETBROADCAST
=
&
RCuser
.
RCUS_SETBROADCAST
;
RCSetBroadcastMode
(
dev
,
(
U16
)
RCUD_SETBROADCAST
->
BroadcastMode
);
break
;
default:
RCUD_DEFAULT
=
&
RCuser
.
RCUS_DEFAULT
;
RCUD_DEFAULT
->
rc
=
0x11223344
;
break
;
}
if
(
copy_to_user
(
rq
->
ifr_data
,
&
RCuser
,
sizeof
(
RCuser
)))
return
-
EFAULT
;
break
;
}
/* RCU_COMMAND */
default:
rq
->
ifr_ifru
.
ifru_data
=
(
caddr_t
)
0x12345678
;
return
-
EINVAL
;
}
return
0
;
}
static
int
RCconfig
(
struct
net_device
*
dev
,
struct
ifmap
*
map
)
{
/*
* To be completed ...
*/
return
0
;
if
(
dev
->
flags
&
IFF_UP
)
/* can't act on a running interface */
return
-
EBUSY
;
/* Don't allow changing the I/O address */
if
(
map
->
base_addr
!=
dev
->
base_addr
)
{
printk
(
KERN_WARNING
"%s Change I/O address not implemented
\n
"
,
dev
->
name
);
return
-
EOPNOTSUPP
;
}
return
0
;
}
static
void
__exit
rcpci_cleanup_module
(
void
)
{
pci_unregister_driver
(
&
rcpci45_driver
);
}
module_init
(
rcpci_init_module
);
module_exit
(
rcpci_cleanup_module
);
static
int
RC_allocate_and_post_buffers
(
struct
net_device
*
dev
,
int
numBuffers
)
{
int
i
;
PU32
p
;
psingleB
pB
;
struct
sk_buff
*
skb
;
PDPA
pDpa
=
dev
->
priv
;
RC_RETURN
status
;
U32
res
=
0
;
if
(
!
numBuffers
)
return
0
;
else
if
(
numBuffers
>
MAX_NMBR_POST_BUFFERS_PER_MSG
)
{
printk
(
KERN_ERR
"%s: Too many buffers requested!
\n
"
,
dev
->
name
);
numBuffers
=
32
;
}
p
=
(
PU32
)
kmalloc
(
sizeof
(
U32
)
+
numBuffers
*
sizeof
(
singleB
),
GFP_DMA
|
GFP_ATOMIC
);
if
(
!
p
)
{
printk
(
KERN_WARNING
"%s unable to allocate TCB
\n
"
,
dev
->
name
);
goto
out
;
}
p
[
0
]
=
0
;
/* Buffer Count */
pB
=
(
psingleB
)
((
U32
)
p
+
sizeof
(
U32
));
/* point to the first buffer */
for
(
i
=
0
;
i
<
numBuffers
;
i
++
)
{
skb
=
dev_alloc_skb
(
MAX_ETHER_SIZE
+
2
);
if
(
!
skb
)
{
printk
(
KERN_WARNING
"%s: unable to allocate enough skbs!
\n
"
,
dev
->
name
);
goto
err_out_unmap
;
}
skb_reserve
(
skb
,
2
);
/* Align IP on 16 byte boundaries */
pB
->
context
=
(
U32
)
skb
;
pB
->
scount
=
1
;
/* segment count */
pB
->
size
=
MAX_ETHER_SIZE
;
pB
->
addr
=
pci_map_single
(
pDpa
->
pci_dev
,
skb
->
data
,
MAX_ETHER_SIZE
,
PCI_DMA_FROMDEVICE
);
p
[
0
]
++
;
pB
++
;
}
if
((
status
=
RCPostRecvBuffers
(
dev
,
(
PRCTCB
)
p
))
!=
RC_RTN_NO_ERROR
)
{
printk
(
KERN_WARNING
"%s: Post buffer failed, error 0x%x
\n
"
,
dev
->
name
,
status
);
goto
err_out_unmap
;
}
out_free:
res
=
p
[
0
];
kfree
(
p
);
out:
return
(
res
);
/* return the number of posted buffers */
err_out_unmap:
for
(;
p
[
0
]
>
0
;
p
[
0
]
--
)
{
--
pB
;
skb
=
(
struct
sk_buff
*
)
pB
->
context
;
pci_unmap_single
(
pDpa
->
pci_dev
,
pB
->
addr
,
MAX_ETHER_SIZE
,
PCI_DMA_FROMDEVICE
);
dev_kfree_skb
(
skb
);
}
goto
out_free
;
}
drivers/scsi/libata-core.c
View file @
bb8abfed
...
...
@@ -818,7 +818,7 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device)
* @dev: Device whose IDENTIFY DEVICE results we will examine
* @s: string into which data is output
* @ofs: offset into identify device page
* @len: length of string to return
* @len: length of string to return
. must be an even number.
*
* The strings in the IDENTIFY DEVICE page are broken up into
* 16-bit chunks. Run through the string, and output each
...
...
@@ -847,29 +847,6 @@ void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
}
}
/**
* ata_dev_parse_strings - Store useful IDENTIFY DEVICE page strings
* @dev: Device whose IDENTIFY DEVICE page info we use
*
* We store 'vendor' and 'product' strings read from the device,
* for later use in the SCSI simulator's INQUIRY data.
*
* Set these strings here, in the case of 'product', using
* data read from the ATA IDENTIFY DEVICE page.
*
* LOCKING:
* caller.
*/
static
void
ata_dev_parse_strings
(
struct
ata_device
*
dev
)
{
assert
(
dev
->
class
==
ATA_DEV_ATA
);
memcpy
(
dev
->
vendor
,
"ATA "
,
8
);
ata_dev_id_string
(
dev
,
dev
->
product
,
ATA_ID_PROD_OFS
,
sizeof
(
dev
->
product
));
}
/**
* __ata_dev_select - Select device 0/1 on ATA bus
* @ap: ATA channel to manipulate
...
...
@@ -1127,8 +1104,6 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
ata_dump_id
(
dev
);
ata_dev_parse_strings
(
dev
);
/* ATA-specific feature tests */
if
(
dev
->
class
==
ATA_DEV_ATA
)
{
if
(
!
ata_id_is_ata
(
dev
))
/* sanity check */
...
...
@@ -2346,7 +2321,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
if
(
cmd
)
{
if
(
unlikely
(
drv_stat
&
(
ATA_ERR
|
ATA_BUSY
|
ATA_DRQ
)))
{
if
(
qc
->
flags
&
ATA_QCFLAG_ATAPI
)
if
(
is_atapi_taskfile
(
&
qc
->
tf
)
)
cmd
->
result
=
SAM_STAT_CHECK_CONDITION
;
else
ata_to_sense_error
(
qc
);
...
...
@@ -2659,6 +2634,8 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
unsigned
int
handled
=
0
;
switch
(
qc
->
tf
.
protocol
)
{
/* BMDMA completion */
case
ATA_PROT_DMA
:
case
ATA_PROT_ATAPI_DMA
:
if
(
ap
->
flags
&
ATA_FLAG_MMIO
)
{
...
...
@@ -2677,8 +2654,16 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
handled
=
1
;
break
;
/* command completion, but no data xfer */
/* FIXME: a shared interrupt _will_ cause a non-data command
* to be completed prematurely, with an error.
*
* This doesn't matter right now, since we aren't sending
* non-data commands down this pipe except in development
* situations.
*/
case
ATA_PROT_ATAPI
:
case
ATA_PROT_NODATA
:
/* command completion, but no data xfer */
case
ATA_PROT_NODATA
:
status
=
ata_busy_wait
(
ap
,
ATA_BUSY
|
ATA_DRQ
,
1000
);
DPRINTK
(
"BUS_NODATA (drv_stat 0x%X)
\n
"
,
status
);
ata_qc_complete
(
qc
,
status
);
...
...
@@ -3525,3 +3510,4 @@ EXPORT_SYMBOL_GPL(ata_scsi_error);
EXPORT_SYMBOL_GPL
(
ata_scsi_slave_config
);
EXPORT_SYMBOL_GPL
(
ata_scsi_release
);
EXPORT_SYMBOL_GPL
(
ata_host_intr
);
EXPORT_SYMBOL_GPL
(
ata_dev_id_string
);
drivers/scsi/libata-scsi.c
View file @
bb8abfed
...
...
@@ -498,7 +498,9 @@ void ata_scsi_rbuf_fill(struct ata_scsi_args *args,
unsigned
int
ata_scsiop_inq_std
(
struct
ata_scsi_args
*
args
,
u8
*
rbuf
,
unsigned
int
buflen
)
{
const
u8
hdr
[]
=
{
struct
ata_device
*
dev
=
args
->
dev
;
u8
hdr
[]
=
{
TYPE_DISK
,
0
,
0x5
,
/* claim SPC-3 version compatibility */
...
...
@@ -506,14 +508,20 @@ unsigned int ata_scsiop_inq_std(struct ata_scsi_args *args, u8 *rbuf,
96
-
4
};
/* set scsi removeable (RMB) bit per ata bit */
if
(
ata_id_removeable
(
dev
))
hdr
[
1
]
|=
(
1
<<
7
);
VPRINTK
(
"ENTER
\n
"
);
memcpy
(
rbuf
,
hdr
,
sizeof
(
hdr
));
if
(
buflen
>
36
)
{
memcpy
(
&
rbuf
[
8
],
args
->
dev
->
vendor
,
8
);
memcpy
(
&
rbuf
[
16
],
args
->
dev
->
product
,
16
);
memcpy
(
&
rbuf
[
32
],
DRV_VERSION
,
4
);
memcpy
(
&
rbuf
[
8
],
"ATA "
,
8
);
ata_dev_id_string
(
dev
,
&
rbuf
[
16
],
ATA_ID_PROD_OFS
,
16
);
ata_dev_id_string
(
dev
,
&
rbuf
[
32
],
ATA_ID_FW_REV_OFS
,
4
);
if
(
rbuf
[
32
]
==
0
||
rbuf
[
32
]
==
' '
)
memcpy
(
&
rbuf
[
32
],
"n/a "
,
4
);
}
if
(
buflen
>
63
)
{
...
...
@@ -687,9 +695,17 @@ static void ata_msense_push(u8 **ptr_io, const u8 *last,
static
unsigned
int
ata_msense_caching
(
struct
ata_device
*
dev
,
u8
**
ptr_io
,
const
u8
*
last
)
{
u8
page
[
7
]
=
{
0xf
,
0
,
0x10
,
0
,
0x8
,
0xa
,
0
};
if
(
dev
->
flags
&
ATA_DFLAG_WCACHE
)
page
[
6
]
=
0x4
;
u8
page
[]
=
{
0x8
,
/* page code */
0x12
,
/* page length */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
/* 10 zeroes */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
/* 8 zeroes */
};
if
(
ata_id_wcache_enabled
(
dev
))
page
[
2
]
|=
(
1
<<
2
);
/* write cache enable */
if
(
!
ata_id_rahead_enabled
(
dev
))
page
[
12
]
|=
(
1
<<
5
);
/* disable read ahead */
ata_msense_push
(
ptr_io
,
last
,
page
,
sizeof
(
page
));
return
sizeof
(
page
);
...
...
@@ -715,6 +731,31 @@ static unsigned int ata_msense_ctl_mode(u8 **ptr_io, const u8 *last)
return
sizeof
(
page
);
}
/**
* ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
* @dev: Device associated with this MODE SENSE command
* @ptr_io: (input/output) Location to store more output data
* @last: End of output data buffer
*
* Generate a generic MODE SENSE r/w error recovery page.
*
* LOCKING:
* None.
*/
static
unsigned
int
ata_msense_rw_recovery
(
u8
**
ptr_io
,
const
u8
*
last
)
{
const
u8
page
[]
=
{
0x1
,
/* page code */
0xa
,
/* page length */
(
1
<<
7
)
|
(
1
<<
6
),
/* note auto r/w reallocation */
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
/* 9 zeroes */
};
ata_msense_push
(
ptr_io
,
last
,
page
,
sizeof
(
page
));
return
sizeof
(
page
);
}
/**
* ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands
* @args: Port / device / SCSI command of interest.
...
...
@@ -754,6 +795,10 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
last
=
rbuf
+
buflen
-
1
;
switch
(
scsicmd
[
2
]
&
0x3f
)
{
case
0x01
:
/* r/w error recovery */
output_len
+=
ata_msense_rw_recovery
(
&
p
,
last
);
break
;
case
0x08
:
/* caching */
output_len
+=
ata_msense_caching
(
dev
,
&
p
,
last
);
break
;
...
...
@@ -764,6 +809,7 @@ unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf,
}
case
0x3f
:
/* all pages */
output_len
+=
ata_msense_rw_recovery
(
&
p
,
last
);
output_len
+=
ata_msense_caching
(
dev
,
&
p
,
last
);
output_len
+=
ata_msense_ctl_mode
(
&
p
,
last
);
break
;
...
...
@@ -804,20 +850,23 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
VPRINTK
(
"ENTER
\n
"
);
n_sectors
--
;
/*
one off
*/
n_sectors
--
;
/*
ATA TotalUserSectors - 1
*/
tmp
=
n_sectors
;
/* note: truncates, if lba48 */
if
(
args
->
cmd
->
cmnd
[
0
]
==
READ_CAPACITY
)
{
/* sector count, 32-bit */
rbuf
[
0
]
=
tmp
>>
(
8
*
3
);
rbuf
[
1
]
=
tmp
>>
(
8
*
2
);
rbuf
[
2
]
=
tmp
>>
(
8
*
1
);
rbuf
[
3
]
=
tmp
;
/* sector size */
tmp
=
ATA_SECT_SIZE
;
rbuf
[
6
]
=
tmp
>>
8
;
rbuf
[
7
]
=
tmp
;
}
else
{
/* sector count, 64-bit */
rbuf
[
2
]
=
n_sectors
>>
(
8
*
7
);
rbuf
[
3
]
=
n_sectors
>>
(
8
*
6
);
rbuf
[
4
]
=
n_sectors
>>
(
8
*
5
);
...
...
@@ -827,6 +876,7 @@ unsigned int ata_scsiop_read_cap(struct ata_scsi_args *args, u8 *rbuf,
rbuf
[
8
]
=
tmp
>>
(
8
*
1
);
rbuf
[
9
]
=
tmp
;
/* sector size */
tmp
=
ATA_SECT_SIZE
;
rbuf
[
12
]
=
tmp
>>
8
;
rbuf
[
13
]
=
tmp
;
...
...
@@ -901,8 +951,6 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc, u8 *scsicmd)
{
struct
scsi_cmnd
*
cmd
=
qc
->
scsicmd
;
qc
->
flags
|=
ATA_QCFLAG_ATAPI
;
qc
->
tf
.
flags
|=
ATA_TFLAG_ISADDR
|
ATA_TFLAG_DEVICE
;
if
(
cmd
->
sc_data_direction
==
SCSI_DATA_WRITE
)
{
qc
->
tf
.
flags
|=
ATA_TFLAG_WRITE
;
...
...
@@ -1106,7 +1154,11 @@ static void ata_scsi_simulate(struct ata_port *ap, struct ata_device *dev,
args
.
done
=
done
;
switch
(
scsicmd
[
0
])
{
case
TEST_UNIT_READY
:
/* FIXME: correct? */
/* no-op's, complete with success */
case
REZERO_UNIT
:
case
SEEK_6
:
case
SEEK_10
:
case
TEST_UNIT_READY
:
case
FORMAT_UNIT
:
/* FIXME: correct? */
case
SEND_DIAGNOSTIC
:
/* FIXME: correct? */
ata_scsi_rbuf_fill
(
&
args
,
ata_scsiop_noop
);
...
...
drivers/scsi/libata.h
View file @
bb8abfed
...
...
@@ -36,8 +36,6 @@ struct ata_scsi_args {
};
/* libata-core.c */
extern
void
ata_dev_id_string
(
struct
ata_device
*
dev
,
unsigned
char
*
s
,
unsigned
int
ofs
,
unsigned
int
len
);
extern
struct
ata_queued_cmd
*
ata_qc_new_init
(
struct
ata_port
*
ap
,
struct
ata_device
*
dev
);
extern
int
ata_qc_issue
(
struct
ata_queued_cmd
*
qc
);
...
...
drivers/scsi/sata_sil.c
View file @
bb8abfed
...
...
@@ -276,8 +276,14 @@ static void sil_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
static
void
sil_dev_config
(
struct
ata_port
*
ap
,
struct
ata_device
*
dev
)
{
unsigned
int
n
,
quirks
=
0
;
const
char
*
s
=
&
dev
->
product
[
0
];
unsigned
int
len
=
strnlen
(
s
,
sizeof
(
dev
->
product
));
unsigned
char
model_num
[
40
];
const
char
*
s
;
unsigned
int
len
;
ata_dev_id_string
(
dev
,
model_num
,
ATA_ID_PROD_OFS
,
sizeof
(
model_num
));
s
=
&
model_num
[
0
];
len
=
strnlen
(
s
,
sizeof
(
model_num
));
/* ATAPI specifies that empty space is blank-filled; remove blanks */
while
((
len
>
0
)
&&
(
s
[
len
-
1
]
==
' '
))
...
...
include/linux/ata.h
View file @
bb8abfed
...
...
@@ -38,6 +38,7 @@ enum {
ATA_ID_WORDS
=
256
,
ATA_ID_PROD_OFS
=
27
,
ATA_ID_FW_REV_OFS
=
23
,
ATA_ID_SERNO_OFS
=
10
,
ATA_ID_MAJOR_VER
=
80
,
ATA_ID_PIO_MODES
=
64
,
...
...
@@ -103,6 +104,7 @@ enum {
ATA_REG_IRQ
=
ATA_REG_NSECT
,
/* ATA device commands */
ATA_CMD_CHK_POWER
=
0xE5
,
/* check power mode */
ATA_CMD_EDD
=
0x90
,
/* execute device diagnostic */
ATA_CMD_FLUSH
=
0xE7
,
ATA_CMD_FLUSH_EXT
=
0xEA
,
...
...
@@ -200,11 +202,14 @@ struct ata_taskfile {
};
#define ata_id_is_ata(dev) (((dev)->id[0] & (1 << 15)) == 0)
#define ata_id_rahead_enabled(dev) ((dev)->id[85] & (1 << 6))
#define ata_id_wcache_enabled(dev) ((dev)->id[85] & (1 << 5))
#define ata_id_has_lba48(dev) ((dev)->id[83] & (1 << 10))
#define ata_id_has_wcache(dev) ((dev)->id[82] & (1 << 5))
#define ata_id_has_pm(dev) ((dev)->id[82] & (1 << 3))
#define ata_id_has_lba(dev) ((dev)->id[49] & (1 << 8))
#define ata_id_has_dma(dev) ((dev)->id[49] & (1 << 9))
#define ata_id_removeable(dev) ((dev)->id[0] & (1 << 7))
#define ata_id_u32(dev,n) \
(((u32) (dev)->id[(n) + 1] << 16) | ((u32) (dev)->id[(n)]))
#define ata_id_u64(dev,n) \
...
...
@@ -213,4 +218,10 @@ struct ata_taskfile {
((u64) dev->id[(n) + 1] << 16) | \
((u64) dev->id[(n) + 0]) )
static
inline
int
is_atapi_taskfile
(
struct
ata_taskfile
*
tf
)
{
return
(
tf
->
protocol
==
ATA_PROT_ATAPI
)
||
(
tf
->
protocol
==
ATA_PROT_ATAPI_DMA
);
}
#endif
/* __LINUX_ATA_H__ */
include/linux/libata.h
View file @
bb8abfed
...
...
@@ -111,7 +111,6 @@ enum {
ATA_QCFLAG_ACTIVE
=
(
1
<<
1
),
/* cmd not yet ack'd to scsi lyer */
ATA_QCFLAG_DMA
=
(
1
<<
2
),
/* data delivered via DMA */
ATA_QCFLAG_ATAPI
=
(
1
<<
3
),
/* is ATAPI packet command? */
ATA_QCFLAG_SG
=
(
1
<<
4
),
/* have s/g table? */
/* various lengths of time */
...
...
@@ -260,12 +259,6 @@ struct ata_device {
unsigned
int
pio_mode
;
unsigned
int
udma_mode
;
unsigned
char
vendor
[
8
];
/* space-padded, not ASCIIZ */
unsigned
char
product
[
32
];
/* WARNING: shorter than
* ATAPI7 spec size, 40 ASCII
* characters
*/
/* cache info about current transfer mode */
u8
xfer_protocol
;
/* taskfile xfer protocol */
u8
read_cmd
;
/* opcode to use on read */
...
...
@@ -398,6 +391,8 @@ extern int ata_port_start (struct ata_port *ap);
extern
void
ata_port_stop
(
struct
ata_port
*
ap
);
extern
irqreturn_t
ata_interrupt
(
int
irq
,
void
*
dev_instance
,
struct
pt_regs
*
regs
);
extern
void
ata_fill_sg
(
struct
ata_queued_cmd
*
qc
);
extern
void
ata_dev_id_string
(
struct
ata_device
*
dev
,
unsigned
char
*
s
,
unsigned
int
ofs
,
unsigned
int
len
);
extern
void
ata_bmdma_setup_mmio
(
struct
ata_queued_cmd
*
qc
);
extern
void
ata_bmdma_start_mmio
(
struct
ata_queued_cmd
*
qc
);
extern
void
ata_bmdma_setup_pio
(
struct
ata_queued_cmd
*
qc
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment