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

📄 nicrtl.c

📁 avr上的RTOS
💻 C
📖 第 1 页 / 共 3 页
字号:
    } else {        while (++cnt && bit_is_clear(RTL_EESK_PIN, RTL_EESK_BIT));    }#ifdef RTL_EE_MEMBUS    /*     * Enable memory interface.     */#ifdef __AVR_ENHANCED__    /* On the ATmega 128 we release bits 5-7 as normal port pins. */    outb(XMCRB, inb(XMCRB) & ~(_BV(XMM0) | _BV(XMM1)));#else    /* On the ATmega 103 we have to disable the external memory interface. */    sbi(MCUCR, SRE);#endif#endif    /* Reset port outputs to default. */    cbi(RTL_EEDO_PORT, RTL_EEDO_BIT);    cbi(RTL_EEDO_DDR, RTL_EEDO_BIT);#ifdef RTL_EEMU_BIT    cbi(RTL_EEMU_PORT, RTL_EEMU_BIT);    cbi(RTL_EEMU_DDR, RTL_EEMU_BIT);#endif    /* Restore previous interrupt enable state. */    NutExitCritical();    /* Wait until controller ready. */    while (NICINB(NIC_CR) != (NIC_CR_STP | NIC_CR_RD2));    return cnt ? 0 : -1;#else    return -1;#endif}#ifdef RTL_EESK_BIT/* * 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 */};#endif/*! * \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 RTL_EESK_BIT    register u_char clk;    register u_char cnt;    register u_char val;    /*     * Disable all interrupts. This routine requires critical timing     * and optionally may disable the memory interface.     */    NutEnterCritical();    /*     * Prepare the EEPROM emulation port bits. Configure the EEDO and     * the EEMU lines as outputs and set EEDO to low and EEMU to high.     */    cbi(RTL_EEDO_PORT, RTL_EEDO_BIT);    sbi(RTL_EEDO_DDR, RTL_EEDO_BIT);#ifdef RTL_EEMU_BIT    sbi(RTL_EEMU_PORT, RTL_EEMU_BIT);    sbi(RTL_EEMU_DDR, RTL_EEMU_BIT);#endif    NutDelay(20);    /*     * 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. */    NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);    NICOUTB(NIC_PG3_EECR, NIC_EECR_EEM0);    /*     * We can avoid wasting port pins for EEPROM emulation by using the     * upper bits of the address bus.     */#ifdef RTL_EE_MEMBUS    /*     * No external memory access beyond this point.     */#ifdef __AVR_ENHANCED__    /* On the ATmega 128 we release bits 5-7 as normal port pins. */    outb(XMCRB, inb(XMCRB) | _BV(XMM0) | _BV(XMM1));#else    /* On the ATmega 103 we have to disable the external memory interface. */    cbi(MCUCR, SRE);#endif#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));        }    }#ifdef RTL_EE_MEMBUS    /*     * Enable memory interface.     */#ifdef __AVR_ENHANCED__    /* On the ATmega 128 we release bits 5-7 as normal port pins. */    outb(XMCRB, inb(XMCRB) & ~(_BV(XMM0) | _BV(XMM1)));#else    /* On the ATmega 103 we have to disable the external memory interface. */    sbi(MCUCR, SRE);#endif#endif    /* Reset port outputs to default. */    cbi(RTL_EEDO_DDR, RTL_EEDO_BIT);#ifdef RTL_EEMU_BIT    cbi(RTL_EEMU_PORT, RTL_EEMU_BIT);    cbi(RTL_EEMU_DDR, RTL_EEMU_BIT);#endif    /* Restore previous interrupt enable state. */    NutExitCritical();#endif}/* * Fires up the network interface. NIC interrupts * should have been disabled when calling this * function. */static int NicStart(CONST u_char * mac){    u_char i;    if (NicReset()) {        return -1;    }    if (DetectNicEeprom() == 0) {        EmulateNicEeprom();    }    /*     * Mask all interrupts and clear any interrupt status flag to set the     * INT pin back to low.     */    NICOUTB(NIC_PG0_IMR, 0);    NICOUTB(NIC_PG0_ISR, 0xff);    /*     * During reset the nic loaded its initial configuration from an     * external eeprom. On the ethernut board we do not have any     * configuration eeprom, but simply tied the eeprom data line to     * high level. So we have to clear some bits in the configuration     * register. Switch to register page 3.     */    NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0 | NIC_CR_PS1);    /*     * The nic configuration registers are write protected unless both     * EEM bits are set to 1.     */    NICOUTB(NIC_PG3_EECR, NIC_EECR_EEM0 | NIC_EECR_EEM1);    /*     * Network media had been set to 10Base2 by the virtual EEPROM and     * will be set now to auto detect. This will initiate a link test.     * We don't force 10BaseT, because this would disable the link test.     */    NICOUTB(NIC_PG3_CONFIG2, NIC_CONFIG2_BSELB);    /*     * Disable sleep and power down.     *     * The virtual EEPROM (resistor tight to VCC) will set all bits of     * CONFIG3 to 1. Unfortunately we are not able to modify the full     * duplex bit. The only solution is to use a real EEPROM or emulate     * one.     */    NICOUTB(NIC_PG3_CONFIG3, NIC_CONFIG3_LEDS1 | NIC_CONFIG3_LEDS1);    /*     * Reenable write protection of the nic configuration registers     * and wait for link test to complete.     */    NICOUTB(NIC_PG3_EECR, 0);    NutDelay(255);    /*     * Switch to register page 0 and set data configuration register     * to byte-wide DMA transfers, normal operation (no loopback),     * send command not executed and 8 byte fifo threshold.     */    NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2);    NICOUTB(NIC_PG0_DCR, NIC_DCR_LS | NIC_DCR_FT1);    /*     * Clear remote dma byte count register.     */    NICOUTB(NIC_PG0_RBCR0, 0);    NICOUTB(NIC_PG0_RBCR1, 0);    /*     * Temporarily set receiver to monitor mode and transmitter to     * internal loopback mode. Incoming packets will not be stored     * in the nic ring buffer and no data will be send to the network.     */    NICOUTB(NIC_PG0_RCR, NIC_RCR_MON);    NICOUTB(NIC_PG0_TCR, NIC_TCR_LB0);    /*     * Configure the nic's ring buffer page layout.     * NIC_PG0_BNRY: Last page read.     * NIC_PG0_PSTART: First page of receiver buffer.     * NIC_PG0_PSTOP: Last page of receiver buffer.     */    NICOUTB(NIC_PG0_TPSR, NIC_FIRST_TX_PAGE);    NICOUTB(NIC_PG0_BNRY, NIC_STOP_PAGE - 1);    NICOUTB(NIC_PG0_PSTART, NIC_FIRST_RX_PAGE);    NICOUTB(NIC_PG0_PSTOP, NIC_STOP_PAGE);    /*     * Once again clear interrupt status register.     */    NICOUTB(NIC_PG0_ISR, 0xff);    /*     * Switch to register page 1 and copy our MAC address into the nic.     * We are still in stop mode.     */    NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2 | NIC_CR_PS0);    for (i = 0; i < 6; i++)        NICOUTB(NIC_PG1_PAR0 + i, mac[i]);    /*     * Clear multicast filter bits to disable all packets.     */    for (i = 0; i < 8; i++)        NICOUTB(NIC_PG1_MAR0 + i, 0);    /*     * Set current page pointer to one page after the boundary pointer.     */    NICOUTB(NIC_PG1_CURR, NIC_FIRST_RX_PAGE);    /*     * Switch back to register page 0, remaining in stop mode.     */    NICOUTB(NIC_CR, NIC_CR_STP | NIC_CR_RD2);    /*     * Take receiver out of monitor mode and enable it for accepting     * broadcasts.     */    NICOUTB(NIC_PG0_RCR, NIC_RCR_AB);    /*     * Clear all interrupt status flags and enable interrupts.     */    NICOUTB(NIC_PG0_ISR, 0xff);    /* Note: transmitter if polled, thus no NIC_IMR_PTXE */    NICOUTB(NIC_PG0_IMR, NIC_IMR_PRXE | NIC_IMR_RXEE | NIC_IMR_TXEE | NIC_IMR_OVWE);    /*     * Fire up the nic by clearing the stop bit and setting the start bit.     * To activate the local receive dma we must also take the nic out of     * the local loopback mode.     */    NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2);    NICOUTB(NIC_PG0_TCR, 0);    NutDelay(255);    return 0;}/*! * Complete remote DMA. */static void NicCompleteDma(void){    u_char i;    /*     * Complete remote dma.     */    NICOUTB(NIC_CR, NIC_CR_STA | NIC_CR_RD2);    /*     * Check that we have a DMA complete flag.     */    for (i = 0; i <= 20; i++)        if (NICINB(NIC_PG0_ISR) & NIC_ISR_RDC)            break;    /*     * Reset remote dma complete flag.     */    NICOUTB(NIC_PG0_ISR, NIC_ISR_RDC);}/* * Write data block to the NIC. */static void NicWrite(u_char * buf, u_short len){    register u_short l = len - 1;    register u_char ih = (u_short) l >> 8;    register u_char il = (u_char) l;    if (!len)        return;    do {        do {            NICOUTB(NIC_IOPORT, *buf++);        } while (il-- != 0);    } while (ih-- != 0);}/* * Read data block from the NIC. */static void NicRead(u_char * buf, u_short len){    register u_short l = len - 1;    register u_char ih = (u_short) l >> 8;    register u_char il = (u_char) l;    if (!len)        return;    do {        do {            *buf++ = NICINB(NIC_IOPORT);        } while (il-- != 0);    } while (ih-- != 0);}/*! * \brief Load a packet into the nic's transmit ring buffer. * * * \param base NIC hardware base address. * \param nb Network buffer structure containing the packet to be sent. *           The structure must have been allocated by a previous *           call NutNetBufAlloc(). * * \return 0 on success, -1 in case of any errors. Errors *         will automatically release the network buffer *         structure. */static int NicPutPacket(NETBUF * nb){    u_short sz;    u_short i;    u_char padding = 0;    /*     * Calculate the number of bytes to be send. Do not     * send packets larger than 1514 bytes.     *     * The previous version was wrong by specifying a maximum     * of 1518, because it didn't take the CRC into account,     * which is generated by the hardware and automatically     * appended. Thanks to Bengt Florin, who discovered this.     */    sz = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz;    if (sz > 1514)        return -1;    /*     * The controller will not append pad bytes,     * so we have to do this.     */    if (sz < 60) {        padding = (u_char) (60 - sz);        sz = 60;    }    /*     * Bengt Florin introduces polling mode for the transmitter. Be     * aware, that this may introduce other problems. If a high     * priority thread is waiting for the transmitter, it may hold     * the CPU for more than 1.2 milliseconds in worst cases.     */    while (NICINB(NIC_CR) & NIC_CR_TXP)        NutThreadYield();    /* we don't want to be interrupted by NIC owerflow */    cbi(EIMSK, RTL_SIGNAL_IRQ);    /*

⌨️ 快捷键说明

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