⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 realtek.c

📁 含有完整TCP/IP PPP协议的嵌入式操作系统
💻 C
字号:
#include <stdio.h>#include <sys/timer.h>#include "basemon.h"#include "utils.h"#include "uart.h"#include "rtlregs.h"#include "realtek.h"#define RTL_EESK_BIT    5#define RTL_EESK_PORT   PORTC#define RTL_EESK_PIN    PINC#define RTL_EESK_DDR    DDRC#define RTL_EEDO_BIT    6#define RTL_EEDO_PORT   PORTC#define RTL_EEDO_DDR    DDRC#define RTL_EEMU_BIT    7#define RTL_EEMU_PORT   PORTC#define RTL_EEMU_DDR    DDRC#define RTL_EE_MEMBUSstatic int NicReset(void){    volatile u_char *base = (u_char *) 0x8300;    u_char i;    u_char j;    /* Start command clears the reset bit. */    nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2);    //printf("[%02X]", nic_read(NIC_PG0_ISR));    for (j = 0; j < 20; j++) {        printf("SW-Reset...");        i = nic_read(NIC_RESET);        Delay(500);        nic_write(NIC_RESET, i);        for (i = 0; i < 20; i++) {            //Delay(5000);            /*             * ID detection added for version 1.1 boards.             */            if ((nic_read(NIC_PG0_ISR) & NIC_ISR_RST) != 0 && nic_read(NIC_PG0_RBCR0) == 0x50 && nic_read(NIC_PG0_RBCR1) == 0x70) {                puts("OK");                return 0;            }        }        puts("failed\x07");        /*         * Toggle the hardware reset line. Since Ethernut version 1.3 the         * hardware reset pin of the nic is no longer connected to bit 4         * on port E, but wired to the board reset line.         */        if (j == 10) {            puts("HW-Reset");            sbi(DDRE, 4);            sbi(PORTE, 4);            Delay(100000);            cbi(PORTE, 4);            Delay(250000);        }    }    return -1;}static int DetectNicEeprom(void){#ifdef __AVR_ENHANCED__    register u_int cnt = 0;    cli();    /*     * Prepare the EEPROM emulation port bits. Configure the EEDO     * and the EEMU lines as outputs and set both lines to high.     */    outb(PORTC, 0xC0);    outb(DDRC, 0xC0);    /*     * Force the chip to re-read the EEPROM contents.     */    nic_outlb(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);    nic_outlb(NIC_PG3_EECR, NIC_EECR_EEM0);    /*     * No external memory access beyond this point.     */#if defined(__AVR_AT90CAN128__)    cbi(XMCRA, SRE);#else    cbi(MCUCR, SRE);#endif    /*     * Check, if the chip toggles our EESK input. If not, we do not     * have EEPROM emulation hardware.     */    if(bit_is_set(PINC, 5)) {        while(++cnt && bit_is_set(PINC, 5));    }    else {        while(++cnt && bit_is_clear(PINC, 5));    }    /*     * Enable memory interface.     */#if defined(__AVR_AT90CAN128__)    sbi(XMCRA, SRE);#else    sbi(MCUCR, SRE);#endif    /* Reset port outputs to default. */    outb(PORTC, 0x00);    outb(DDRC, 0x00);    /* Wait until controller ready. */    while(nic_inlb(NIC_CR) != (NIC_CR_STP | NIC_CR_RD2));    sei();    return cnt ? 0 : -1;#else    return -1;#endif}/* * Emulated EEPROM contents. * * In jumper mode our influence is quite limited, only CONFIG3 and CONFIG4 * can be modified. */static prog_char nic_eeprom[18] = {    0xFF,   /* CONFIG2: jPL1 jPL0   0      jBS4   jBS3   jBS2  jBS1  jBS0  */    0xFF,   /* CONFIG1: 1    jIRQS2 jIRQS1 jIRQS0 jIOS3  jIOS2 jIOS1 jIOS0 */    0xFF,   /* CONFIG4: -    -      -      -      -      -     -     IOMS  */    0x30,   /* CONFIG3  PNP  FUDUP  LEDS1  LEDS0  -      0     PWRDN ACTB  */    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* MAC */    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF /* ID */};/*! * \brief EEPROM emulator. * * Forces the chip to re-read the EEPROM contents and emulates a serial * EEPROM. * * If the hardware does not support this feature, then this call will * never return. Thus, make sure to have the driver properly configured. */static void EmulateNicEeprom(void){#ifdef __AVR_ENHANCED__    register u_char clk;    register u_char cnt;    register u_char val;    /*     * Prepare the EEPROM emulation port bits. Configure the EEDO and     * the EEMU lines as outputs and set EEDO to low and EEMU to high.     */    outb(PORTC, 0xC0);    outb(DDRC, 0xC0);    /*     * Start EEPROM configuration. Stop/abort any activity and select     * configuration page 3. Setting bit EEM0 will force the controller     * to read the EEPROM contents.     */    /* Select page 3, stop and abort/complete. */    nic_outlb(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);    nic_outlb(NIC_PG3_EECR, NIC_EECR_EEM0);    /*     * We can avoid wasting port pins for EEPROM emulation by using the     * upper bits of the address bus.     */    /*     * No external memory access beyond this point.     */#if defined(__AVR_AT90CAN128__)    cbi(XMCRA, SRE);#else    cbi(MCUCR, SRE);#endif    /*     * Loop for all EEPROM words.     */    for(cnt = 0; cnt < sizeof(nic_eeprom); ) {        /*         *         * 1 start bit, always high         * 2 op-code bits         * 7 address bits         * 1 dir change bit, always low         */        for(clk = 0; clk < 11; clk++) {            while(bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));            while(bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));        }        /*         * Shift out the high byte, MSB first. Our data changes at the EESK         * rising edge. Data is sampled by the Realtek at the falling edge.         */        val = PRG_RDB(nic_eeprom + cnt);        cnt++;        for(clk = 0x80; clk; clk >>= 1) {            while(bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));            if(val & clk)                sbi(RTL_EEDO_PORT, RTL_EEDO_BIT);            while(bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));            cbi(RTL_EEDO_PORT, RTL_EEDO_BIT);        }        /*         * Shift out the low byte.         */        val = PRG_RDB(nic_eeprom + cnt);        cnt++;        for(clk = 0x80; clk; clk >>= 1) {            while(bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));            if(val & clk)                sbi(RTL_EEDO_PORT, RTL_EEDO_BIT);            while(bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));            cbi(RTL_EEDO_PORT, RTL_EEDO_BIT);        }        /* 5 remaining clock cycles. */        for(clk = 0; clk < 5; clk++) {            while(bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));            while(bit_is_set(RTL_EESK_PIN, RTL_EESK_BIT));        }    }    /*     * Enable memory interface.     */#if defined(__AVR_AT90CAN128__)    sbi(XMCRA, SRE);#else    sbi(MCUCR, SRE);#endif    /* Reset port outputs to default. */    outb(PORTC, 0x00);    outb(DDRC, 0x00);#endif}/*! * \brief Detect an RTL8019AS chip. */int RealtekDetect(void){    u_char bv;    bv = nic_inlb(NIC_CR);    if(bv & (NIC_CR_PS0 | NIC_CR_PS1)) {        nic_outlb(NIC_CR, NIC_CR_STP | NIC_CR_RD2);    }    if(nic_inw(NIC_PG0_RBCR0) != 0x7050) {        return -1;    }    return 0;}void RealtekLoop(void){    printf_P(presskey_P);    for (;;) {        nic_outlb(NIC_CR, NIC_CR_STP | NIC_CR_RD2);        printf("\rid=0x%04X", nic_inw(NIC_PG0_RBCR0));        if (GetChar()) {            puts("");            return;        }    }}int RealtekTest(void){    int i;    u_char force_swreset = 0;    volatile u_char *base = (u_char *) 0x8300;    u_short nic_id;    /*     * NIC ID detection loop.     */    for (;;) {        /*         * Reset loop.         */        for (;;) {            /*             * The hardware reset pin of the nic is connected             * to bit 4 on port E. Make this pin an output pin             * and toggle it.             */            sbi(DDRE, 4);            sbi(PORTE, 4);            Delay(2000);            cbi(PORTE, 4);            Delay(20000);            /*             * If the hardware reset didn't set the nic in reset             * state, perform an additional software reset and             * wait until the controller enters the reset state.             */            if (force_swreset || (*(base + 7) & 0x80) == 0) {                *(base + 0x1f) = *(base + 0x1f);                Delay(200000);                for (i = 0; i < 255; i++) {                    if (*(base + 7) & 0x80) {                        break;                    }                }                if (i < 255) {                    break;                }                puts("failed\x07");            } else {                break;            }            if (uart_bs >= 0)                break;        }        nic_id = nic_inw(NIC_PG0_RBCR0);        if (nic_id == 0x7050) {            puts("OK");            break;        }        printf("failed, got 0x%04X, expected 0x7050\n\x07", nic_id);        if (force_swreset && uart_bs >= 0)            break;        force_swreset = 1;    }    return 0;}#define NIC_PAGE_SIZE       0x100#define NIC_START_PAGE      0x40#define NIC_STOP_PAGE       0x60#define NIC_TX_PAGES        6#define NIC_TX_BUFFERS      2#define NIC_FIRST_TX_PAGE   NIC_START_PAGE#define NIC_FIRST_RX_PAGE   (NIC_FIRST_TX_PAGE + NIC_TX_PAGES * NIC_TX_BUFFERS)#define TX_PAGES            12void RealtekSend(void){    u_char mac[] = {        0x00, 0x06, 0x98, 0x00, 0x00, 0x00    };    u_short sz;    u_short i;    volatile u_char *base = (u_char *) 0x8300;    u_char rb;    u_long cnt = 0;    printf("Init controller...");    nic_write(NIC_PG0_IMR, 0);    nic_write(NIC_PG0_ISR, 0xff);    if (NicReset())        return;    printf(" detecting...");    Delay(200000);    if (DetectNicEeprom() == 0) {        printf("EEPROM Emulation...");        EmulateNicEeprom();    }    nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);    nic_write(NIC_PG3_EECR, NIC_EECR_EEM0 | NIC_EECR_EEM1);    nic_write(NIC_PG3_CONFIG3, 0);    nic_write(NIC_PG3_CONFIG2, NIC_CONFIG2_BSELB);    nic_write(NIC_PG3_EECR, 0);    Delay(50000);    nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2);    nic_write(NIC_PG0_DCR, NIC_DCR_LS | NIC_DCR_FT1);    nic_write(NIC_PG0_RBCR0, 0);    nic_write(NIC_PG0_RBCR1, 0);    nic_write(NIC_PG0_RCR, NIC_RCR_MON);    nic_write(NIC_PG0_TCR, NIC_TCR_LB0);    nic_write(NIC_PG0_TPSR, NIC_FIRST_TX_PAGE);    nic_write(NIC_PG0_BNRY, NIC_STOP_PAGE - 1);    nic_write(NIC_PG0_PSTART, NIC_FIRST_RX_PAGE);    nic_write(NIC_PG0_PSTOP, NIC_STOP_PAGE);    nic_write(NIC_PG0_ISR, 0xff);    nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0);    for (i = 0; i < 6; i++)        nic_write(NIC_PG1_PAR0 + i, mac[i]);    for (i = 0; i < 8; i++)        nic_write(NIC_PG1_MAR0 + i, 0);    nic_write(NIC_PG1_CURR, NIC_START_PAGE + TX_PAGES);    nic_write(NIC_CR, NIC_CR_STP | NIC_CR_RD2);    nic_write(NIC_PG0_RCR, NIC_RCR_AB);    nic_write(NIC_PG0_ISR, 0xff);    nic_write(NIC_PG0_IMR, 0);    nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2);    nic_write(NIC_PG0_TCR, 0);    Delay(1000000);    puts("done");    nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);    rb = nic_read(NIC_PG3_CONFIG0);    switch (rb & 0xC0) {    case 0x00:        printf("RTL8019AS ");        if (rb & 0x08)            printf("jumper mode: ");        if (rb & 0x20)            printf("AUI ");        if (rb & 0x10)            printf("PNP ");        break;    case 0xC0:        printf("RTL8019 ");        if (rb & 0x08)            printf("jumper mode: ");        break;    default:        printf("Unknown chip ");        break;    }    if (rb & 0x04)        printf("BNC\x07 ");    if (rb & 0x03)        printf("Failed\x07 ");    rb = nic_read(NIC_PG3_CONFIG1);    printf("IRQ%u ", (rb >> 4) & 7);    rb = nic_read(NIC_PG3_CONFIG2);    switch (rb & 0xC0) {    case 0x00:        printf("Auto ");        break;    case 0x40:        printf("10BaseT ");        break;    case 0x80:        printf("10Base5 ");        break;    case 0xC0:        printf("10Base2 ");        break;    }    printf("\n");    nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2);    for (;;) {        Delay(500000);        printf("\r%lu", cnt++);        sz = 1500;        nic_write(NIC_PG0_RBCR0, sz);        nic_write(NIC_PG0_RBCR1, sz >> 8);        nic_write(NIC_PG0_RSAR0, 0);        nic_write(NIC_PG0_RSAR1, NIC_FIRST_TX_PAGE);        nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD1);        /*         * Transfer ethernet physical header.         */        for (i = 0; i < 6; i++)            nic_write(NIC_IOPORT, 0xFF);        for (i = 0; i < 6; i++)            nic_write(NIC_IOPORT, mac[i]);        nic_write(NIC_IOPORT, 0x08);        nic_write(NIC_IOPORT, 0x00);        /*         * Add pad bytes.         */        for (i = 0; i < sz; i++)            nic_write(NIC_IOPORT, 0);        /*         * Complete remote dma.         */        nic_write(NIC_CR, NIC_CR_STA | NIC_CR_RD2);        for (i = 0; i <= 20; i++)            if (nic_read(NIC_PG0_ISR) & NIC_ISR_RDC)                break;        nic_write(NIC_PG0_ISR, NIC_ISR_RDC);        /*         * Number of bytes to be transmitted.         */        nic_write(NIC_PG0_TBCR0, (sz & 0xff));        nic_write(NIC_PG0_TBCR1, ((sz >> 8) & 0xff));        /*         * First page of packet to be transmitted.         */        nic_write(NIC_PG0_TPSR, NIC_FIRST_TX_PAGE);        /*         * Start transmission.         */        nic_write(NIC_CR, NIC_CR_STA | NIC_CR_TXP | NIC_CR_RD2);        if (GetChar())            break;        Delay(10000);    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -