📄 rtk8019as.c
字号:
#endif ipres(); delay_uS( 500 ); // Wait 0.5ms // Assign ethernet address ethif = interface->state; *(ethif->ethaddr) = rtkEthernetAddress; } // Do I have an ethernet address? Complain if I don't macOr = 0; for (char i = 0; i < (char) sizeof interface->hwaddr; i++) { macOr |= interface->hwaddr[i]; } if (!macOr) { puts("No MAC address (ethernet address) found or given\n"); return; } // This device initialization is the same for all boards / modules. The only // thing that differs is the page addresses. // Stop nic, change to register page 1 oute( rtkWriteAddress, 0x60 ); // Write the ethernet address (six bytes) into the 8019as registers for( unsigned i = 0; i < sizeof interface->hwaddr; ++i ) oute( rtkWriteAddress+1+i, interface->hwaddr[i] ); // initialize MARx to 0 (ie: reject all multicast) for( unsigned i = 0; i < 8; ++i ) oute( rtkWriteAddress+8+i, 0 ); // Initialize the interface // Stop nic, abort remote dma, reset to register page 0 oute( rtkWriteAddress, 0x21 ); delay_uS( 1600 ); // Wait 1.6ms // Normal operation, initialize remote Dma, fifo threshhold 8 bytes oute( rtkWriteAddress+PD_DATACFG, 0x58 ); // Remote dma byte count = 0000h oute( rtkWriteAddress+PD_RMTBCNT0, 0 ); oute( rtkWriteAddress+PD_RMTBCNT1, 0 ); oute( rtkWriteAddress+PD_RMTSADR0, 0 ); // Remote dma start address = 4000h oute( rtkWriteAddress+PD_RMTSADR1, 0x40 ); oute( rtkWriteAddress+PD_RXCFG, 0x20 ); // Monitor mode oute( rtkWriteAddress+PD_TXCFG, 0x02 ); // Place NIC in loopback // Tx buffer < 4600h <= rx buffer oute( rtkWriteAddress+PD_PAGESTART, 0x46 ); oute( rtkWriteAddress+PD_BOUNDARY, 0x46 ); // Rx buffer < 8000h oute( rtkWriteAddress+PD_PAGESTOP, PD_PAGE_STOP ); // Clear all interrupt flags oute( rtkWriteAddress+PD_INTSTATUS, 0xFF ); // Disable interrupt generation //oute( rtkWriteAddress+PD_INTMASK, 0 ); oute( rtkWriteAddress+PD_TXPAGE, 0x40 ); // 4000h < tx buffer // Stop nic, change to register page 1 oute( rtkWriteAddress, 0x61 ); // Next place to rx a packet oute( rtkWriteAddress+PD_CURRENT, 0x46 ); // Start nic, abort remote dma oute( rtkWriteAddress, 0x22 ); // Change from loopback mode to normal op oute( rtkWriteAddress+PD_TXCFG, 0 ); oute( rtkWriteAddress+PD_RXCFG, 0x04 ); // Accept broadcast packets // Clear any pending interrupts oute( rtkWriteAddress+PD_INTSTATUS, 0xFF );#ifdef DEBUG { char eth[20]; printf("MAC address: %s\n", etherAddressToString(eth, interface->hwaddr)); printf("read: 0x%x write: 0x%x\n", rtkReadAddress, rtkWriteAddress); } printRealTekRegisters(); puts("leaving RTK8019as init\n");#endif}/** * Send a packet to the RTK8019as from a series of pbuf buffers. */int RealTekSendPacket(struct pbuf *p){ struct pbuf * q; unsigned int packetLength = p->tot_len; unsigned char padLength = 0; // Weakness: multiple threads could write at the same time ipset3(); writing = 1; ipres(); if (packetLength < 60) { padLength = 60 - packetLength; packetLength = 60; }#ifdef TX_DEBUG printf("<send: %d pad: %d\n", packetLength, padLength);#endif // Semaphore is necessary here or before we get here for lwIP cases. // Abort any dma currently active oute( rtkWriteAddress, 0x20 ); // Wait for completion transmitting prev packet - Bit 2 set if busy while( (char) ( ine( rtkReadAddress ) & (1 << 2) ) != 0 ); // Amount to send oute( rtkWriteAddress+PD_RMTBCNT0, packetLength ); oute( rtkWriteAddress+PD_RMTBCNT1, packetLength >> 8 ); // Address on NIC to store oute( rtkWriteAddress+PD_RMTSADR0, 0 ); oute( rtkWriteAddress+PD_RMTSADR1, 0x40 ); oute( rtkWriteAddress, 0x12 ); // Write command to start // Send the packet from the chain of buffers, one byte at a time for (q = p; q != NULL; q = q->next) { unsigned char *payload = q->payload; unsigned int i; unsigned char j; //for (int i = 0; i < q->len; i++) for (i = q->len; i; i--) { //oute(rtkWriteAddress + PD_IOPORT, payload[i]);#ifdef TX_DEBUG //printf("%02x", *payload);#endif oute(rtkWriteAddress + PD_IOPORT, *payload++); } // Write padding for undersized packets for (j = padLength; j; j--) { oute(rtkWriteAddress + PD_IOPORT, 0); } } // Wait for dma to complete - Bit 6 clear if busy while( (char) ( ine( rtkReadAddress+PD_INTSTATUS ) & (1 << 6) ) == 0 ); // Clear dma bit in register oute( rtkWriteAddress+PD_INTSTATUS, 0x40 ); // Addr in ring to transmit oute( rtkWriteAddress+PD_TXPAGE, 0x40 ); oute( rtkWriteAddress+PD_TXBCNT0, packetLength ); // Amount to send oute( rtkWriteAddress+PD_TXBCNT1, packetLength >> 8 ); // Start transmission (and shut off remote dma) oute( rtkWriteAddress, 0x26 );#ifdef LINK_STATS stats.link.xmit++;#endif /* LINK_STATS */ #ifdef TX_DEBUG //printf("done transmitting packet\n");#endif ipset3(); writing = 0; ipres(); return ERR_OK;}/** * Read a packet into a pbuf chain. */static struct pbuf * readPacket(void){ unsigned int packetLength; unsigned char PDHeader[18]; // Temp storage for DMA and Ethernet headers struct pbuf * p; struct pbuf * q; // Read header oute( rtkWriteAddress, 0x1A ); // Start dma next packet for( unsigned char i = 0; i < 18; i++ ) { PDHeader[i] = ine( PD_IOPORT+rtkReadAddress ); } // Check for a good packet - Bit 0 set checking all but bit 5 if( ( PDHeader[0] & 0xDF ) != 1 ) { char current; char boundary; boundary = ine( PD_BOUNDARY+rtkReadAddress ); if( boundary <= 0x45 || boundary > PD_PAGE_STOP) // Header bad, reset to 0x46 oute( rtkWriteAddress+PD_BOUNDARY, current = 0x46 ); else // Set boundary current = PD_PAGE_STOP+1; oute( rtkWriteAddress, 0x62 ); // Page 1 + abort dma oute( rtkWriteAddress+PD_CURRENT, current ); oute( rtkWriteAddress, 0x22 ); // Page 0 + abort dma return NULL; } // Check for IP or ARP exception if( PDHeader[16] != 8 || ( PDHeader[17] != 0 && PDHeader[17] != 6 ) ) { oute( rtkWriteAddress, 0x22 ); // Page 0 + abort dma oute( rtkWriteAddress+PD_BOUNDARY, PDHeader[1] ); // Delete packet return NULL; } // Store real length, set len to packet length - header packetLength = ((unsigned) PDHeader[2] | ( PDHeader[3] << 8 ));#ifdef RX_DEBUG //puts(">"); printf("packet length: %d\n", packetLength);#endif // Allocate the right amount for the packet from the memory pool p = pbuf_alloc(PBUF_LINK, packetLength, PBUF_POOL); if (p != NULL) { // This assumes a minimum pbuf size of 14 ... a good assumption memcpy(p->payload, PDHeader + 4, 14); // Iterate over the pbuf chain, reading the entire packet minus // the header into storage. for (q = p; q != NULL; q = q->next) { unsigned char * payload = q->payload; unsigned char * payload_end = payload + q->len; // First 14 bytes are already there, skip them if (q == p) { payload += 14; } // Fill this pbuf byte by byte in the chain. while (payload != payload_end) { *payload++ = ine(PD_IOPORT + rtkReadAddress); } }#ifdef LINK_STATS stats.link.recv++;#endif /* LINK_STATS */ } else { // Read remainder of packet and discard for(unsigned int i = packetLength - 14; i; --i) { ine(PD_IOPORT + rtkReadAddress); }#ifdef LINK_STATS stats.link.memerr++; stats.link.drop++;#endif /* LINK_STATS */ } return p; }/** * Read a packet, clearing overflows. */struct pbuf * RealTekRecvPacket(){ char current; char boundary; // Don't try to read if writing is in progress. ipset3(); if (writing) { ipres(); return NULL; } ipres();#ifdef RX_DEBUG //printf("*");#endif oute( rtkWriteAddress, 0x20 ); // Select page 0 if ( ( (char) ine( rtkReadAddress+PD_INTSTATUS ) & (char) (1 << 4) ) != 0 ) { pbuf_free(readPacket()); oute( rtkReadAddress+PD_INTSTATUS, 0x10 ); // Clear overflow return NULL; } oute( rtkWriteAddress, 0x62 ); // Page 1 + abort dma current = ine( rtkReadAddress+PD_CURRENT ); oute( rtkWriteAddress, 0x22 ); // Page 0 + abort dma boundary = ine( rtkReadAddress+PD_BOUNDARY ); // Check for no packet if (current == boundary) { //return E_Interface_NoPacket; return NULL; } return readPacket();}// Delay microseconds.// Uses the RTC clock - waiting for 488uS periods.void delay_uS( unsigned uS ){ unsigned base; if( uS == 0 ) return; outi( RTC0R, 0 ); // Latch clock // Count of clock to wait (wrap is ok here) base = ((ini( RTC1R ) << 8) | (unsigned) ini( RTC0R )) + ((uS + 487) / 488); do { outi( RTC0R, 0 ); } while( ((ini( RTC1R ) << 8) | (unsigned) ini( RTC0R )) < base );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -