您的位置:首页 > 理论基础 > 计算机网络

linux0.99网络模块-网络设备初始化

2015-10-15 16:05 281 查看
在《llinux0.99网络模块-网络模块初始化》中我们分析了网络模块的初始化过程,其中关于设备初始化我们单独拿到这里来分析。

对于linux0.99内核来说,它初始化了两个设备-loopback和wd8003.

1.数据结构



net/tcp/dev.h

47 #define DEV_NUMBUFFS 3

48 #define MAX_ADDR_LEN 6

49 #define MAX_HEADER 14

50 #define MAX_ROUTE 16

52 struct device

53 {

54 char *name; //设备名

55 unsigned long rmem_end; //接收内存结束地址

56 unsigned long rmem_start; //接收内存起始地址

57 unsigned long mem_end; //设备发送内存结束地址

58 unsigned long mem_start; //设备发送内存起始地址

59 unsigned short base_addr; //寄存器基地址(见tcp/wereg.h:128)

60 unsigned char irq; //中断

61 unsigned char start:1, //启动标志

62 tbusy:1, //设备忙

63 loopback:1, //回环设备标志

64 interrupt:1, //是否有中断

65 up:1; //发送标志

66 struct device *next; //连接下一个设备

67 int (*init)(struct device *dev); //初始化函数指针

68 unsigned long trans_start; //传输开始

69 struct sk_buff *buffs[DEV_NUMBUFFS]; //缓冲区

70 struct sk_buff *backlog; /* no longer used. */ //积压队列

71 int (*open)(struct device *dev); //打开设备函数指针

72 int (*stop)(struct device *dev); //停止设备函数指针

73 int (*hard_start_xmit) (struct sk_buff *skb, struct device *dev); //向硬件发送数据

74 int (*hard_header) (unsigned char *buff, struct device *dev, //生成首部

75 unsigned short type, unsigned long daddr,

76 unsigned long saddr, unsigned len);

77 void (*add_arp) (unsigned long addr, struct sk_buff *skb, //向arp表中添加表项

78 struct device *dev);

79 void (*queue_xmit)(struct sk_buff *skb, struct device *dev, int pri); //向链路层传递数据的函数

80 int (*rebuild_header)(void *eth, struct device *dev); //重建首部

81 unsigned short (*type_trans) (struct sk_buff *skb, struct device *dev); //类型转换

82 void (*send_packet)(struct sk_buff *skb, struct device *dev); //发送数据报

83 void *private; //私有数据

84

85 unsigned short type; //设备类型

86 unsigned short hard_header_len; //首部长度

87 unsigned short mtu; //最大传输单元

88 unsigned char broadcast[MAX_ADDR_LEN]; //广播地址

89 unsigned char dev_addr[MAX_ADDR_LEN]; //设备MAC地址

90 unsigned char addr_len; //硬件地址长度

91 };

net/tcp/sock.h

155 struct sk_buff //描述数据报的

156 {

157 struct sk_buff *next; //

158 struct sk_buff *prev; //链接成双向链表

159 struct sk_buff *link3; //重传队列

160 volatile struct sock *sk; //描述TCP连接

161 unsigned long when; /* used to compute rtt's. */

162 struct device *dev; //属于哪个设备

163 void *mem_addr; //内存地址

164 union

165 {

166 struct tcp_header *th;

167 struct enet_header *eth;

168 struct ip_header *iph;

169 struct udp_header *uh;

170 struct arp *arp;

171 unsigned char *raw;

172 unsigned long seq;

173 } h; //首部,对于不同协议,意义不同

174 unsigned long mem_len; //包括结构体和数据在内的长度

175 unsigned long len; //数据部分的长度

176 unsigned long saddr; //源地址

177 unsigned long daddr; //目的地址

178 int magic; //魔数

179 unsigned long acked:1,used:1,free:1,arp:1, urg_used:1, lock:1; //

180 };

51 struct sock //描述TCP连接的

52 {

53 struct options *opt; //选项

54 unsigned long wmem_alloc; //写内存大小

55 unsigned long rmem_alloc; //读内存大小

56 unsigned long send_seq; //发送序号

57 unsigned long acked_seq; //确认序号

58 unsigned long copied_seq; //拷贝序号

59 unsigned long rcv_ack_seq; //接收确认序号

60 unsigned long window_seq; //窗口序号

61 unsigned long fin_seq; //fin序号

62 unsigned long inuse:1, dead:1, urginline:1,

63 intr:1, blog:1, done:1, reuse:1, keepopen:1, linger:1,

64 delay_acks:1, timeout:3, destroy:1, ack_timed:1, no_check:1,

65 exp_growth:1;

66 int proc; //进程?

67 volatile struct sock *next; //链接下一个

68 volatile struct sock *pair; //

69 struct sk_buff *send_tail; //重传队列尾

70 struct sk_buff *send_head; //重传队列头

71 struct sk_buff *back_log; //积压

72 struct sk_buff *send_tmp; //临时发送缓冲

73 long retransmits; //重新发送

74 struct sk_buff *wback, *wfront, *rqueue; //写队列,接收队列

75 struct proto *prot; //协议

76 struct wait_queue **sleep; //等待队列

77 unsigned long daddr; //目的地址

78 unsigned long saddr; //源地址

79 unsigned short max_unacked; //最大未确认

80 unsigned short window; //窗口大小

81 unsigned short bytes_rcv; //接收字节数

82 unsigned short mtu; //maximum transmit unit

83 unsigned short num; //

84 unsigned short cong_window; //拥塞窗口

85 unsigned short packets_out; //可以发送的数据报数量

86 unsigned short urg; //紧急字段

87 unsigned short shutdown; //

88 unsigned short mss; //max segment size

89 short rtt; //往返

90 short err;

91 unsigned char protocol; //协议名

92 unsigned char state; //状态

93 unsigned char ack_backlog; //确认积压队列

94 unsigned char max_ack_backlog; //队列大小,防止内存耗尽

95 unsigned char priority; //优先级

96 struct tcp_header dummy_th; /* I may be able to get rid of this. *///用来描述连接的另一端

97 struct timer time_wait; //等待定时器

98 };

上面的数据结构已经给出了注释,有些地方我也不是很确定,大致看一下就可以了,具体的含义会在后面的源码中逐步推断出来。

2.
loopback



132 int

133 loopback_init(struct device *dev)

134 {

135 printk ("Loopback device init\n");

136 /* initialize the rest of the device structure. */

137 dev->mtu = 2000; /* mtu */

138 dev->hard_start_xmit = loopback_xmit; //将数据发送给设备

139 dev->open = NULL;

140 dev->hard_header = eth_hard_header; //生成头

141 dev->add_arp = NULL; //不需要arp,因为不会发送给其他主机

142 dev->hard_header_len = sizeof (struct enet_header); //首部长度

143 dev->addr_len = ETHER_ADDR_LEN; //硬件地址长度

144 dev->type = ETHER_TYPE; //设备类型

145 dev->queue_xmit = dev_queue_xmit; //向链路层传递数据的函数

146 dev->rebuild_header = eth_rebuild_header; //重建首部

147 dev->type_trans = eth_type_trans; //类型转换(返回sk_buff首部type字段)

148 dev->loopback = 1; //回环设备标志

149 return (0);

150 }

可以看到初始化函数非常简单,通俗的说 loopback_xmit指明数据从哪来,dev_queue_xmit指明数据到哪去,剩余的则指明数据和设备本身的相关属性。

3.wd8003



647 int

648 wd8003_init(struct device *dev)

649 {

650 unsigned char csum;

651 int i;

652 csum = 0;

653 for (i = 0; i < 8; i++)

654 {

655 csum += inb_p(WD_ROM+i);

656 }

657 if (csum != WD_CHECK)

658 {

659 printk ("Warning WD8013 board not found at i/o = %X.\n",dev->base_addr);

660

661 /* make sure no one can attempt to open the device. */

662 status = OPEN;

663 return (1);

664 }

665 printk("wd8013");
上面是校验工作。(怎么校验的?

666 /* initialize the rest of the device structure. */

667 dev->mtu = 1500; /* eth_mtu */以太网MTU

668 dev->hard_start_xmit = wd8003_start_xmit; //发送数据到硬件的函数

669 dev->open = wd8003_open; //打开函数

670 dev->hard_header = eth_hard_header; //头部生成函数

671 dev->add_arp = eth_add_arp; //在arp表中添加表项函数

672 dev->type_trans = eth_type_trans; //类型转换函数

673 dev->hard_header_len = sizeof (struct enet_header); //首部长度

674 dev->addr_len = ETHER_ADDR_LEN; //地址长度 6

675 dev->type = ETHER_TYPE; //类型

676 dev->queue_xmit = dev_queue_xmit; //向链路层发送数据函数

677 dev->rebuild_header = eth_rebuild_header; //重建首部函数

678 for (i = 0; i < DEV_NUMBUFFS; i++)

679 dev->buffs[i] = NULL; //初始化缓冲区为NULL

681 #ifndef FORCE_8BIT

682 /* check for 16 bit board - it doesn't have register 0/8 aliasing */

683 for (i = 0; i < 8; i++) {

684 if( inb_p( EN_SAPROM+i ) != inb_p( EN_CMD+i) ){

685 csum = inb_p( EN_REG1 ); /* fiddle with 16bit bit */

686 outb( csum ^ BUS16, EN_REG1 ); /* attempt to clear 16bit bit */

687 if( (csum & BUS16) == (inb_p( EN_REG1 ) & BUS16) ) {

688 printk(", using 16 bit I/F ");

689 dconfig |= 1; /* use word mode of operation */

690 outb_p( LAN16ENABLE|MEMMASK, EN_REG5);

691 outb( csum , EN_REG1 );

692 break; /* We have a 16bit board here! */

693 }

694 outb( csum , EN_REG1 );

695 }

696 }

697 #endif /* FORCE_8BIT */

699 /* mapin the interface memory. */

700 outb_p(WD_IMEM,WD_CTL);

702 /* clear the interface memory */

703 for (i = dev->mem_start; i < dev->mem_end; i++)

704 {

705 *((unsigned char *)i) = 0;

706 if (*((unsigned char *)i) != 0)

707 {

708 printk ("WD Memory error.\n");

709 if( (i - dev->mem_start) > 4096 )

710 break;

711 else

712 status = OPEN;

713 }

714 }
假设一切顺利,也就是706行为false,i最终等于mem_end。如果为true也就是MD发生内存错误,那么如果此时有超过一个内存页的可用内存,就用i来记录这个位置。否则,设置status为OPEN,保证没有人会打开此设备。这里说明至少要有4K空间可用。

715 /* Calculate how many pages of memory on board */

716 max_pages = ( i - dev->mem_start )/256;

计算网卡适配器(?)内存页数

718 /* need to set up the dev->mem_end and dev->rmem_end */

719 dev->rmem_end = i;

720 dev->mem_end = i;

722 /* print the initialization message, and the

723 ethernet address. */

724 printk (", %d pages memory, ethernet Address: ", max_pages );

725 for (i = 0; i <ETHER_ADDR_LEN; i++)

726 {

727 dev->dev_addr[i]=inb_p(WD_ROM+i); //读取硬件地址

728 dev->broadcast[i]=0xff; //广播地址设为全1

729 printk ("%2.2X ",dev->dev_addr[i]);

730 }

732 /* Clear the statistics */

733 for( i = 0; i < sizeof( struct enet_statistics ); i++ )

734 ((char *)&stats)[i] = 0;

清空statics,这是用来统计数据的

736 printk ("\n");

737 status = 0;

739 if (irqaction (dev->irq, &wd8003_sigaction))

740 {

741 printk ("Unable to get IRQ%d for wd8013 board\n", dev->irq);

742 return (1);

743 }

注册中断请求处理函数为wd8003_sigaction,它会把耗时操作交给上一篇文章中提到的下半部来处理

744 return (0);

745 }

硬件初始化就分析到这里。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: