\section{Network Adaptors}

% -----------------------------------------------------------------
\begin{slide}{}

   \subsection{Overview}

   Typically where data link functionality is implemented
   \begin{sitem}
      \item Framing
      \item Error Detection
      \item Media Access Control (MAC)
   \end{sitem}

   \pichere{adaptor_blk.eps,height=3in}

\end{slide}

% -----------------------------------------------------------------
\begin{slide}{}

   \subsection{Host Perspective}

   Control Status Register (CSR)
   \begin{sitem}
      \item Available at some memory address
      \item CPU can read and write
      \item CPU instructs Adaptor (e.g., transmit)
      \item Adaptor informs CPU (e.g., receive error)
   \end{sitem}

   \bigskip
   Example

   \begin{verbatim}
   LE_RINT  0x0400  Received packet Interrupt (RC)
   LE_TINT  0x0200  Transmitted packet Interrupt (RC)
   LE_IDON  0x0100  Initialization Done (RC)
   LE_IENA  0x0040  Interrupt Enable (RW)
   LE_INIT  0x0001  Initialize (RW1)
   \end{verbatim}
\end{slide}

% -----------------------------------------------------------------
\begin{slide}{}

   \subsection{Moving Frames Between Host and Adaptor}

   Direct Memory Access (DMA)

   \pichere{buf_desc.eps,height=2.5in}

   Programmed I/O (PIO)

   \pichere{pio.eps,height=2.5in}
\end{slide}

% -----------------------------------------------------------------
\begin{slide}{}

   \subsection{Device Driver}
 
   Interrupt Handler
   \begin{verbatim}
   interrupt_handler()
   {
       disable_interrupts();
       /* some error occurred */
       if (csr & LE_ERR) 
       {
           print_and_clear_error();
       }
       /* transmit interrupt */
       if (csr & LE_TINT) 
       {
           csr = LE_TINT | LE_INEA;
           semSignal(xmit_queue);
       }
       /* receive interrupt */
       if (csr & LE_RINT) 
       {
           receive_interrupt();
       }
       enable_interrupts();
       return(0);
   }
   \end{verbatim}
\end{slide}

% -----------------------------------------------------------------
\begin{slide}{}

   Transmit Routine:

   \begin{verbatim}
   transmit(Msg *msg)
   {
       char *src, *dst;
       Context c;
       int len;

       semWait(xmit_queue);
       semWait(mutex);
       disable_interrupts();
       dst = next_xmit_buf();
       msgWalkInit(&c, msg);
       while ((src = msgWalk(&c, &len)) != 0)
           copy_data_to_lance(src, dst, len);
       msgWalkDone(&c);
       enable_interrupts();
       semSignal(mutex);
       return;
   }
   \end{verbatim}
\end{slide}

% -----------------------------------------------------------------
\begin{slide}{}   

   Receive Interrupt Routine

   \begin{verbatim}
   receive_interrupt()
   {
      Msg  *msg,  *new_msg;
      char *buf;

      while (rdl = next_rcv_desc()) 
      {   
          /* create process to handle this message */
          msg = rdl->msg;
          process_create(ethDemux, msg);

          /* msg eventually freed in ethDemux */ 
          /* now allocate a replacement */
          buf = msgConstructAllocate(new_msg, MTU);
          rdl->msg = new_msg;
          rdl->buf = buf;
          install_rcv_desc(rdl);
      }
      return;
   }
   \end{verbatim}
\end{slide}
