📄 cs8900.c
字号:
cs_flags ^= 1;}static int CSEthPutPacket(NUTDEVICE * dev, NETBUF * nb){ u_short i; u_short sz; u_char *p; NICINFO *ni; ni = (NICINFO *) dev->dev_dcb; // // Calculate the number of bytes to be send. Do not // send packets larger than 1536 bytes. // sz = nb->nb_dl.sz + nb->nb_nw.sz + nb->nb_tp.sz + nb->nb_ap.sz; if (sz >= 0x600) { NutNetBufFree(nb); return -1; }#if 0 if (tcp_trace) { NutPrintFormat_P(dev_debug, PSTR("[ETHTX-%u]\r\n"), sz); NutPrintFlush(dev_debug); }#endif // Start transmission after entire frame is loaded into CS8900 CSWrite16(CS_TX_CMD_I, 0xC0); // Set frame size CSWrite16(CS_TX_LEN_I, sz); // Wait for buffer space, but only for a while (200ms) // If the cable is disconnected this will never become true // If we don't get the go ahead within 200ms return 0 (Sucess) // And let the upper layers deal with re-transmission // If we return failure TCP sockets will close straight away which probably // isn't the correct behaviour i = 0; while ((CSReadPP16(CS_BUS_STAT) & 0x0100) == 0) { i++; if (i > 20) return 0; NutSleep(10); } // // Transfer ethernet physical header. // CSBeginFrame(); p = nb->nb_dl.vp; for (i = 0; i < nb->nb_dl.sz; i++) { CSWriteFrameByte(*p++); } p = nb->nb_nw.vp; for (i = 0; i < nb->nb_nw.sz; i++) { CSWriteFrameByte(*p++); } p = nb->nb_tp.vp; for (i = 0; i < nb->nb_tp.sz; i++) { CSWriteFrameByte(*p++); } p = nb->nb_ap.vp; for (i = 0; i < nb->nb_ap.sz; i++) { CSWriteFrameByte(*p++); } CSEndFrame(); return 0;}/*! * \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(). This buffer will be automatically * released in case of an error. * * \return 0 on success, -1 in case of any errors. Errors * will automatically release the network buffer * structure. */int CSNicOutput(NUTDEVICE * dev, NETBUF * nb){ int rc = -1; NICINFO *ni; ni = (NICINFO *) dev->dev_dcb;#if 0 if (tcp_trace) { NutPrintFormat_P(dev_debug, PSTR("Enter EthOutput\r\n")); NutPrintFlush(dev_debug); }#endif if ((rc = CSEthPutPacket(dev, nb)) == 0) ni->ni_tx_packets++; return rc;}/*! \fn PPPRx(void *arg) * \brief PPP receiver thread. * * * It runs with high priority. */THREAD(CSNICrx, arg){ NUTDEVICE *dev; IFNET *ifn; NICINFO *ni; NETBUF *nb; u_char *p; u_char *q; u_short i, m; volatile u_short l; dev = arg; ifn = (IFNET *) dev->dev_icb; ni = (NICINFO *) dev->dev_dcb;#if 0 if (tcp_trace) { NutPrintFormat_P(dev_debug, PSTR("Enter ETHReceive\r\n")); NutPrintFlush(dev_debug); }#endif l = 0; NutThreadSetPriority(8); for (;;) { while ((CSReadPP16(CS_RX_EVENT) & 0x0100) == 0) { NutSleep(10); }#ifdef NUT_CS8900_OLD // Get the RxStatus But don't let the compiler do any optomisation asm volatile ("lds __tmp_reg__, %3" "\n\t" "mov %B0, __tmp_reg__" "\n\t" "lds __tmp_reg__, %2" "\n\t" "mov %A0, __tmp_reg__" "\n\t":"=r" (l) :"0"(l), "n"((unsigned short) (CS_DATA_P0)), "n"((unsigned short) (CS_DATA_P0 + 1)) ); // Get the Packet Length But don't let the compiler do any optomisation asm volatile ("lds __tmp_reg__, %3" "\n\t" "mov %B0, __tmp_reg__" "\n\t" "lds __tmp_reg__, %2" "\n\t" "mov %A0, __tmp_reg__" "\n\t":"=r" (l) :"0"(l), "n"((unsigned short) (CS_DATA_P0)), "n"((unsigned short) (CS_DATA_P0 + 1)) );#else l = *(u_char *) (CS_DATA_P0 + 1) << 8 | *(u_char *) (CS_DATA_P0); l = *(u_char *) (CS_DATA_P0 + 1) << 8 | *(u_char *) (CS_DATA_P0);#endif //NutPrintFormat_P(dev_debug,PSTR("RxLength = %x \r\n"), l); //NutPrintFlush(dev_debug); // Account for odd length packets if (l & 1) m = l - 1; else m = l; nb = NutNetBufAlloc(0, NBAF_DATALINK, l); if (nb) { q = nb->nb_dl.vp; for (i = 0; i < m; i += 2) { p = (u_char *) CS_DATA_P0; *q++ = *p; p = (u_char *) CS_DATA_P0 + 1; *q++ = *p; } // Odd length packets if (m != l) { p = (u_char *) CS_DATA_P0; *q++ = *p; p = (u_char *) CS_DATA_P0 + 1; m = *p; } ni->ni_rx_packets++; (*ifn->if_recv) (dev, nb); } }}void CSSoftwareWakeup(void){ volatile u_short *p; p = (u_short *) CS_PP_PTR; *p = CS_SELF_CTRL; NutDelay(10);}void CSSoftwareReset(void){ volatile u_short *p; p = (u_short *) CS_PP_PTR; *p = CS_SELF_CTRL; p = (u_short *) CS_DATA_P0; *p = 0x0040;}/*! * \brief Initialize Ethernet Interface. * * * Applications typically do not use this function, but * call NutNetIfConfig(). * * \param dev Identifies the device to initialize. The * structure must be properly set. */int CSNicInit(NUTDEVICE * dev){ u_short i; u_short j; IFNET *ifn; NICINFO *ni;#if 0 if (tcp_trace) { NutPrintFormat_P(dev_debug, PSTR("Enter NicInit \r\n")); NutPrintFlush(dev_debug); }#endif cs_base = dev->dev_base; if (confnet.cd_size == 0) NutNetLoadConfig(dev->dev_name); ifn = dev->dev_icb; memcpy(ifn->if_mac, confnet.cdn_mac, 6); memset(dev->dev_dcb, 0, sizeof(NICINFO)); ni = (NICINFO *) dev->dev_dcb; // Take CS8900 out of reset and wait for internal reset to complete#ifdef NUT_CS8900_OLD outp(inp(PORTD) & ~RESETE, PORTD);#else CSSoftwareWakeup(); CSSoftwareReset();#endif NutDelay(100); // Check for presence if (CSReadPP16(CS_PROD_ID) != 0x630E) return -1; // // Copy our MAC address to the NIC // for (i = 0; i < 6; i += 2) { j = ifn->if_mac[i] << 8; j |= ifn->if_mac[i + 1]; CSWritePP16(CS_IEEE_ADDR + i, j); j = CSReadPP16(CS_IEEE_ADDR + i);#if 0 if (tcp_trace) { NutPrintFormat_P(dev_debug, PSTR("ADDR = %x\r\n"), j); NutPrintFlush(dev_debug); }#endif } // // Enable the Transmitter and Receiver // CSWritePP16(CS_LINE_CTRL, 0x00C0); //i = CSReadPP16(CS_LINE_CTRL); //NutPrintFormat_P(dev_debug,PSTR("CS_LINE_CTRL = %x\r\n"), i); CSWritePP16(CS_RX_CTL, 0x0F40); //i = CSReadPP16(CS_RX_CTL); //NutPrintFormat_P(dev_debug,PSTR("CS_RX_CTL = %x\r\n"), i); // // Start receiver thread // NutThreadCreate("csnicrx", CSNICrx, dev, 500); return 0;}/*@}*/#elsevoid keep_icc_happy(void){}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -