//************************************************************************ // // FILE : transmit.uc // // AUTHOR : Jeremy Bryan // // CLASS : CS522 Semester Project // // DATE : 11/25/2000 // // DESCRIPTION : This file contains microcode that implements // the packet transmit engine. // //************************************************************************ .xfer_order $xfer0 $xfer1 $xfer2 $xfer3 .operand_synonym $status_word0 $xfer2 // // Check the context number. // // Run only one receive thread. If we are not running as context 0, // then permanently swap out. // br!=ctx[0, transmit_done#] // // Initialize Constant Registers // // data_addr - address of the data buffer in SDRAM // descriptor_addr - address of packet descriptor in SRAM // const_128 - constant value // tx_ready - local copy of transmit ready flags // tx_outptr - local copy of transmit pointer // current_ptr - number of the next T_FIFO element to use // immed[data_addr, 0x100] immed[descriptor_addr, 0x100] immed[const_128, 128] immed[tx_ready, 0] immed[tx_outptr, 0] immed[current_inptr, 0] immed[$xfer3, 0] // // Start of transmit loop // transmit_loop#: // // Wait for a signal from the receive thread that a packet // is in the buffer and ready to be transmitted // ctx_arb[inter_thread] // // Read the packet descriptor from SRAM // get_descriptor#: sram[read, $descriptor, descriptor_addr, 0, 1], ctx_swap ;; ;; 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 ;; // // Before transmitting, we must check the availability of both // the MAC port and next transmit FIFO element. // got_transmit_ready#: // // Use the port number to test the transmit ready flags. // If the port is not ready, re-read the ready flags and ptr. // alu[port, 0x1f, AND, $descriptor] alu[temp, --, B, tx_ready] alu[--, port, B, 0] alu[--, 1, AND, temp, >>indirect] br=0[get_transmit_ready#] // // Now check to see if the transmit FIFO element we plan to use // is ready to be transmitted by the transmit state machine. // got_fifo_ready#: // // It is ready if the state machine's transmit pointer // is equal to our pointer. This means that the state machine // is waiting to transmit our target FIFO element. // If the element is not ready, re-read the ready flags and ptr. // alu[--, tx_outptr, -, current_inptr] br!=0[get_transmit_ready#] transfer_data#: // // Set up an indirect register to put the number of quadwords // alu[qw_count, 0x7, AND, $descriptor, >>13] alu[qw_count, 1, OR, qw_count, <<16] // // Set up another indirect register to put our (T_FIFO pointer * 8) // alu[elem_addr, 0, B, current_inptr, <<3] // // Form the indirect reference word by shifting the element address // to its appropiate position and combining it with the quadword count. // alu[--, qw_count, OR, elem_addr, <<4] sdram[t_fifo_wr, --, data_addr, 0, 8], indirect_ref, ctx_swap // // Write the control word to the T_FIFO element. // The descriptor definition matches that of the control // word so it is written to the control word as is. // // Calculate the address of the T_FIFO control word. The // address is the input pointer multiplied by 2 (the length // of control and prepend fields) plus 128 (offset into // T_FIFO to start of control/prepend fields) // write_control#: alu[$status_word0, --, B, $descriptor] alu[status_tfifo_addr, const_128, +, current_inptr, <<1] t_fifo_wr[$status_word0, status_tfifo_addr, 0, 1], ctx_swap // // Validate the T_FIFO entry. // // First place the T_FIFO element number into the indirect // specification. Then issue a fast write to validate the // T_FIFO element. This tells the IX bus interface unit // to transmit the packet data to the MAC // status_sent#: alu[--, 1, OR, current_inptr, <<5] fast_wr[0, XMIT_VALIDATE], indirect_ref // // Issue an inter_thread signal to the receive thread // fast_wr[0x0, inter_thd_sig] // // Increment our FIFO pointer for the next time around. // // Roll the pointer over if it has reached 16 // incr_inptr#: alu[tempa, 1, +4, current_inptr] alu[tempa, tempa, AND, 0x0f] alu[current_inptr, --, B, tempa] br[transmit_loop#] // // The following code is treated as a subroutine. // // It reads the transmit ready flags and transmit pointer // from the transmit state machine and copies these values // to local GPRs. // get_transmit_ready#: csr[read, $xfer0, XMIT_PTR] csr[read, $xfer1, XMIT_RDY_LO], ctx_swap alu[tx_outptr, --, B, $xfer0] alu[tx_ready, --, B, $xfer1] br[got_transmit_ready#] // // Finished processing packets // // We should only get here if we are not context 0 // transmit_done#: ctx_arb[kill]