• 网卡搭建新通道


    一、网卡工作基本原理
    1.网络模型
    1.1 OSI七层模型
    OSI(Open SystemInterconnection),开放式系统互联参考模型 。它把网络协议从逻辑上分为了7层。
    通过七个层次使不同的系统网络之间实现可靠的通讯。
    1.2 Linux四层模型
    OSI参考模型的过于庞大、复杂招致了许多批评。与此对照,由技术人员自己开发的TCP/IP协议栈获得了更为广泛的应用。


    2.网卡硬件结构

    网卡的实质就是MAC通过MII接口控制PHY的过程

    2.1 DM9000硬件结构

    MAC属于数据链路层,PHY数据物理层

    2.2 MAC
    MAC主要负责数据帧的构建、数据差错检查、传送控制等。


    2.3 PHY
    PHY是物理接口收发器,属于物理层,当它收到MAC过来的数据时,它会去加上校验码,然后按照物理层的规则进行数据编码,再发送到传输介质上。接收过程则相反


    2.4 MII
    MII:媒体独立接口, “媒体独立”表明MAC一定情况下,任何类型的PHY设备都可以正常工作。


    3.DM9000工作特性
    3.1 编程接口

    DM9000只有两种接口:INDEX接口(偏移接口)、数据接口(内容接口)
    2440平台片选为什么是0x2开头的,DM9000连接的2440是CS4,而CS4是片选4(nGCS4),对应的基地址是0x20000000
    为什么是300:打开DM9000芯片手册,300H是芯片的基地址。
    为什么是4:DM9000传输数据是用SD0~SD15,cmd位来决定使用INDEX端口或者数据端口。

    二、DM9000驱动程序设计
    1. /*
    2.  * dm9000.c
    3.  *
    4.  * Created on: 2016-11-25
    5.  * Author: root
    6.  */
    7. #include "dm9000.h"

    8. #define DM_ADD (*((volatile unsigned short *)0x20000300))
    9. #define DM_DATA (*((volatile unsigned short *)0x20000304))

    10. #define BWSCON (*(volatile unsigned long*) 0x48000000)
    11. #define BANKCON4 (*(volatile unsigned long*) 0x48000014)
    12. #define GPFCON (*(volatile unsigned long*) 0x56000050)
    13. #define EXTINT0 (*(volatile unsigned long*) 0x56000088)
    14. #define INTMSK (*(volatile unsigned long*) 0X4A000008)
    15. #define EINTMASK (*(volatile unsigned long*) 0x560000A4)
    16. #define SRCPND (*(volatile unsigned long*) 0X4A000000)
    17. #define INTPND (*(volatile unsigned long*) 0X4A000010)
    18. #define EINTPEND (*(volatile unsigned long*) 0x560000A8)

    19. typedef unsigned char u8;
    20. typedef unsigned short u16;
    21. typedef unsigned int u32;

    22. u8 mac_addr[6] = {9,8,7,6,5,4};
    23. u8 buffer[1000];

    24. void cs_init()
    25. {
    26.     //设置bank4为16位长度
    27.     BWSCON = BWSCON & (~(0x3<<16));
    28.     BWSCON = BWSCON | (0x01<<16);
    29.     //设置时钟
    30.     BANKCON4 = (0x0<<13)|(0x0<<11)|(0x7<<8)|(0x1<<6)|(0x0<<4)|(0x0<<2)|(0x0<<0);
    31. }

    32. void int_init()
    33. {
    34.     //配置GPF7为EINT7
    35.     GPFCON = GPFCON & (~(0X3)<<14);
    36.     GPFCON = GPFCON | ((0X2)<<14);

    37.     EXTINT0 = EXTINT0 & (~(0X7)<<28);
    38.     EXTINT0 = EXTINT0 | ((0X1)<<28);

    39.     INTMSK = INTMSK & (~(1<<4));
    40.     EINTMASK = EINTMASK & (~(0x1<<7));

    41.     SRCPND = (1<<4);
    42.     INTPND = (1<<4);
    43. }

    44. //dm9000寄存器读取函数
    45. void dm9000_reg_write(u16 reg, u16 data)
    46. {
    47.     DM_ADD = reg;
    48.     DM_DATA = data;
    49. }

    50. //dm9000寄存器写入函数
    51. u8 dm9000_reg_read(u16 reg)
    52. {
    53.     DM_ADD = reg;
    54.     return DM_DATA;
    55. }

    56. void dm9000_reset()
    57. {
    58.     //设置成输出
    59.     dm9000_reg_write(DM9000_GPCR, GPCR_GPIO0_OUT);
    60.     //写0清零POWER_DOWN信号,使PHY使活动的
    61.     dm9000_reg_write(DM9000_GPR, 0);
    62.     //软件重启,MAC Internal loopback模式,重启
    63.     dm9000_reg_write(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST));
    64.     //重新复位(第二次)
    65.     dm9000_reg_write(DM9000_NCR, 0);
    66.     dm9000_reg_write(DM9000_NCR, (NCR_LBK_INT_MAC | NCR_RST));
    67. }

    68. void dm9000_probe(void)
    69. {
    70.     u32 id_val;
    71.     //读取供应商的值,并比较
    72.     id_val = dm9000_reg_read(DM9000_VIDL);
    73.     id_val |= dm9000_reg_read(DM9000_VIDH) << 8;
    74.     id_val |= dm9000_reg_read(DM9000_PIDL) << 16;
    75.     id_val |= dm9000_reg_read(DM9000_PIDH) << 24;
    76.     if (id_val == DM9000_ID) {
    77.         printf("dm9000 is found! ");
    78.         return;
    79.     } else {
    80.         printf("dm9000 is not found! ");
    81.         return;
    82.     }
    83. }

    84. void dm9000_init()
    85. {
    86.     u32 i;
    87.     /*设置片选*/
    88.     cs_init();

    89.     /*中断初始化*/
    90.     int_init();

    91.     /*复位设备*/
    92.     dm9000_reset();

    93.     /*捕获dm9000*/
    94.     dm9000_probe();

    95.     /*MAC初始化*/
    96.     /* Program operating register, only internal phy supported */
    97.     dm9000_reg_write(DM9000_NCR, 0x0);
    98.         /* TX Polling clear */
    99.     dm9000_reg_write(DM9000_TCR, 0);
    100.         /* Less 3Kb, 200us */
    101.     dm9000_reg_write(DM9000_BPTR, BPTR_BPHW(3) | BPTR_JPT_600US);
    102.         /* Flow Control : High/Low Water */
    103.     dm9000_reg_write(DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));
    104.         /* SH FIXME: This looks Flow Control */
    105.     dm9000_reg_write(DM9000_FCR, 0x0);
    106.         /* Special Mode */
    107.     dm9000_reg_write(DM9000_SMCR, 0);
    108.         /* clear TX status */
    109.     dm9000_reg_write(DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
    110.         /* Clear interrupt status */
    111.     dm9000_reg_write(DM9000_ISR, ISR_ROOS | ISR_ROS | ISR_PTS | ISR_PRS);

    112.     /*填充MAC地址*/
    113.     /* fill device MAC address registers */
    114.     for (i = 0; i < 6; i++)
    115.         dm9000_reg_write(DM9000_PAR + i, mac_addr[i]);
    116.     /*多播地址
    117.     for (i = 0, oft = 0x16; i < 8; i++, oft++)
    118.         dm9000_reg_write(oft, 0xff);
    119.     */

    120.     /*激活dm9000*/
    121.     /* Activate DM9000 */
    122.     /* RX enable */
    123.     dm9000_reg_write(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
    124.     /* Enable TX/RX interrupt mask */
    125.     dm9000_reg_write(DM9000_IMR, IMR_PAR);
    126. }

    127. void dm9000_tx(u8 *data,u32 length)
    128. {
    129.     u32 i;
    130.     /*禁止中断*/
    131.     dm9000_reg_write(DM9000_IMR, 0x80);
    132.     /*写入发送数据的长度*/
    133.     dm9000_reg_write(DM9000_TXPLL, length & 0xff);
    134.     dm9000_reg_write(DM9000_TXPLH, (length >> 8) & 0xff);
    135.     /*写入待发送的数据*/
    136.     DM_ADD = DM9000_MWCMD;
    137.     for(i=0;i<length;i+=2)
    138.     {
    139.         DM_DATA = data[i] | (data[i+1]<<8);
    140.     }
    141.     /*启动发送*/
    142.     dm9000_reg_write(DM9000_TCR, TCR_TXREQ);
    143.     /*等待发送结束*/
    144.     while(1)
    145.     {
    146.         u8 status;
    147.         status = dm9000_reg_read(DM9000_TCR);
    148.         if((status & 0x01) == 0x00)
    149.             break;
    150.     }
    151.     /*清除发送状态*/
    152.     dm9000_reg_write(DM9000_NSR, 0x2c);
    153.     /*恢复中断使能*/
    154.     dm9000_reg_write(DM9000_IMR, 0x81);
    155. }

    156. #define PTK_MAX_LEN 1522

    157. u32 dm9000_rx(u8 *data)
    158. {
    159.     u8 status,len;
    160.     u16 tmp;
    161.     u32 i;
    162.     /*判断是否产生中断,且清除*/
    163.     if(dm9000_reg_read(DM9000_ISR) & 0x01)
    164.         dm9000_reg_write(DM9000_ISR, 0x01);
    165.     else
    166.         return 0;
    167.     /*空读*/
    168.     dm9000_reg_read(DM9000_MRCMDX);
    169.     /*读取状态,读取包长度*/
    170.     status = dm9000_reg_read(DM9000_MRCMD);
    171.     len = DM_DATA;
    172.     /*读取包的数据*/
    173.     if(len<PTK_MAX_LEN)
    174.     {
    175.         for(i=0;i<len;i+=2)
    176.         {
    177.             tmp = DM_DATA;
    178.             data[i] = tmp & 0x0ff;
    179.             data[i+1] = tmp>>8 & 0x0ff;
    180.         }
    181.     }
    182. }

    183. void int_issue()
    184. {
    185.     u32 i;
    186.     i = dm9000_rx(buffer);

    187.     SRCPND = (1<<4);
    188.     INTPND = (1<<4);
    189.     EINTPEND |= 1<<7;
    190. }

    三、ARP协议实现
    1.ARP协议介绍
    1.1 以太网通讯
    在计算机网络中,数据发送的过程,就是一个把数据按照各层协议层层封装的过程。在这个过程中,最终要使用的协议通常是以太网协议(数据链路层协议)。


    1.2 以太网包格式

    目的MAC地址:接收者的物理地址
    源MAC地址:发送者的物理地址
    类型:标明高层的数据使用的协议类型
    数据:高层的数据
    CRC:校验码

    1.3 ARP功能
    在以太网络中,每台计算机的唯一身份标示是MAC地址(物理层的地址),两台计算机要进行通讯,也必须知道对方的MAC地址,但是用户通常只知道对方的IP地址,这个时候,就可以利用ARP(地址解析协议)来向局域网中的所有计算机发送ARP请求包,收到请求包且满足条件的计算机将回复ARP应答包,告知其MAC地址。所以ARP协议是一种利用IP地址或者MAC地址的协议。

    1.4 ARP格式


    ARP包分为请求包和应答包,通过OP字段来区别。(网络层)
    发送包(A->B):
    以太网的头部以太网目的地址、以太网源地址、帧类型。
    硬件地址长度:就是MAC地址长度
    发送端以太网地址、发送端IP地址:如果A发送给B,这里填写的应该是A的地址
    目的以太网地址:应该填写的是全FFFFF,找的使所有的连接设备。
    目的IP地址:应该是B的IP地址
    应答包(B->A):
    发送端以太网地址、发送端IP地址此时应该是B的地址
    目的以太网地址:A的目的以太网地址(从发送包中获得)
    目的IP地址:应该是A的IP地址

    1.5 编写实现ARP
    开发板做一台主机,PC做一台主机。
    ①开发板发送ARP请求包(pc),PC会往开发板回应答包。
    ②开发板提取PC中的MAC地址打印出来。



    无欲速,无见小利。欲速,则不达;见小利,则大事不成。
  • 相关阅读:
    【Python高级编程034 ● 静态web服务器 ● 静态Web服务器-返回固定页面数据】
    【Python高级编程033 ● 静态web服务器 ● 搭建Python自带静态Web服务器】
    【Python高级编程032 ● http协议 ● http响应报文】
    【Python高级编程031 ● http协议 ● http请求报文】
    做更好的自己:如何下得细功夫
    抓取图片视频等资源链接地址的Python小工具
    互联网应用服务端的常用技术思想与机制纲要
    《反脆弱》读书笔记
    错误启示录
    碎碎念集萃三九
  • 原文地址:https://www.cnblogs.com/ch122633/p/7363303.html
Copyright © 2020-2023  润新知