/* * Sergei Vlasov. * Last edited on: Mar 11, 2016 Document revision: 33 * address@hidden */ #include #include "eth.h" #include "netif/etharp.h" /* Global static variables */ UINT8 eth_link_speed; UINT8 eth_link_mode; UINT8 eth_link_on = 0; UINT8 ncsi_channel_selected = 0; // package/channel we use. Terminal settable UINT8 NCSI_Package[NCSI_MAX_PACKAGE_ID+1]; // up to 8 NCSI-connected packages supported UINT8 NCSI_Channel[NCSI_MAX_CHANNEL_ID]; // up to 31 NCSI channels per package UINT16 *rptr; // DMA UINT8 *tptr; // DMA /* Local function prototypes */ void eth_enable( void ); /* FUNCTIONS CALLED BY LWIP/ETHERNETIF(ipmnetif) */ /* ----------------------------------------------------------------------------- eth_enable(void) / eth_init( void ) The Ethernet controller is configured using the following registers: 1. Power: In the PCONP register set bit PCENET. Remark: On reset, the Ethernet block is disabled (PCENET = 0). 2. Clock: see LPC23xx uman Section 4–7.1. 3. Pins: Select Ethernet pins and their modes in PINSEL2/3 and PINMODE2/3 (Section 9–5). 4. Wakeup: Use the INTWAKE register (Table 4–45) to enable activity on the Ethernet port to wake up the microcontroller from Power-down mode. 5. Interrupts: Interrupts are (now disabled (Table 7–71). 6. Initialization: see Section 11–17.2. */ #if LWIP_TCP void tcp_tmr_callback( UINT8 *context ) { tcp_tmr(); timer_add_callout_queue( (void *)ð_link_mode, /*/ ~250msec timeout */ TCP_REFRESH_PERIOD_TICKS, tcp_tmr_callback, 0 ); } /*/ tcp_tmr_callback */ #endif #if LWIP_ARP void arp_tmr_callback( UINT8 *context ) { etharp_tmr(); timer_add_callout_queue( (void *)&arp_table, /*/ ~5sec timeout */ ARP_REFRESH_PERIOD_TICKS, arp_tmr_callback, 0 ); } /*/ arp_tmr_callback */ #endif /* eth_init helper */ void eth_enable( void ) { int i; /* Clock enable & Power up the ethernet controller */ PCONP |= PCENET; DelayMs(1); EthPowerDown = 0; DelayMs(1); /* Enable ethernet pins */ PINSEL2 |= ( PS2_P1_0_ENET_TXD0 | PS2_P1_1_ENET_TXD1 | PS2_P1_4_ENET_TX_EN | PS2_P1_8_ENET_CRS | PS2_P1_9_ENET_RXD0 | PS2_P1_10_ENET_RXD1 | PS2_P1_14_ENET_RX_ER | PS2_P1_15_ENET_REF_CLK ); for(i = 0; i <= NCSI_MAX_PACKAGE_ID; i++) NCSI_Package[i] = 0xFF; // invalidate for(i = 0; i < NCSI_MAX_CHANNEL_ID; i++) // skip the broadcast ch=0x1F NCSI_Channel[i] = 0xFF; // invalidate } // eth_enable /* Initialize Ethernet MAC & Phy */ /* Return value: true = init successful */ /* false = init failed: please retry or abort/cancel */ BOOL eth_init( void ) { int i; eth_enable(); // power on. /* reset MAC */ MAC_MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES; EthCommand = CR_REG_RES | CR_TX_RES | CR_RX_RES; /* init MAC control regs */ MAC_MAC1 = MAC1_PASS_ALL; MAC_MAXF = ETH_MAX_FLEN; // 0x600 = 1536. /* enable RMII */ EthCommand = CR_RMII | CR_PASS_RUNT_FRM; // note: we do not use MDIO MAC_MCFG = 0x8018; // clk/20 + reset MII mgmt // descriptors init. See KS8721 datasheet 18.18 "Reset" MAC_MAC1 |= MAC1_RES_MCS_TX; /* Reset the MAC Control Sublayer Tx */ MAC_MAC1 |= MAC1_RES_TX; /* Put the Tx Function logic in reset */ EthCommand |= CR_TX_RES; /* Reset Transmit Datapath */ MAC_MAC1 &= ~MAC1_RES_MCS_TX; /* Off the Reset MAC TX Ctl Sub logic */ MAC_MAC1 &= ~MAC1_RES_TX; /* Transmit Function logic Reset off */ MAC_MAC1 &= ~MAC1_RECV_EN; MAC_MAC1 |= MAC1_RES_MCS_RX; EthCommand &= ~CR_RX_EN; MAC_MAC1 |= MAC1_RES_RX; EthCommand |= CR_RX_RES; MAC_MAC1 &= ~MAC1_RES_MCS_RX; MAC_MAC1 &= ~MAC1_RES_RX; EthCommand |= CR_PASS_RUNT_FRM; EthCommand |= CR_PASS_RX_FILT; MAC_MAC1 |= MAC1_PASS_ALL; /* pass all receive frames*/ MAC_MAC2 = MAC2_CRC_EN | MAC2_PAD_EN; MAC_CLRT = CLRT_DEF; MAC_IPGR = IPGR_DEF; // IPGR2 = 0x12; MAC_IPGR |= 0x0C00; // IPGR1 = 0x0c; MAC_IPGT = IPGT_FULL_DUP; // init default MAC_MAC2 |= MAC2_FULL_DUP; EthCommand |= CR_FULL_DUP; MAC_SUPP |= SUPP_SPEED; /* 100Mbps */ eth_link_on = 1; // NC-SI version of Init. /* set the Ethernet MAC Address registers */ MAC_SA0 = ( (UINT16)IPMInetIF.hwaddr[0] << 8) | (UINT16)IPMInetIF.hwaddr[1]; MAC_SA1 = ( (UINT16)IPMInetIF.hwaddr[2] << 8) | (UINT16)IPMInetIF.hwaddr[3]; MAC_SA2 = ( (UINT16)IPMInetIF.hwaddr[4] << 8) | (UINT16)IPMInetIF.hwaddr[5]; /* init Rx DMA Descriptors */ for (i = 0; i < NUM_RX_FRAG; i++) { RX_DESC_PACKET(i) = RX_BUF(i); RX_DESC_CTRL(i) = RCTRL_INT | (ETH_FRAG_SIZE-1); RX_STAT_INFO(i) = 0; RX_STAT_HASHCRC(i)= 0; } /* set MAC Rx Descriptor Registers */ EthRxDescriptor = RX_DESC_BASE; // 0x7FE00000 EthRxStatus = RX_STAT_BASE; EthRxDescriptorNumber = NUM_RX_FRAG-1; /* Rx Descriptors Point to 0 */ EthRxConsumeIndex = 0; /* init Tx DMA Descriptors */ for (i = 0; i < NUM_TX_FRAG; i++) { TX_DESC_PACKET(i) = TX_BUF(i); TX_DESC_CTRL(i) = (ETH_FRAG_SIZE-1) | TCTRL_LAST | TCTRL_INT | TCTRL_CRC | TCTRL_PAD | TCTRL_OVERRIDE; TX_STAT_INFO(i) = 0; } /* set MAC Tx Descriptor Registers */ EthTxDescriptor = TX_DESC_BASE; EthTxStatus = TX_STAT_BASE; EthTxDescriptorNumber = NUM_TX_FRAG-1; /* Tx Descriptors Point to 0 */ EthTxProduceIndex = 0; /* receive Broadcast and Perfect Match Packets */ EthRxFliterCtrl = 0; /* enable MAC interrupts */ EthIntEnable = 0; /* reset all interrupts */ EthIntClear = 0xFFFF; // nn /* enable receive and transmit mode of MAC Ethernet core */ EthCommand |= (CR_RX_EN | CR_TX_EN); MAC_MAC1 |= MAC1_RECV_EN; /* Receive enable */ #if LWIP_TCP timer_add_callout_queue( (void *)ð_link_mode, /* ~250msec timeout */ TCP_REFRESH_PERIOD_TICKS, tcp_tmr_callback, (void *)ð_link_mode ); #endif #if LWIP_ARP timer_add_callout_queue( (void *)&arp_table, /* ~5s timeout */ ARP_REFRESH_PERIOD_TICKS, arp_tmr_callback, (void *)&arp_table ); #endif return true; } // eth_init UINT8 eth_get_link_speed( void ) { return eth_link_speed; } // eth_get_link_speed UINT8 eth_get_link_mode( void ) { return eth_link_mode; } // eth_get_link_mode void eth_init_tbuf( void ) { tptr = ( UINT8 * ) ( *( UINT32 * )( TX_DESC_BASE + 8 * EthTxProduceIndex ) ); } // eth_init_tbuf void eth_write_tbuf( void *src, UINT32 len ) { int i; UINT8* s = (UINT8*)src; for( i = 0; i < len; i++ ) { *tptr++ = *s++; // *tbuf++ = *s++; } } // eth_write_tbuf void eth_send_tbuf( UINT16 len ) { UINT32 idx; idx = EthTxProduceIndex; TX_DESC_CTRL( idx ) = (len-1) | TCTRL_LAST | TCTRL_CRC | TCTRL_OVERRIDE; if( ++idx >= NUM_TX_FRAG ) idx = 0; EthTxProduceIndex = idx; } // eth_send_tbuf int eth_check_rcv( void ) { UINT32 a = EthRxProduceIndex; UINT32 b = EthRxConsumeIndex; if( a != b ) return( 1 ); else return( 0 ); } // eth_check_rcv UINT16 eth_get_rcv_size( void ) { UINT16 len; UINT32 idx; idx = EthRxConsumeIndex; len = ( RX_STAT_INFO( idx ) & RINFO_SIZE ) - 3; rptr = ( UINT16 * )RX_DESC_PACKET( idx ); return( len ); } // eth_get_rcv_size void eth_read_rbuf( void *dest, UINT16 len ) { UINT16 * pdest; pdest = dest; while( len > 1 ) { *pdest++ = *rptr++; len -= 2; } if( len ) // leftover byte *( UINT8 * )pdest = ( UINT8 )*rptr++; } // eth_read_rbuf /* -------------------------------------------------------------------------- -------------------------------------------------------------------------- */ void eth_rcv_done( void ) { UINT32 idx; /* DMA free packet. */ idx = EthRxConsumeIndex; if( ++idx == NUM_RX_FRAG ) idx = 0; EthRxConsumeIndex = idx; } // eth_rcv_done /* ---------------------------------------------------------------------------- */ #ifdef LAN_USE_NCSI UINT8 ncsi_data_input(struct netif *netif, struct pbuf *p) { static UINT8 seq; UINT8 stat; NCSI_RESP* resp; DPRINTF( DBG_OTHER_MEDIA | DBG_LVL1, "ncsi_data_input: reply packet received.\n" ); // process NC-SI response resp = (NCSI_RESP*)p->payload; stat = resp->status; // default status if(resp->iid == seq){ DPUTHEX( DBG_WARN | DBG_OTHER_MEDIA, "ncsi retry of 0x", resp->packet_type, ".\n" ); } else switch(resp->packet_type){ case NCSI_ENABLE_BROADCAST_FILTER +NCSI_RESP_FL: DPRINTF( DBG_OTHER_MEDIA, "ncsi Broadcast filter set.\n"); break; // generic response. done. case NCSI_SET_MAC_ADDRESS +NCSI_RESP_FL: DPRINTF( DBG_OTHER_MEDIA, "ncsi MAC address set.\n"); break; // generic response. done. case NCSI_CLEAR_INITIAL_STATE +NCSI_RESP_FL: if( NCSI_STATUS_COMPLETED == be16(resp->status) ){ NCSI_Channel[ resp->channel_id & 0x1F ] = resp->channel_id; }else{ DPUTHEX( DBG_OTHER_MEDIA, "ncsi cls: failed reset channel 0x", resp->channel_id, ".\n" ); } break; case NCSI_SELECT_PACKAGE +NCSI_RESP_FL: NCSI_Package[ resp->channel_id >> 5 ] = resp->channel_id >> 5; DPUTHEX( DBG_OTHER_MEDIA, "ncsi package/channel 0x", resp->channel_id, " selected. " ); DPUTHEX32( DBG_OTHER_MEDIA, " resp. code=0x", be16(resp->status), "\n" ); break; // NCSI_SELECT_PACKAGE case NCSI_DESELECT_PACKAGE +NCSI_RESP_FL: DPUTHEX( DBG_OTHER_MEDIA, "ncsi package/channel 0x", resp->channel_id, " deselected." ); DPUTHEX32( DBG_OTHER_MEDIA, " resp. code=0x", be16(resp->status), "\n" ); break; // NCSI_DESELECT_PACKAGE case NCSI_ENABLE_CHANNEL +NCSI_RESP_FL: if( NCSI_STATUS_COMPLETED == be16(resp->status) ){ DPUTHEX( DBG_OTHER_MEDIA, "ncsi channel 0x", resp->channel_id, " enabled.\n" ); }else{ DPUTHEX32( DBG_OTHER_MEDIA, "ncsi Enable Channel returned status: 0x", be16(resp->status), ".\n" ); } break; case NCSI_DISABLE_CHANNEL_TX +NCSI_RESP_FL: break; case NCSI_ENABLE_CHANNEL_TX +NCSI_RESP_FL: if( NCSI_STATUS_COMPLETED == be16(resp->status) ){ DPUTHEX( DBG_OTHER_MEDIA, "ncsi channel 0x", resp->channel_id, " TX enabled.\n" ); }else{ DPUTHEX32( DBG_OTHER_MEDIA, "ncsi Enable Channel returned status: 0x", be16(resp->status), ".\n" ); } break; case NCSI_GET_VERSION_ID +NCSI_RESP_FL: if(resp->status == NCSI_STATUS_COMPLETED){ NCSI_GET_VERSION_ID_RESP* vidp = (NCSI_GET_VERSION_ID_RESP*)&resp->status; // we just print this until any better use found. DPUTHEX32( DBG_OTHER_MEDIA, "ncsi version:", be32(vidp->ncsi_version), "" ); DPUTHEX32( DBG_OTHER_MEDIA, " FW version:", be32(vidp->firmware_version), "" ); DPUTHEX32( DBG_OTHER_MEDIA, " IANA:", be32(vidp->mfg_id), "\n" ); } break; // NCSI_GET_VERSION_ID case NCSI_GET_CAPABILITIES +NCSI_RESP_FL: if( NCSI_STATUS_COMPLETED == be16(resp->status) ){ NCSI_GET_CAPABILITIES_RESP* gcp = (NCSI_GET_CAPABILITIES_RESP*)&resp->status; DPUTHEX32( DBG_OTHER_MEDIA, "ncsi caps: flags=0x", be32(gcp->caps_flags), ""); DPUTHEX( DBG_OTHER_MEDIA, " BC filter=0x", be32(gcp->broadcast_filter_caps), ""); DPUTHEX32( DBG_OTHER_MEDIA, " buffering=0x", be32(gcp->buffering_caps), ""); DPUTHEX( DBG_OTHER_MEDIA, " chans=", gcp->channel_count, "\n"); } break; // NCSI_GET_CAPABILITIES case NCSI_GET_PARAMETERS +NCSI_RESP_FL: if(resp->status == NCSI_STATUS_COMPLETED){ NCSI_GET_PARAMETERS_RESP* gp = (NCSI_GET_PARAMETERS_RESP*)&resp->status; DPUTHEX( DBG_OTHER_MEDIA, "ncsi params: MAC count=", gp->mac_address_count, ""); DPUTHEX( DBG_OTHER_MEDIA, " flags=", gp->mac_address_flags, ""); DPUTHEX( DBG_OTHER_MEDIA, " BC filter=", be32(gp->broadcast_packet_filter_settings), ""); DPUTHEX( DBG_OTHER_MEDIA, " cfg flags=", be32(gp->configuration_flags), "\n"); DPUTHEX( DBG_OTHER_MEDIA, "MAC=", gp->mac_address_1[0], ""); DPUTHEX( DBG_OTHER_MEDIA, ":", gp->mac_address_1[1], ""); DPUTHEX( DBG_OTHER_MEDIA, ":", gp->mac_address_1[2], ""); DPUTHEX( DBG_OTHER_MEDIA, ":", gp->mac_address_1[3], ""); DPUTHEX( DBG_OTHER_MEDIA, ":", gp->mac_address_1[4], ""); DPUTHEX( DBG_OTHER_MEDIA, ":", gp->mac_address_1[5], ""); // "\n"); // status print out always follows this } break; // NCSI_GET_PARAMETERS case NCSI_GET_LINK_STATUS +NCSI_RESP_FL: if(resp->status == NCSI_STATUS_COMPLETED){ NCSI_GET_LINK_STATUS_RESP* lsp = (NCSI_GET_LINK_STATUS_RESP*)&resp->status; // we just print this until more use found. DPUTHEX32( DBG_OTHER_MEDIA," link stat: ", lsp->link_status, ".\n" ); } break; // NCSI_GET_LINK_STATUS case NCSI_GET_MC_PACKET_STATISTICS+NCSI_RESP_FL: if(resp->status == NCSI_STATUS_COMPLETED){ NCSI_GET_MC_PACKET_STATISTICS_RESP* msp = (NCSI_GET_MC_PACKET_STATISTICS_RESP*)&resp->status; DPUTHEX32( DBG_OTHER_MEDIA,"ncsi mc statistics: bytes Tx=", be32(msp->bytes_tx), "" ); DPUTHEX32( DBG_OTHER_MEDIA," Rx=", be32(msp->bytes_rx), ".\n" ); DPUTHEX32( DBG_OTHER_MEDIA,"Packets: uRx=",be32(msp->unicast_packets_rx),""); DPUTHEX32( DBG_OTHER_MEDIA," bRx=", be32(msp->broadcast_packets_rx), "" ); DPUTHEX32( DBG_OTHER_MEDIA," uTx=", be32(msp->unicast_packets_tx),""); DPUTHEX32( DBG_OTHER_MEDIA," bTx=", be32(msp->broadcast_packets_tx),".\n"); // . . . more information available in the reply . . . } break; // NCSI_GET_MC_PACKET_STATISTICS case NCSI_GET_NCSI_STATISTICS +NCSI_RESP_FL: if(resp->status == NCSI_STATUS_COMPLETED){ NCSI_GET_NCSI_STATISTICS_RESP* gns = (NCSI_GET_NCSI_STATISTICS_RESP*)&resp->status; DPUTHEX( DBG_OTHER_MEDIA, "ncsi statistics: cmd.Rx=", (UINT8)be32(gns->commands_received), ""); DPUTHEX( DBG_OTHER_MEDIA, " dropped=", be32(gns->command_packets_dropped), ""); DPUTHEX( DBG_OTHER_MEDIA, " errors=", be32(gns->command_checksum_errors), ""); DPUTHEX( DBG_OTHER_MEDIA, "+", be32(gns->command_type_errors), "\n"); // DPUTHEX32( DBG_OTHER_MEDIA," Rx=", be32(gns->rx_packets), ""); // DPUTHEX32( DBG_OTHER_MEDIA," Tx=", be32(gns->rx_packets), "\n"); } // else stat = resp->status; break; case NCSI_GET_NCSI_PT_STATISTICS+NCSI_RESP_FL: DPRINTF( DBG_OTHER_MEDIA, "ncsi get PT statistics (nyf)\n"); stat = CC_NOT_SUPPORTED; break; default: DPUTHEX( DBG_OTHER_MEDIA, "ncsi_data_input: unsupported reply cmd code 0x", resp->packet_type, " received.\n" ); stat = CC_NOT_SUPPORTED; break; } // case seq = resp->iid; // retry detector pbuf_free(p); return(stat); /* not finished implementation */ } // ncsi_data_input UINT8 ncsi_control(UINT8 ctl_code, UINT8* param) { const UINT8 ncsi_request_template[] = { //<----------- DA ----------> <-------------- SA ------------> <- NCSI-> 0xFF,0xFF, 0xFF,0xFF, 0xFF,0xFF, 0xFF,0xFF, 0xFF,0xFF, 0xFF,0xFF, 0x88,0xF8, //ID rev x IID PTyp ChID Payld_Length x x x x x x x x 0x00,0x01, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, // Payload : variable length -> <------ cks -----> 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00 /* Ethernet packet pad to 64B total ----------------------------*/ }; static UINT8 seq; static const UINT32 this_broadcast_filter = // (BF_ARP_PACKETS); (BF_ARP_PACKETS | BF_DHCP_CLIENT_PACKETS | BF_DHCP_SERVER_PACKETS); struct pbuf *p; int i; // UINT32 i, timer; NCSI_REQ* req; p = pbuf_alloc(PBUF_RAW, sizeof(ncsi_request_template), PBUF_RAM); if ( NULL == p ) { DPRINTF( DBG_WARN | DBG_OTHER_MEDIA, "LAN_send udp: couldn't allocate pbuf.\n\r" ); }else{ memcpy( (UINT8*)p->payload, ncsi_request_template, sizeof(ncsi_request_template) ); req = (NCSI_REQ*)p->payload; req->packet_type = ctl_code; req->payload_len = 0; req->iid = ++seq; // single package ID==0; channel is one-of-many req->channel_id = (NCSI_Package[0] << 5) | ncsi_channel_selected; switch(ctl_code){ case NCSI_SET_MAC_ADDRESS: // set the NC-SI MAC address #1 (we support just one) if(NULL == param){ pbuf_free(p); return (CC_NORMAL); // nothing to set: silently ignore the command } memcpy(&req->payload[0], ¶m[0], sizeof(struct eth_addr)); req->payload[sizeof(struct eth_addr)] = 1; /* MAC address #1 */ req->payload[sizeof(struct eth_addr)+1] = 1; /* enable this MAC */ req->payload_len = sizeof(struct eth_addr) +2; /* 1 byte "length" */ break; // NCSI_SET_MAC_ADDRESS case NCSI_SELECT_PACKAGE: // if(NULL != param){ // select package specified if not null. req->channel_id = *param; /* PKG ID + Int Ch ID */ } req->payload[0] = req->payload[1] = req->payload[2] = 0; req->payload[3] = NCSI_DISABLE_HW_ARBITRATION; req->payload_len = 4; break; // NCSI_SELECT_PACKAGE case NCSI_DESELECT_PACKAGE: if(NULL != param){ // deselect package specified if not null. req->channel_id = *param; /* PKG ID + Int Ch ID */ } break; // NCSI_DESELECT_PACKAGE case NCSI_CLEAR_INITIAL_STATE: if(NULL != param){ req->channel_id = *param; /* PKG ID + Int Ch ID */ } break; case NCSI_ENABLE_BROADCAST_FILTER: { NCSI_ENABLE_BROADCAST_FILTER_REQ* ebf_req; ebf_req = (NCSI_ENABLE_BROADCAST_FILTER_REQ*) &req->payload[0]; if(NULL != param){ // req->channel_id = *param; /* PKG ID + Int Ch ID */ } ebf_req->broadcast_filter = be32(this_broadcast_filter); req->payload_len = sizeof(NCSI_ENABLE_BROADCAST_FILTER_REQ);/* 1B len */ } break; // NCSI_ENABLE_BROADCAST_FILTER case NCSI_DISABLE_CHANNEL: if(NULL != param){ req->channel_id = *param; /* PKG ID + Int Ch ID */ } req->payload[0] = req->payload[1] = req->payload[2] = 0; req->payload[3] = NCSI_ALLOW_LINK_DOWN; req->payload_len = 4; break; case NCSI_ENABLE_CHANNEL: case NCSI_DISABLE_CHANNEL_TX: case NCSI_ENABLE_CHANNEL_TX: if(NULL != param){ req->channel_id = *param; /* PKG ID + Int Ch ID */ } break; case NCSI_GET_LINK_STATUS: break; /* cmd-code-only (generic req) */ case NCSI_GET_VERSION_ID: break; /* ... no payload commands */ case NCSI_GET_CAPABILITIES: break; /* ... */ case NCSI_GET_PARAMETERS: break; /* ... */ case NCSI_GET_MC_PACKET_STATISTICS: break; /* ... */ case NCSI_GET_NCSI_STATISTICS: break; /* ... */ case NCSI_GET_NCSI_PT_STATISTICS: break; /* --------------------------- */ default: pbuf_free(p); return (CC_INVALID_CMD); } for( i = 0; i < NCSI_RETRIES; i++ ){ IPMInetIF.linkoutput(&IPMInetIF, p); // timer = lbolt + NCSI_TIME_OUT; // while (lbolt < timer){ DelayMs(2); if(true == ipmnetif_input(&IPMInetIF)) break; // for (stop retries) } // for pbuf_free(p); } return(CC_NORMAL); } // ncsi_control /* ---------------------------------------------------------------------------- */ // ncsi_reset() :: DTMF 6.2.13.1 - non-hardware arbitration startup sequence. // * Discover NC-SI-attached packages and package channels; // * Read the NC-SI properties; // * Assign MAC address(es). // Commands used: // 1. Using the Select Package discover NCSI packages (cmd = 0x01) // 2. Using the Clear Initial State discover channels (cmd = 0x00) // 3. (option) Get ID and statistics (cmd = 0x15..0x1A) // 4. Set MAC (cmd = 0x0E) // 5. Set filter(s) (cmd = 0x10) // 6. Channel (Network pass-through Tx/Rx) Enable (cmd = 0x03, 0x06) void ncsi_reset() { UINT8 i, j, ID; for( i = 0; i <= NCSI_MAX_PACKAGE_ID; i++){ ID = i << 5 | NCSI_CHANNEL_ID_BROADCAST; ncsi_control(NCSI_SELECT_PACKAGE, &ID); ncsi_control(NCSI_DESELECT_PACKAGE, &ID); } for ( i = 0, j = 0; i <= NCSI_MAX_PACKAGE_ID; i++ ){ if(0xFF != NCSI_Package[i]) j++; } if( 0 != j ){ DPUTHEX( DBG_OTHER_MEDIA, "ncsi_reset : ", j, " packages found.\n" ); eth_link_on = 1; } else { DPRINTF( DBG_OTHER_MEDIA, "ncsi_reset : no packages.\n" ); eth_link_on = 0; return; } // we will use/support single package at this time! ID = (NCSI_Package[0] << 5) | NCSI_CHANNEL_ID_BROADCAST; ncsi_control(NCSI_SELECT_PACKAGE, &ID); ncsi_get_ncsi_statistics(); // reset counters // Note: ch=NCSI_MAX_CHANNEL_ID is a broadcast ID, we do not include it. for ( i = 0, ID = NCSI_Package[0]<<5; i < NCSI_MAX_CHANNEL_ID; i++ ){ ncsi_control(NCSI_CLEAR_INITIAL_STATE, &ID); ID += 1; // next channel } for ( i = 0, j = 0; i < NCSI_MAX_CHANNEL_ID; i++ ){ if(0xFF != NCSI_Channel[i]) j++; } DPUTHEX( DBG_OTHER_MEDIA, "ncsi_reset : ", j, " channels found.\n" ); // initialize first channel available, this is a default ncsi_control(NCSI_SET_MAC_ADDRESS, &IPMInetIF.hwaddr[0]); ncsi_control(NCSI_ENABLE_BROADCAST_FILTER, NULL); ID = (NCSI_Package[0]<<5) | ncsi_channel_selected; ncsi_control(NCSI_ENABLE_CHANNEL, &ID); ncsi_control(NCSI_ENABLE_CHANNEL_TX, &ID); } // ncsi_reset void ncsi_get_link_status_parameters() { if( CC_NORMAL != ncsi_control(NCSI_GET_PARAMETERS, NULL)) { // &NCSI_Package[0])){ DPRINTF( DBG_OTHER_MEDIA, "ncsi: failed to get parameters.\n" ); } if( CC_NORMAL != ncsi_control(NCSI_GET_LINK_STATUS, NULL)) { // &NCSI_Package[0])){ DPRINTF( DBG_OTHER_MEDIA, "ncsi_reset : failed to get link status.\n" ); } } // ncsi_get_link_status_parameters void ncsi_get_ncsi_statistics() { if( CC_NORMAL != ncsi_control(NCSI_GET_NCSI_STATISTICS, NULL)) { // &NCSI_Package[0])){ DPRINTF( DBG_OTHER_MEDIA, "ncsi: failed to get statistics.\n" ); } } // ncsi_get_ncsi_statistics void ncsi_get_capabilities() { if( CC_NORMAL != ncsi_control(NCSI_GET_CAPABILITIES, NULL)) { // &NCSI_Package[0])){ DPRINTF( DBG_OTHER_MEDIA, "ncsi: failed to get capabilities.\n" ); } } // ncsi_get_capabilities void ncsi_get_mc_statistics() { if( CC_NORMAL!=ncsi_control(NCSI_GET_MC_PACKET_STATISTICS, NULL)) { // &NCSI_Package[0])){ DPRINTF( DBG_OTHER_MEDIA,"ncsi: failed to get the MC statistics.\n"); } } // ncsi_get_mc_statistics UINT8 ncsi_remap_channel(UINT8 channel) { if ( ((channel & 0x1F) >= NCSI_MAX_CHANNEL_ID) || ( 0xFF == NCSI_Channel[channel&0x1F] )) return CC_PARAM_OUT_OF_RANGE; ncsi_control(NCSI_DISABLE_CHANNEL_TX,NULL); // disable last ("this") channel ncsi_control(NCSI_DISABLE_CHANNEL, NULL); // disable last ("this") channel ncsi_channel_selected = channel; // store globally new channel # ncsi_control(NCSI_SET_MAC_ADDRESS, &IPMInetIF.hwaddr[0]); ncsi_control(NCSI_ENABLE_BROADCAST_FILTER, NULL); ncsi_control(NCSI_ENABLE_CHANNEL, NULL); ncsi_control(NCSI_ENABLE_CHANNEL_TX, NULL); return (CC_NORMAL); } // ncsi_remap_channel #else #warning To use the NCSI please #define the LAN_USE_NCSI constant (preferrably @project level). #endif // LAN_USE_NCSI /* -------------------------------------------------------------------------- * * The End of lwip_ncsi_1768.c file. * * -------------------------------------------------------------------------- */