Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
X
xv6-public
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
问题
0
问题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
银宸时代
OS Lab Group
奖励实验
xv6-public
提交
dfa9c79c
提交
dfa9c79c
12月 17, 2011
创建
作者:
Silas Boyd-Wickizer
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
First complete pass at e1000.
All our machines, however, have e1000e cards.
上级
7ab0d619
显示空白字符变更
内嵌
并排
正在显示
6 个修改的文件
包含
267 行增加
和
9 行删除
+267
-9
Makefile
Makefile
+4
-1
e1000.c
e1000.c
+197
-7
kernel.h
kernel.h
+10
-0
net.c
net.c
+47
-0
pci.c
pci.c
+2
-1
trap.c
trap.c
+7
-0
没有找到文件。
Makefile
浏览文件 @
dfa9c79c
...
...
@@ -45,6 +45,7 @@ OBJS = \
main.o
\
memide.o
\
mp.o
\
net.o
\
ns.o
\
pci.o
\
picirq.o
\
...
...
@@ -142,7 +143,9 @@ $(O)/mscan.kern: $(O)/kernel
##
## qemu
##
QEMUOPTS
=
-smp
$(QEMUSMP)
-m
512
-serial
mon:stdio
-nographic
QEMUOPTS
=
-smp
$(QEMUSMP)
-m
512
-serial
mon:stdio
-nographic
\
-net
user
-net
nic,model
=
e1000
\
-net
dump,file
=
qemu.pcap
qemu
:
$(O)/kernel
$(QEMU)
$(QEMUOPTS)
-kernel
$(O)
/kernel
...
...
e1000.c
浏览文件 @
dfa9c79c
...
...
@@ -4,22 +4,36 @@
#include "pci.h"
#include "e1000reg.h"
#define TX_RING_SIZE 64
#define RX_RING_SIZE 64
int
e1000irq
;
static
struct
{
u32
membase
;
u32
iobase
;
u16
pcidevid
;
u32
txclean
;
u32
txinuse
;
u32
rxclean
;
u32
rxuse
;
struct
wiseman_txdesc
txd
[
TX_RING_SIZE
]
__attribute__
((
aligned
(
16
)));
struct
wiseman_rxdesc
rxd
[
RX_RING_SIZE
]
__attribute__
((
aligned
(
16
)));
}
e1000
;
static
u32
e
1000_io_rea
d
(
u32
reg
)
static
inline
u32
e
r
d
(
u32
reg
)
{
paddr
pa
=
e1000
.
membase
+
reg
;
volatile
u32
*
ptr
=
p2v
(
pa
);
return
*
ptr
;
}
static
void
e
1000_io_write
(
u32
reg
,
u32
val
)
static
inline
void
e
wr
(
u32
reg
,
u32
val
)
{
paddr
pa
=
e1000
.
membase
+
reg
;
volatile
u32
*
ptr
=
p2v
(
pa
);
...
...
@@ -33,9 +47,9 @@ eeprom_eerd_read(u16 off)
int
x
;
// [E1000 5.3.1] Software EEPROM access
e
1000_io_write
(
WMREG_EERD
,
(
off
<<
EERD_ADDR_SHIFT
)
|
EERD_START
);
for
(
x
=
0
;
x
<
100
;
x
++
)
{
reg
=
e
1000_io_rea
d
(
WMREG_EERD
);
e
wr
(
WMREG_EERD
,
(
off
<<
EERD_ADDR_SHIFT
)
|
EERD_START
);
for
(
x
=
0
;
x
<
5
;
x
++
)
{
reg
=
e
r
d
(
WMREG_EERD
);
if
(
reg
&
EERD_DONE
)
return
(
reg
&
EERD_DATA_MASK
)
>>
EERD_DATA_SHIFT
;
microdelay
(
50000
);
...
...
@@ -58,6 +72,176 @@ eeprom_read(u16 *buf, int off, int count)
}
int
e1000tx
(
void
*
buf
,
u32
len
)
{
struct
wiseman_txdesc
*
desc
;
u32
tail
;
// WMREG_TDT should only equal WMREG_TDH when we have
// nothing to transmit. Therefore, we can accomodate
// TX_RING_SIZE-1 buffers.
if
(
e1000
.
txinuse
==
TX_RING_SIZE
-
1
)
{
cprintf
(
"TX ring overflow
\n
"
);
return
-
1
;
}
tail
=
erd
(
WMREG_TDT
);
desc
=
&
e1000
.
txd
[
tail
];
if
(
!
(
desc
->
wtx_fields
.
wtxu_status
&
WTX_ST_DD
))
panic
(
"oops"
);
desc
->
wtx_addr
=
v2p
(
buf
);
desc
->
wtx_cmdlen
=
len
|
WTX_CMD_RS
|
WTX_CMD_EOP
|
WTX_CMD_IFCS
;
memset
(
&
desc
->
wtx_fields
,
0
,
sizeof
(
&
desc
->
wtx_fields
));
ewr
(
WMREG_TDT
,
(
tail
+
1
)
%
TX_RING_SIZE
);
e1000
.
txinuse
++
;
return
0
;
}
static
void
cleantx
(
void
)
{
struct
wiseman_txdesc
*
desc
;
void
*
va
;
while
(
e1000
.
txinuse
)
{
desc
=
&
e1000
.
txd
[
e1000
.
txclean
];
if
(
!
(
desc
->
wtx_fields
.
wtxu_status
&
WTX_ST_DD
))
break
;
va
=
p2v
(
desc
->
wtx_addr
);
netfree
(
va
);
desc
->
wtx_fields
.
wtxu_status
=
0
;
e1000
.
txclean
=
(
e1000
.
txclean
+
1
)
%
TX_RING_SIZE
;
desc
=
&
e1000
.
txd
[
e1000
.
txclean
];
e1000
.
txinuse
--
;
}
}
static
void
allocrx
(
void
)
{
struct
wiseman_rxdesc
*
desc
;
void
*
buf
;
u32
i
;
i
=
erd
(
WMREG_RDT
);
desc
=
&
e1000
.
rxd
[
i
];
if
(
desc
->
wrx_status
&
WRX_ST_DD
)
panic
(
"allocrx"
);
buf
=
netalloc
();
if
(
buf
==
NULL
)
panic
(
"Oops"
);
desc
->
wrx_addr
=
v2p
(
buf
);
ewr
(
WMREG_RDT
,
(
i
+
1
)
%
RX_RING_SIZE
);
}
static
void
cleanrx
(
void
)
{
struct
wiseman_rxdesc
*
desc
;
void
*
va
;
u16
len
;
u32
i
;
i
=
e1000
.
rxclean
;
desc
=
&
e1000
.
rxd
[
i
];
while
(
desc
->
wrx_status
&
WRX_ST_DD
)
{
va
=
p2v
(
desc
->
wrx_addr
);
len
=
desc
->
wrx_len
;
desc
->
wrx_status
=
0
;
allocrx
();
netrx
(
va
,
len
);
i
=
(
i
+
1
)
%
RX_RING_SIZE
;
desc
=
&
e1000
.
rxd
[
i
];
}
e1000
.
rxclean
=
i
;
}
void
e1000intr
(
void
)
{
u32
icr
=
erd
(
WMREG_ICR
);
while
(
icr
&
(
ICR_TXDW
|
ICR_RXO
|
ICR_RXT0
))
{
if
(
icr
&
ICR_TXDW
)
cleantx
();
if
(
icr
&
ICR_RXT0
)
cleanrx
();
if
(
icr
&
ICR_RXO
)
panic
(
"ICR_RXO"
);
icr
=
erd
(
WMREG_ICR
);
}
}
static
void
e1000reset
(
void
)
{
u32
ctrl
;
paddr
tpa
;
paddr
rpa
;
ctrl
=
erd
(
WMREG_CTRL
);
// [E1000 13.4.1] Assert PHY_RESET then delay as much as 10 msecs
// before clearing PHY_RESET.
ewr
(
WMREG_CTRL
,
ctrl
|
CTRL_PHY_RESET
);
microdelay
(
10000
);
ewr
(
WMREG_CTRL
,
ctrl
);
// [E1000 13.4.1] Delay 1 usec after reset
ewr
(
WMREG_CTRL
,
ctrl
|
CTRL_RST
);
microdelay
(
1
);
// [E1000 13.4.41] Transmit Interrupt Delay Value of 1 usec.
// A value of 0 is not allowed. Enabled on a per-TX decriptor basis.
ewr
(
WMREG_TIDV
,
1
);
// [E1000 13.4.44] Delay TX interrupts a max of 1 usec.
ewr
(
WMREG_TADV
,
1
);
for
(
int
i
=
0
;
i
<
TX_RING_SIZE
;
i
++
)
e1000
.
txd
[
i
].
wtx_fields
.
wtxu_status
=
WTX_ST_DD
;
// [E1000 14.5] Transmit Initialization
tpa
=
v2p
(
e1000
.
txd
);
ewr
(
WMREG_TDBAH
,
tpa
>>
32
);
ewr
(
WMREG_TDBAL
,
tpa
&
0xffffffff
);
ewr
(
WMREG_TDLEN
,
sizeof
(
e1000
.
txd
));
ewr
(
WMREG_TDH
,
0
);
ewr
(
WMREG_TDT
,
0
);
ewr
(
WMREG_TCTL
,
TCTL_EN
|
TCTL_PSP
|
TCTL_CT
(
0x10
)
|
TCTL_COLD
(
0x40
));
ewr
(
WMREG_TIPG
,
TIPG_IPGT
(
10
)
|
TIPG_IPGR1
(
8
)
|
TIPG_IPGR2
(
6
));
for
(
int
i
=
0
;
i
<
RX_RING_SIZE
>>
1
;
i
++
)
{
void
*
buf
=
netalloc
();
e1000
.
rxd
[
i
].
wrx_addr
=
v2p
(
buf
);
}
rpa
=
v2p
(
e1000
.
rxd
);
ewr
(
WMREG_RDBAH
,
rpa
>>
32
);
ewr
(
WMREG_RDBAL
,
rpa
&
0xffffffff
);
ewr
(
WMREG_RDLEN
,
sizeof
(
e1000
.
rxd
));
ewr
(
WMREG_RDH
,
0
);
ewr
(
WMREG_RDT
,
RX_RING_SIZE
>>
1
);
ewr
(
WMREG_RDTR
,
0
);
ewr
(
WMREG_RADV
,
0
);
ewr
(
WMREG_RCTL
,
RCTL_EN
|
RCTL_RDMTS_1_2
|
RCTL_DPF
|
RCTL_BAM
|
RCTL_2k
);
ewr
(
WMREG_RDT
,
RX_RING_SIZE
-
1
);
// [E1000 13.4.20]
ewr
(
WMREG_IMC
,
~
0
);
ewr
(
WMREG_IMS
,
ICR_TXDW
|
ICR_RXO
|
ICR_RXT0
);
}
//#define E1000_WRITE_FLUSH() erd(WMREG_STATUS)
int
e1000attach
(
struct
pci_func
*
pcif
)
{
int
r
;
...
...
@@ -67,6 +251,12 @@ e1000attach(struct pci_func *pcif)
e1000
.
membase
=
pcif
->
reg_base
[
0
];
e1000
.
iobase
=
pcif
->
reg_base
[
2
];
e1000
.
pcidevid
=
pcif
->
dev_id
;
e1000irq
=
pcif
->
irq_line
;
picenable
(
e1000irq
);
ioapicenable
(
e1000irq
,
0
);
e1000reset
();
// Get the MAC address
u16
myaddr
[
3
];
...
...
kernel.h
浏览文件 @
dfa9c79c
...
...
@@ -65,6 +65,11 @@ void panic(const char*) __attribute__((noreturn));
void
snprintf
(
char
*
buf
,
u32
n
,
char
*
fmt
,
...);
void
consoleintr
(
int
(
*
)(
void
));
// e1000.c
extern
int
e1000irq
;
void
e1000intr
(
void
);
int
e1000tx
(
void
*
buf
,
u32
len
);
// exec.c
int
exec
(
char
*
,
char
**
);
...
...
@@ -139,6 +144,11 @@ void lapicpc(char mask);
extern
int
ncpu
;
int
mpbcpu
(
void
);
// net.c
void
netfree
(
void
*
va
);
void
*
netalloc
(
void
);
void
netrx
(
void
*
va
,
u16
len
);
// ns.c
enum
{
nskey_int
=
1
,
...
...
net.c
0 → 100644
浏览文件 @
dfa9c79c
#include "types.h"
#include "kernel.h"
static
u8
ping_packet
[]
=
{
0x52
,
0x55
,
0x0a
,
0x00
,
0x02
,
0x02
,
0x52
,
0x54
,
0x00
,
0x12
,
0x34
,
0x56
,
0x08
,
0x00
,
0x45
,
0x00
,
0x00
,
0x54
,
0x00
,
0x00
,
0x40
,
0x00
,
0x40
,
0x01
,
0x22
,
0x99
,
0x0a
,
0x00
,
0x02
,
0x0f
,
0x0a
,
0x00
,
0x02
,
0x02
,
0x08
,
0x00
,
0x94
,
0xa0
,
0x03
,
0x07
,
0x00
,
0x01
,
0x71
,
0xfc
,
0xec
,
0x4e
,
0x00
,
0x00
,
0x00
,
0x00
,
0x3b
,
0x39
,
0x08
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x10
,
0x11
,
0x12
,
0x13
,
0x14
,
0x15
,
0x16
,
0x17
,
0x18
,
0x19
,
0x1a
,
0x1b
,
0x1c
,
0x1d
,
0x1e
,
0x1f
,
0x20
,
0x21
,
0x22
,
0x23
,
0x24
,
0x25
,
0x26
,
0x27
,
0x28
,
0x29
,
0x2a
,
0x2b
,
0x2c
,
0x2d
,
0x2e
,
0x2f
,
0x30
,
0x31
,
0x32
,
0x33
,
0x34
,
0x35
,
0x36
,
0x37
};
void
netfree
(
void
*
va
)
{
kfree
(
va
);
}
void
*
netalloc
(
void
)
{
return
kalloc
();
}
void
netrx
(
void
*
va
,
u16
len
)
{
cprintf
(
"netrx %lx len %x
\n
"
,
va
,
len
);
}
void
nettest
(
void
)
{
void
*
ping
;
u32
len
;
ping
=
netalloc
();
len
=
sizeof
(
ping_packet
);
memmove
(
ping
,
ping_packet
,
len
);
e1000tx
(
ping
,
len
);
//e1000tx(ping_packet, sizeof(ping_packet));
}
pci.c
浏览文件 @
dfa9c79c
...
...
@@ -30,11 +30,12 @@ struct pci_driver pci_attach_class[] = {
};
// pci_attach_vendor matches the vendor ID and device ID of a PCI device
// http://www.intel.com/products/ethernet/resource.htm?wapkw=software%20manual%20pcie#s1=Gigabit%20Ethernet&s2=all&s3=Manual
struct
pci_driver
pci_attach_vendor
[]
=
{
// [E1000 5.2]
// QEMU emulates an 82540EM, specifically.
{
0x8086
,
0x100e
,
&
e1000attach
},
// Both of ud0's e1000e
// Both of ud0's e1000e
(82573E, 82573L)
{
0x8086
,
0x108c
,
&
e1000attach
},
{
0x8086
,
0x109A
,
&
e1000attach
},
{
0
,
0
,
0
},
...
...
trap.c
浏览文件 @
dfa9c79c
...
...
@@ -117,6 +117,13 @@ trap(struct trapframe *tf)
sampconf
();
break
;
default:
if
(
tf
->
trapno
==
T_IRQ0
+
e1000irq
)
{
e1000intr
();
lapiceoi
();
piceoi
();
break
;
}
if
(
myproc
()
==
0
||
(
tf
->
cs
&
3
)
==
0
){
// In kernel, it must be our mistake.
cprintf
(
"unexpected trap %d from cpu %d rip %lx (cr2=0x%lx)
\n
"
,
...
...
编写
预览
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论