//************************************************************************ // // FILE : receive.uc // // AUTHOR : Jeremy Bryan // // CLASS : CS522 Semester Project // // DATE : 11/25/2000 // // DESCRIPTION : This file contains microcode that implements // the packet receive engine. // //************************************************************************ .xfer_order $xfer0 $xfer1 // // Check the context number. // // Run only one receive thread. If we are not running as context 0, // then permanently swap out. // br!=ctx[0, receive_done#] // // Initialize Constant Registers // // my_context - absolute context number of this thread used for RCV_REQ // data_addr - address of the data buffer in SDRAM // descriptor_addr - address of the packet descriptor in SRAM // current_port - MAC port number where packets will be received // packet_count - total number of packets received // immed[my_context, 0] immed[data_addr, 0x100] immed[descriptor_addr, 0x100] immed[current_port, 1] immed[packet_count, 0] // // Start of infinite loop // begin#: // // Read receive ready flags until our port has data // wait_for_ready#: csr[read, $xfer1, RCV_RDY_LO], ctx_swap alu[rx_ready, --, B, $xfer1] alu[--, rx_ready, AND, 0x02] br=0[wait_for_ready#] // // Write the receive request and swap out until the write is complete // // - Our Thread ID // - Port Number // - Receive FIFO Element Number // ;; ;; RCV_REQ format ;; ;; bits description ;; ;; 29 fetch 9 ;; 28:27 msg pkt ;; 26 stat ;; 25:22 elem #2 ;; 21:18 elem #1 ;; 17:16 sequence number ;; 15 1 or 2 ;; 14:12 misc ;; 11 sig sched ;; 10:06 thread ;; 05:00 port ;; alu[this_rr, --, B, my_context, <<6] alu[this_rr, this_rr, OR, current_port] alu[$xfer0, this_rr, OR, current_port, <<18] csr[write, $xfer0, rcv_req], ctx_swap // // Swap out and wait for a signal from the IX bus unit // that the packet data is in the receive FIFO element // ctx_arb[start_receive] // // Now the packet is in the receive FIFO element. // // Read the RCV_CNTL register to retreive the control data // csr[read, $xfer7, RCV_CNTL], ctx_swap alu[rcv_cmd, --, B, $xfer7] ;; ;; RCV_CNTL format ;; ;; bits description ;; ;; 31:30 msg ;; 29:24 port ;; 23:20 sequence number ;; 19 receive fail ;; 18 error ;; 17:14 element 2 ;; 13:10 element 1 ;; 9 1 or 2 ;; 8 seq ;; 7:2 valid bytes ;; 1 EOP ;; 0 SOP // // Move the packet from the FIFO element into SDRAM // ;; ;; Indirect specification for SDRAM[R_FIFO_RD] ;; ;; bits description ;; ;; 31 OV ;; 30:28 microengine address ;; 27:21 res ;; 20 OV ;; 19:16 Ref Cnt ;; 15:12 res ;; 11:4 quadword address ;; 3 res ;; 2 OV ;; 1:0 context number ;; write_sdram#: // // Take the element number from the RCV_CNTL register, // then multiply it by 8 (the number of quadwords per // element) to get the FIFO element. // alu[rfifo_entry, 0xf, AND, rcv_cmd, >>10] alu[rfifo_address, 0, B, rfifo_entry, <<3] alu[--, --, B, rfifo_address, <<4] sdram[r_fifo_rd, --, data_addr, 0, 8], indirect_ref, ctx_swap // // Write the packet descriptor to SRAM // // - Take quadword count, byte count, EOP, SOP, and port from RCV_CNTL // ;; ;; Descriptor format ;; ;; bits description ;; ;; 31 res ;; 15:13 number of quadwords ;; 12:10 number of bytes ;; 9 EOP ;; 8 SOP ;; 7 skip ;; 6:0 port ;; ld_field_w_clr[descriptor, 0010, rcv_cmd, <<8] alu[$descriptor, descriptor, +4, rcv_cmd, >>24] write_sram#: sram[write, $descriptor, descriptor_addr, 0, 1], ctx_swap // // Signal the transmit thread to process the packet // fast_wr[0x4, inter_thd_sig] // // Increment the packet count // alu[packet_count, packet_count, +, 1] status_written#: ctx_arb[inter_thread] br[begin#] // // Finished processing // // We should only get here if we are not context 0 // receive_done#: ctx_arb[kill]