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

📄 lanc111.c

📁 avr上的RTOS
💻 C
📖 第 1 页 / 共 3 页
字号:
        nic_outlb(NIC_ACK, INT_TX_EMPTY);        imr &= ~INT_TX_EMPTY;        NutEventPostFromIrq(&ni->ni_tx_rdy);    }    /* Transmit error. */    else if (isr & INT_TX) {        /* re-enable transmit */        nic_bs(0);        nic_outw(NIC_TCR, nic_inlb(NIC_TCR) | TCR_TXENA);        nic_bs(2);        nic_outlb(NIC_ACK, INT_TX);        /* kill the packet */        nic_outlb(NIC_MMUCR, MMU_PKT);        NutEventPostFromIrq(&ni->ni_tx_rdy);    }    /*     * If this is a receive interrupt, then wake up the receiver      * thread.     */    if (isr & INT_RX_OVRN) {        nic_outlb(NIC_ACK, INT_RX_OVRN);        //nic_outlb(NIC_MMUCR, MMU_TOP);    }    if (isr & INT_ERCV) {        nic_outlb(NIC_ACK, INT_ERCV);        NutEventPostFromIrq(&ni->ni_rx_rdy);    }    if (isr & INT_RCV) {        nic_outlb(NIC_ACK, INT_RCV);        imr &= ~INT_RCV;        NutEventPostFromIrq(&ni->ni_rx_rdy);    }    if (isr & INT_ALLOC) {        imr &= ~INT_ALLOC;        NutEventPostFromIrq(&maq);    }    //printf(" -%02X-%02X- ", nic_inlb(NIC_IST), inb(PINE) & 0x20);    nic_outlb(NIC_MSK, imr);}/* * 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 {            nic_outlb(NIC_DATA, *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++ = nic_inlb(NIC_DATA);        } while (il-- != 0);    } while (ih-- != 0);}/*! * \brief Fetch the next packet out of the receive ring buffer. * * Nic interrupts must be disabled when calling this funtion. * * \return Pointer to an allocated ::NETBUF. If there is no *         no data available, then the function returns a *         null pointer. If the NIC's buffer seems to be *         corrupted, a pointer to 0xFFFF is returned. */static NETBUF *NicGetPacket(void){    NETBUF *nb = 0;    //u_char *buf;    u_short fsw;    u_short fbc;    /* Check the fifo empty bit. If it is set, then there is        nothing in the receiver fifo. */    nic_bs(2);    if (nic_inw(NIC_FIFO) & 0x8000) {        return 0;    }    /* Inialize pointer register. */    nic_outw(NIC_PTR, PTR_READ | PTR_RCV | PTR_AUTO_INCR);    _NOP();    _NOP();    _NOP();    _NOP();    /* Read status word and byte count. */    fsw = nic_inw(NIC_DATA);    fbc = nic_inw(NIC_DATA);    //printf("[SW=%04X,BC=%04X]", fsw, fbc);    /* Check for frame errors. */    if (fsw & 0xAC00) {        nb = (NETBUF *) 0xFFFF;    }    /* Check the byte count. */    else if (fbc < 66 || fbc > 1524) {        nb = (NETBUF *) 0xFFFF;    }    else {        /*          * Allocate a NETBUF.          * Hack alert: Rev A chips never set the odd frame indicator.         */        fbc -= 3;        nb = NutNetBufAlloc(0, NBAF_DATALINK, fbc);        /* Perform the read. */        if (nb)            NicRead(nb->nb_dl.vp, fbc);    }    /* Release the packet. */    nic_outlb(NIC_MMUCR, MMU_TOP);    return nb;}/*! * \brief Load a packet into the nic's transmit ring buffer. * * Interupts must have been disabled when calling this function. * * \param nb Network buffer structure containing the packet to be sent. *           The structure must have been allocated by a previous *           call NutNetBufAlloc(). This routine will automatically *           release the buffer in case of an error. * * \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_char odd = 0;    u_char imsk;    //printf("[P]");    /*     * Calculate the number of bytes to be send. Do not send packets      * larger than the Ethernet maximum transfer unit. The MTU     * consist of 1500 data bytes plus the 14 byte Ethernet header     * plus 4 bytes CRC. We check the data bytes only.     */    if ((sz = nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz) > ETHERMTU)        return -1;    /* Disable all interrupts. */    imsk = nic_inlb(NIC_MSK);    nic_outlb(NIC_MSK, 0);    /* Allocate packet buffer space. */    nic_bs(2);    nic_outlb(NIC_MMUCR, MMU_ALO);    if (NicMmuWait(100))        return -1;    /* Enable interrupts including allocation success. */    nic_outlb(NIC_MSK, imsk | INT_ALLOC);    /* The MMU needs some time. Use it to calculate the byte count. */    sz += nb->nb_dl.sz;    sz += 6;    if (sz & 1) {        sz++;        odd++;    }    /* Wait for allocation success. */    while ((nic_inlb(NIC_IST) & INT_ALLOC) == 0) {        if (NutEventWait(&maq, 125)) {            nic_outlb(NIC_MMUCR, MMU_RST);            NicMmuWait(1000);            nic_outlb(NIC_MMUCR, MMU_ALO);            if (NicMmuWait(100) || (nic_inlb(NIC_IST) & INT_ALLOC) == 0) {                if (NutEventWait(&maq, 125)) {                    return -1;                }            }        }    }    /* Disable interrupts. */    imsk = nic_inlb(NIC_MSK);    nic_outlb(NIC_MSK, 0);    nic_outlb(NIC_PNR, nic_inhb(NIC_PNR));    nic_outw(NIC_PTR, 0x4000);    /* Transfer control word. */    nic_outlb(NIC_DATA, 0);    nic_outlb(NIC_DATA, 0);    /* Transfer the byte count. */    nic_outw(NIC_DATA, sz);    /* Transfer the Ethernet frame. */    NicWrite(nb->nb_dl.vp, nb->nb_dl.sz);    NicWrite(nb->nb_nw.vp, nb->nb_nw.sz);    NicWrite(nb->nb_tp.vp, nb->nb_tp.sz);    NicWrite(nb->nb_ap.vp, nb->nb_ap.sz);    if (odd)        nic_outlb(NIC_DATA, 0);    /* Transfer the control word. */    nic_outw(NIC_DATA, 0);    /* Enqueue packet. */    if (NicMmuWait(100))        return -1;    nic_outlb(NIC_MMUCR, MMU_ENQ);    /* Enable interrupts. */    imsk |= INT_TX | INT_TX_EMPTY;    nic_outlb(NIC_MSK, imsk);    return 0;}/*! \fn NicRxLanc(void *arg) * \brief NIC receiver thread. * */THREAD(NicRxLanc, arg){    NUTDEVICE *dev;    IFNET *ifn;    NICINFO *ni;    NETBUF *nb;    u_char imsk;    dev = arg;    ifn = (IFNET *) dev->dev_icb;    ni = (NICINFO *) dev->dev_dcb;    /*     * This is a temporary hack. Due to a change in initialization,     * we may not have got a MAC address yet. Wait until one has been     * set.     */    for (;;) {        if (*((u_long *) (ifn->if_mac)) && *((u_long *) (ifn->if_mac)) != 0xFFFFFFFFUL) {            break;        }        NutSleep(63);    }    /*     * Do not continue unless we managed to start the NIC. We are     * trapped here if the Ethernet link cannot be established.     * This happens, for example, if no Ethernet cable is plugged     * in.     */    while(NicStart(ifn->if_mac)) {        NutSleep(1000);    }    LANC111_SIGNAL_MODE();    sbi(EIMSK, LANC111_SIGNAL_IRQ);    NutEventPost(&mutex);    /* Run at high priority. */    NutThreadSetPriority(9);    for (;;) {        /*         * Wait for the arrival of new packets or         * check the receiver every two second.         */        NutEventWait(&ni->ni_rx_rdy, 2000);        /*         * Fetch all packets from the NIC's internal         * buffer and pass them to the registered handler.         */        imsk = nic_inlb(NIC_MSK);        nic_outlb(NIC_MSK, 0);        while ((nb = NicGetPacket()) != 0) {            if (nb != (NETBUF *) 0xFFFF) {                ni->ni_rx_packets++;                (*ifn->if_recv) (dev, nb);            }        }        nic_outlb(NIC_MSK, imsk | INT_RCV | INT_ERCV);    }}/*! * \brief Send Ethernet packet. * * \param dev   Identifies the device to use. * \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. */int LancOutput(NUTDEVICE * dev, NETBUF * nb){    static u_long mx_wait = 5000;    int rc = -1;    NICINFO *ni;    /*     * After initialization we are waiting for a long time to give     * the PHY a chance to establish an Ethernet link.     */    if (NutEventWait(&mutex, mx_wait) == 0) {        ni = (NICINFO *) dev->dev_dcb;        if (NicPutPacket(nb) == 0) {            ni->ni_tx_packets++;            rc = 0;            /* Ethernet works. Set a long waiting time in case we               temporarly lose the link next time. */            mx_wait = 5000;        }        NutEventPost(&mutex);    }    /*     * Probably no Ethernet link. Significantly reduce the waiting     * time, so following transmission will soon return an error.     */    else {        mx_wait = 500;    }    return rc;}/*! * \brief Initialize Ethernet hardware. * * Resets the LAN91C111 Ethernet controller, initializes all required  * hardware registers and starts a background thread for incoming  * Ethernet traffic. * * Applications should do not directly call this function. It is  * automatically executed during during device registration by  * NutRegisterDevice(). * * If the network configuration hasn't been set by the application * before registering the specified device, this function will * call NutNetLoadConfig() to get the MAC address. * * \param dev Identifies the device to initialize. */int LancInit(NUTDEVICE * dev){    /* Disable NIC interrupt and clear NICINFO structure. */    cbi(EIMSK, LANC111_SIGNAL_IRQ);    memset(dev->dev_dcb, 0, sizeof(NICINFO));    /* Register interrupt handler and enable interrupts. */    if (NutRegisterIrqHandler(&LANC111_SIGNAL, NicInterrupt, dev))        return -1;    /*     * Start the receiver thread.     */    NutThreadCreate("rxi5", NicRxLanc, dev, 640);    //NutSleep(500);    return 0;}static NICINFO dcb_eth0;/*! * \brief Network interface information structure. * * Used to call. */static IFNET ifn_eth0 = {    IFT_ETHER,                  /*!< \brief Interface type. */    {0, 0, 0, 0, 0, 0},         /*!< \brief Hardware net address. */    0,                          /*!< \brief IP address. */    0,                          /*!< \brief Remote IP address for point to point. */    0,                          /*!< \brief IP network mask. */    ETHERMTU,                   /*!< \brief Maximum size of a transmission unit. */    0,                          /*!< \brief Packet identifier. */    0,                          /*!< \brief Linked list of arp entries. */    NutEtherInput,              /*!< \brief Routine to pass received data to, if_recv(). */    LancOutput,                 /*!< \brief Driver output routine, if_send(). */    NutEtherOutput              /*!< \brief Media output routine, if_output(). */};/*! * \brief Device information structure. * * A pointer to this structure must be passed to NutRegisterDevice()  * to bind this Ethernet device driver to the Nut/OS kernel. * An application may then call NutNetIfConfig() with the name \em eth0  * of this driver to initialize the network interface. *  */NUTDEVICE devSmsc111 = {    0,                          /* Pointer to next device. */    {'e', 't', 'h', '0', 0, 0, 0, 0, 0},        /* Unique device name. */    IFTYP_NET,                  /* Type of device. */    0,                          /* Base address. */    0,                          /* First interrupt number. */    &ifn_eth0,                  /* Interface control block. */    &dcb_eth0,                  /* Driver control block. */    LancInit,                   /* Driver initialization routine. */    0,                          /* Driver specific control function. */    0,                          /* Read from device. */    0,                          /* Write to device. */    0,                          /* Write from program space data to device. */    0,                          /* Open a device or file. */    0,                          /* Close a device or file. */    0                           /* Request file size. */};/*@}*/

⌨️ 快捷键说明

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