📄 packet.asm
字号:
ret;*************************************************************;Read Station Address PROM (SAPROM);get_board_data:; ISAOUT EN0_DCFG, #ENDCFG_FT10+ENDCFG_BMS+ENDCFG_WTS; ; fifo treshold, Normal operation,; ; word/byte transfer mode selection; mov R2,#HIGH(2*ETHER_ADDR_LEN) ; R2R3 Byte Count; mov R3,#LOW(2*ETHER_ADDR_LEN); MOV R4,#0 ; R4R5 Remote Start Address; MOV R5,#0; MOV R1,#my_ether ; R1 store pointer; MOV DPTR,#icall_saveskip; pointer to procedure BYTE(@R1) save/skip; sjmp DMARead;;*************************************************************network_init:.ifdef HW45.else LCALL Reset_ISA.endif ;lcall InitRTL8019 ;RETInitRTL8019: lcall ResetRTL8019; mov dptr,#flash_my_ether mov r0,#my_ether mov r1,#ETHER_ADDR_LEN; ENABLE_EE;initaddr: movx a,@dptr mov @r0,a inc dptr inc r0 djnz r1,initaddr; DISABLE_EE;;Set Remote byte count BEGINPORTDATA PORTDATA EN_CMD, EN_PAGE3+EN_NODMA ;Remote DMA PORTDATA EN3_9346CR, 0xC0 PORTDATA EN1_CONFIG3, 0x38 PORTDATA EN3_9346CR, 0 PORTDATA EN_CMD, EN_PAGE0+EN_NODMA ;Remote DMA PORTDATA EN0_RCNTHI,0 ;MSB Remote byte count reg PORTDATA EN0_RCNTLO,0 ;LSB Remote byte count reg PORTDATA EN0_RXCR, ENRXCR_MON ;RX configuration reg ;Monitor mode (no packets rcvd) PORTDATA EN0_TXCR, ENTXCR_LOOP ;TX configuration reg ;set internal loopback mode; ENDPORTDATA; lcall get_board_data; BEGINPORTDATA PORTDATA EN0_DCFG, ENDCFG_FT10+ENDCFG_BMS+ENDCFG_WTS ; fifo treshold, Normal operation, ; word/byte transfer mode selection PORTDATA EN_CMD, EN_PAGE0+EN_NODMA ;Remote DMA PORTDATA EN0_STARTPG, RX_START_PG ;Starting page of ring buffer ;First page of RX Ring PORTDATA EN0_BOUNDARY, RX_START_PG ;Boundary page of ring buffer PORTDATA EN0_STOPPG,NE_STOP_PG ;Ending page +1 of ring buffer ;End Page = Last page + 1 of RX Ring PORTDATA EN0_ISR, -1 ;Interrupt status reg PORTDATA EN0_IMR, 0 ;Interrupt mask reg = Disable All Interrupt PORTDATA EN_CMD, EN_PAGE1+EN_NODMA ;Page 1, Remote DMA PORTDATA EN1_PHYS+portind+0,my_ether+0;This board's physical enet addr PORTDATA EN1_PHYS+portind+1,my_ether+1 PORTDATA EN1_PHYS+portind+2,my_ether+2 PORTDATA EN1_PHYS+portind+3,my_ether+3 PORTDATA EN1_PHYS+portind+4,my_ether+4 PORTDATA EN1_PHYS+portind+5,my_ether+5 PORTDATA EN_CMD, EN_PAGE1+EN_NODMA+EN_STOP ;Page 1, ;Remote DMA, Stop and reset the chip PORTDATA EN1_MULT+0,0xFF ;Multicast filter mask array (8 bytes) PORTDATA EN1_MULT+1,0xFF PORTDATA EN1_MULT+2,0xFF PORTDATA EN1_MULT+3,0xFF PORTDATA EN1_MULT+4,0xFF PORTDATA EN1_MULT+5,0xFF PORTDATA EN1_MULT+6,0xFF PORTDATA EN1_MULT+7,0xFF PORTDATA EN_CMD, EN_PAGE0+EN_NODMA+EN_START ;Remote DMA, Start the chip, clear reset PORTDATA EN_CMD, EN_PAGE1+EN_NODMA+EN_STOP ;Page 1, ;Remote DMA, Stop and reset the chip PORTDATA EN1_CURPAG, RX_CURR_PG ;Current memory page = RX_CURR_PG PORTDATA EN_CMD, EN_PAGE0+EN_NODMA+EN_START ;Remote DMA, Start the chip, clear reset PORTDATA EN0_TXCR, 0 ;TX configuration reg = Normal Operation PORTDATA EN0_RXCR, ENRXCR_BCST ;RX configuration reg = ; Accept broadcasts PORTDATA EN0_ISR, -1 ;Clear the pending Interrupt /* sichr */ ENDPORTDATA; MOV next_packet,#RX_CURR_PG; JNB flagRxEnable,NoRxEnable; ISAOUT EN0_RXCR, #ENRXCR_BCST ;RX configuration reg =; ; Accept broadcasts;NoRxEnable:; ISAOUT EN0_ISR, #-1 ;Clear the pending Interrupt /* sichr */ RET;*************************************************************;;Wait a full Tx time (1.2 ms) + some guard time, NS says 1.6 ms total.plongpause:longpause: PUSH ACC PUSH DPL PUSH DPH MOV DPTR,#-(CPUFRQ/450)longpause_l: INC DPTR ;2 MOV A,DPL ;1 ORL A,DPH ;1 JNZ longpause_l ;2 POP DPH POP DPL POP ACC RET;*************************************************************ReadPacketHeader: mov R2,#HIGH(SIZE_OF_8019_HDR+SIZE_OF_ETH_PKT_HDR) mov R3,#LOW(SIZE_OF_8019_HDR+SIZE_OF_ETH_PKT_HDR) ;R2R3 Byte Count; MOV R4,#0 ;R4R5 Remote Start Address MOV R5,#0 MOV R1,#rcv_hdr ;R1 store pointer MOV DPTR,#icall_save;pointer to procedure BYTE(@R1) save ljmp DMARead;*************************************************************rcv_pkt: clr rx_eth_bit jbc eth_state1, rcv_ovr_ok jbc eth_state2, _eth2state ISAIN EN0_ISR ; Get pending interrupts JNZ ISRtestOverrun RET ; Ret if none_eth2state: ljmp eth2stateISRtestOverrun: ; Was there an overrun ? JB BITISR_OVER,recv_overrun ; Go if so ljmp recv_no_overrun ; Go if not;*************************;*** RxOverrun ***;*************************recv_overrun: ISAIN EN_CMD ; read Chip's command register PUSH Acc ; and save it;; Stop the NIC ISAOUT EN_CMD, #EN_PAGE0+EN_NODMA+EN_STOP ; Remote DMA, Stop and reset the chip;; Wait 1.6ms for the NIC to stop transmitting or receiving a packet. National;; says monitoring the ISR RST bit is not reliable, so a wait of the maximum;; packet time (1.2ms) plus some padding is required. lcall longpause;; Reset RBCR[01] back to zero as per magic incantation. BEGINPORTDATA PORTDATA EN0_RCNTHI,0 ; MSB Remote byte count reg PORTDATA EN0_RCNTLO,0 ; LSB Remote byte count reg ENDPORTDATA;; check the saved state of the EN_TRANS bit in the command register CLR flagResend POP Acc ; pop Chip's command register JNB BIT_TRANS,rcv_ovr_loopback;; Transmitter was running, see if it finished or died ISAIN EN0_ISR ; Get pending interrupts ANL A,#ENISR_TX_ERR+ENISR_TX ; Did the transmitter finish? JNZ rcv_ovr_loopback ; one will be set if TX finished; Transmitter did not complete, remember to resend the packet later. CLR flagResendrcv_ovr_loopback:;; Have to enter loopback mode and then restart the NIC before you are;; allowed to slurp packets up off the ring BEGINPORTDATA PORTDATA EN0_TXCR,ENTXCR_LOOP ; set internal loopback mode PORTDATA EN_CMD, EN_PAGE0+EN_NODMA+EN_START ; Start the chip running again;; Verify that there is really a packet to receive by fetching the current;; page pointer and comparing it to the next packet pointer. PORTDATA EN_CMD, EN_PAGE1+EN_NODMA ; Set Page 1 ENDPORTDATA ISAIN EN1_CURPAG ; Current memory page;; ISAOUTA EN1_CURPAG ; Rewrite Current memory page to fix SMC bug MOV R4,A ISAOUT EN_CMD, #EN_PAGE0+EN_NODMA ; Page 1, Remote DMA MOV A,next_packet XRL A,R4 ; Check if buffer empty JNZ rcv_ovr_rx_one ; O.K. get the NIC header; NO PACKET IN THE RING AFTER AN OVW INTERRUPT??? Can this ever happen?; YES! if overrun happend between a receive interrupt and the when the; current page register is read at the start of recv_frame. sjmp rcv_ovr_empty ; Current Page == next_packetrcv_ovr_rx_one:; MOV R5,#0 ; R4R5 Remote Start Address Register .using 0 PUSH AR4 lcall ReadPacketHeader POP AR4 MOV A,rcv_hdr ; Get the buffer status byte ;Received a good packet ? JNB BITRSR_RXOK, rcv_ovr_ng ; No, received debris; EVEN if the NIC header status is OK, I have seen garbaged NIC headers, so; it doesn't hurt to range check the next packet pointer here. MOV A,rcv_hdr_nxt_pg ; pointer to next packet CJNE A,#RX_START_PG,.+3 ;; First page of RX Ring JC rcv_ovr_ng ;; < RX_START_PG ;;invalid pointer, Bellow around the bottom CJNE A,#NE_STOP_PG,.+3;;Last page + 1 of RX Ring JNC rcv_ovr_ng ;; >= NE_STOP_PG ;;invalid pointer, Above the top MOV next_packet,A ;save pointer to next packet MOV curr_recv,R4 ;save pointer to current packet setb rx_eth_bit setb eth_state1 ret;; LCALL ProcessEthPacket;; SJMP rcv_ovr_okrcv_ovr_ng:;; HAD TO ADD ERROR RECOVERY HERE. TO BLINDLY PROCEED AND ASSUME THE NEXT; PACKET POINTR FROM THE NIC HEADER IS VALID IS INVITING DISASTER.;; Error recovery consists of killing and restarting the NIC. This drops all; the packets in the ring, but thats better than winding up in the weeds!;; Instead copy the last known current page pointer into the next packet pointer; which will result in skipping all the packets from the errored one to where; the NIC was storing them when we entered this ISR, but prevents us from; trying to follow totally bogus next packet pointers through the card RAM; space. MOV A,R4 ; Current memory page ;;MOV next_packet,A sjmp recv_frame_break1 ;save next_packet...rcv_ovr_ok:rcv_ovr_empty: MOV A,next_packet ; Grap the next packet pointer DEC A ; Back up one page CJNE A,#RX_START_PG,.+3 ;; Did it wrap? JNC BoundaryOK ; >= RX_START_PG MOV A,#NE_STOP_PG-1 ;; Yes, back to end of ringBoundaryOK: ISAOUTA EN0_BOUNDARY ;Boundary Register BEGINPORTDATA; Clear the OVW bit in the ISR register. PORTDATA EN0_ISR, ENISR_OVER ;Interrupt status reg ;Receiver overwrote the ring; Take the NIC out of loopback PORTDATA EN0_TXCR, 0 ;Normal Operation ENDPORTDATA; Any incomplete transmission to resend? JNB flagResend,recv_frame_break ;No; Yes, restart the transmission ISAOUT EN_CMD, EN_TRANS+EN_NODMA+EN_START ;Start the transmitter sjmp recv_frame_breakrecv_no_overrun: JNB BITISR_COUNTERS, NoReadTallyCounters;*************************;*** ReadTallyCounters ***;************************* PUSH Acc MOV ADDRPORT,#EN0_COUNTER0+I2CBUS ;CNTR0..2;CNTR0 Frame Alignment Error Tally Counter Register;CNTR1 CRC Error Tally Counter Register;CNTR2 Missed Packet Tally Counter Register ISAREAD INC ADDRPORT ISAREAD INC ADDRPORT ISAREAD ISAOUT EN0_ISR, #ENISR_COUNTERS ;Interrupt status reg ;ReSet CNT (Error Tally Counters) POP AccNoReadTallyCounters: JB BITISR_RX, PacketReceivedOK JB BITISR_RX_ERR, PacketReceived sjmp recv_frame_breakPacketReceived:PacketReceivedOK: ISAOUT EN0_ISR, #ENISR_RX_ERR + ENISR_RX ; Clear those request;; Get the rx page (incoming packet pointer) ISAOUT EN_CMD, #EN_PAGE1+EN_NODMA+EN_START ; Switch to page 1 registers ISAIN EN1_CURPAG ; Get current page of rcv ring MOV curpage, A ; ans save it ISAOUT EN_CMD, #EN_PAGE0+EN_NODMA+EN_START ; Back to page 0 registers; This becomes the loop back point to read packets from the ring.; now only loop back and read until those packets received at the time; the current page register is read above have been read.recv_frame:;; Read all the frames ?? MOV R4,next_packet .using 0 CJNE A,AR4,recv_more_frames ; compare with saved ; current page of rcv ring SJMP recv_frame_break;; Remove one frame from the ring. Boundary is always a page behind.recv_more_frames: MOV curr_recv,R4; MOV R5,#0 ; R4R5 Remote Start Address Register lcall ReadPacketHeader MOV A,rcv_hdr ; Get the buffer status byte XRL A,#ENRSR_RXOK ; Good packet ? JZ GoodPacket XRL A,#((ENRSR_PHY + ENRSR_RXOK) ^ ENRSR_RXOK) ;Received broadcast/multicast JNZ InvalidNextFramePtrGoodPacket:; EVEN if the NIC header status is OK, I have seen garbaged NIC headers, so; it doesn't hurt to range check the next packet pointer here. MOV A,rcv_hdr_nxt_pg; get pointer to next packet MOV next_packet,A ; and save it CJNE A,#RX_START_PG,.+3 ;; First page of RX Ring JC InvalidNextFramePtr ; < RX_START_PG CJNE A,#NE_STOP_PG,.+3 ;; Last page + 1 of RX Ring JC ProcessFrame ; next_packet < NE_STOP_PG;InvalidNextFramePtr: MOV A, curpage ; Get current page of rcv ringrecv_frame_break1: MOV next_packet,Arecv_frame_break: ISAOUT EN0_ISR, #ENISR_RDC ;Interrupt status reg ;remote dma complete RETProcessFrame: setb rx_eth_bit setb eth_state2;; LCALL ProcessEthPacket reteth2state: MOV R4,next_packet DEC R4 CJNE R4,#RX_START_PG,.+3 ;;First page of RX Ring JNC SetBoundaryNxt ; >= RX_START_PG MOV R4,#NE_STOP_PG-1;;Last page + 1 of RX RingSetBoundaryNxt: ISAOUT EN0_BOUNDARY,R4 ; Boundary page of ring buffer MOV A, curpage ; Get current page of rcv ring SJMP recv_frame;*************************************************************;send_port: PUSH ACC MOV A,R0 PUSH ACC MOV R0,SP PUSH DPL PUSH DPH DEC R0 DEC R0 MOV DPH,@R0 ;get string address DEC R0 ;from stack MOV DPL,@R0Sport0: CLR A MOVC A,@A+DPTR ;get port address CJNE A,#endport,Sport1 ;print it INC DPTR ;end of string MOV @R0,DPL ;change return address on stack INC R0 MOV @R0,DPH POP DPH ;restore DPH POP DPL ;restore DPL POP ACC MOV R0,A POP ACC RET;Sport1: MOV C,Acc.5 ORL A,#I2CBUS MOV ADDRPORT,A INC DPTR CLR A MOVC A,@A+DPTR ;get port data JNC NoSpInd .using 0 PUSH AR0 MOV R0,A MOV A,@R0 POP AR0NoSpInd:.ifdef MOVXMODE MOVX @R0,A.else MOV P0,A CLR P3.6 NOP SETB P3.6.endif INC DPTR SJMP Sport0 .section reset_network, #alloc LCALL network_init ;; END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -