Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Added callbacks to allow functios at a higher level to receive packets.
Matt Wojcik [Mon, 4 Aug 2008 21:42:31 +0000 (21:42 +0000)]
palacios/src/geekos/ne2k.c

index 93a7f01..1cc5457 100644 (file)
@@ -3,16 +3,21 @@
 #include <geekos/io.h>
 #include <geekos/irq.h>
 #include <geekos/malloc.h>
+#include <geekos/string.h>
 
 #define DEBUG 1
-#define TX_START_BUFF 0x40
-#define RX_START_BUFF 0x4c
-
+#define TX_START_BUFF  0x40
+#define RX_START_BUFF  0x4c
+#define RX_END_BUFF    0x80
 
 uint_t next = (RX_START_BUFF << 8);
 static uint_t received = 0;
 static uint_t send_done = 1;
 
+struct callback {
+  int (*packet_received)(struct NE2K_Packet_Info *info, uchar_t *packet);
+} callbacks;
+
 static void Dump_Registers()
 {
   uint_t data;
@@ -24,17 +29,77 @@ static void Dump_Registers()
   }
 }
 
+static int NE2K_Transmit(struct NE2K_REGS *regs)
+{
+  while(!send_done);
+  send_done = 0;
+
+  struct _CR * cr = (struct _CR*)&(regs->cr);
+  uint_t packet_size = 80;
+  regs->cr = 0x21;
+  cr->stp = 0x0;  //toggle start on
+  cr->sta = 0x1;
+  Out_Byte(NE2K_CR, regs->cr);
+  
+  // Read-before-write bug fix?
+  Out_Byte(NE2K_RBCR0, 0x42);
+  Out_Byte(NE2K_RBCR1, 0x00);
+  Out_Byte(NE2K_RSAR0, 0x42);
+  Out_Byte(NE2K_RSAR1, 0x00);
+
+  cr->rd = 0x01;  // set remote DMA to 'remote read'
+  Out_Byte(NE2K_CR, regs->cr);
+
+  regs->isr = 0x40;  // clear and set Remote DMA high
+  Out_Byte(NE2K_ISR, regs->isr);
+  
+  Out_Byte(NE2K_RBCR0, packet_size);
+  Out_Byte(NE2K_RBCR1, 0x00);
+
+  Out_Byte(NE2K_TBCR0, packet_size);
+  Out_Byte(NE2K_TBCR1, 0x00);
+
+  Out_Byte(NE2K_RSAR0, 0x00);
+  Out_Byte(NE2K_RSAR1, 0x40);
+
+  regs->cr = 0x16;
+  Out_Byte(NE2K_CR, regs->cr);
+
+  /* Begin pushing the packet into the dataport (located at 0x10 from the base address) */
+  /* Destination address = 52:54:00:12:34:56 */
+  Out_Word(NE2K_CR+0x10, 0x5452);
+  Out_Word(NE2K_CR+0x10, 0x1200);
+  Out_Word(NE2K_CR+0x10, 0x5634);
+
+  /* Source address = 52:54:00:12:34:58 */
+  Out_Word(NE2K_CR+0x10, 0x5452);
+  Out_Word(NE2K_CR+0x10, 0x1200);
+  Out_Word(NE2K_CR+0x10, 0x5834);
+
+  /* Type length and data; currently random data */
+  uint_t i;
+  uint_t n = 0;
+  for(i = 1; i <= packet_size/2-12; i++, n+=2) {
+    //Out_Word(NE2K_CR+0x10, 0x0f0b);
+    Out_Word(NE2K_CR+0x10, (n<<8) | (n+1));
+  }
+
+  //regs->isr = 0x40;
+  //Out_Byte(NE2K_ISR, regs->isr); /* Do we need this here? */
+
+  return 0;
+}
+
 static void NE2K_Interrupt_Handler(struct Interrupt_State * state)
 {
   Begin_IRQ(state);
   PrintBoth("NIC Interrupt Occured!\n");
   uchar_t isr_content = In_Byte(NE2K_ISR);
- // Out_Byte(NE2K_ISR, 0xff); /* Clear all interrupts */
 
   PrintBoth("Contents of ISR: %x\n", isr_content);
 
   if(isr_content & 0x01) /* A packet has been received. */
-  { 
+  {
         uchar_t current;
        do{
          Out_Byte(NE2K_CR, 0x4a);      
@@ -44,7 +109,7 @@ static void NE2K_Interrupt_Handler(struct Interrupt_State * state)
          Out_Byte(NE2K_ISR, 0x01);
         /* If BNRY and CURR aren't equal, more than one packet has been received. */
        }while (current > In_Byte(NE2K_BNRY));
-   }
+  }
 
   End_IRQ(state);
   if(isr_content & 0x02) /* A packet has been successfully transmitted. */
@@ -55,8 +120,10 @@ static void NE2K_Interrupt_Handler(struct Interrupt_State * state)
   Out_Byte(NE2K_ISR, 0xff); /* Clear all interrupts. */
 }
 
-int Init_Ne2k()
+int Init_Ne2k(int (*rcvd_fn)(struct NE2K_Packet_Info *info, uchar_t *packet))
 {
+  callbacks.packet_received = rcvd_fn;
+
   PrintBoth("Initializing network card...\n");
   Out_Byte(NE2K_CR+0x1f, In_Byte(NE2K_CR+0x1f));  /* Reset? */
 
@@ -85,20 +152,18 @@ int Init_Ne2k()
   Out_Byte(NE2K_RSAR0, 0x00);
   Out_Byte(NE2K_RSAR1, 0x00);
 
-  Out_Byte(NE2K_TPSR, TX_START_BUFF);      /* Transmit page start register */
-  Out_Byte(NE2K_PSTART, RX_START_BUFF);    /* Page start register */
-//  Out_Byte(NE2K_BNRY, 0x59);      /* Boundary register */
-  Out_Byte(NE2K_PSTOP, 0x80);     /* Page stop register */
+  Out_Byte(NE2K_TPSR, TX_START_BUFF);          /* Transmit page start register */
+  Out_Byte(NE2K_PSTART, RX_START_BUFF);                /* Page start register */
+  Out_Byte(NE2K_PSTOP, RX_END_BUFF);                   /* Page stop register */
+  Out_Byte(NE2K_BNRY, RX_START_BUFF);          /* Boundary register */ 
 
-  cr->ps = 0x01;  /* Switch to reg page 1. */
+  cr->ps = 0x01; /* Switch to reg page 1. */
   Out_Byte(NE2K_CR, regs->cr);
   /* Current page register: points to first free page that can be used for packet reception. */
   Out_Byte(NE2K_CURR, RX_START_BUFF);
   cr->ps = 0x00; /* Switch to page 0 */
 
   Out_Byte(NE2K_CR, regs->cr);
-  Out_Byte(NE2K_BNRY, RX_START_BUFF); 
-
   Out_Byte(NE2K_ISR, regs->isr);
 
   /* Interrupt mask register: setting a bit to 1 enables the
@@ -122,7 +187,7 @@ int Init_Ne2k()
   Out_Byte(NE2K_CR+0x05, 0x34);
   Out_Byte(NE2K_CR+0x06, 0x58);
 
-  /* Set the multicast address registr to all 1s; accepts all multicast packets */
+  /* Set the multicast address register to all 1s; accepts all multicast packets */
   uint_t i;
   for(i = 0x08; i <= 0x0f; i++) {
     Out_Byte(NE2K_CR+i, 0xff);
@@ -159,18 +224,14 @@ int Init_Ne2k()
   cr->ps = NE2K_PAGE0;
   Out_Byte(NE2K_CR, regs->cr);
 
-  // Reset?
-//  Out_Byte(NE2K_CR+0x1f, In_Byte(NE2K_CR+0x1f));
-
   Install_IRQ(NE2K_IRQ, NE2K_Interrupt_Handler);
   Enable_IRQ(NE2K_IRQ);
-/*
-  for(i = 0; i < 2; i++)
+
+  for(i = 0; i < 0; i++)
   {
     NE2K_Transmit(regs);
     PrintBoth("Transmitting a packet\n");
   }
-*/
 
   uchar_t src_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x58 };
   uchar_t dest_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x56 };
@@ -179,11 +240,11 @@ int Init_Ne2k()
   uchar_t *data = Malloc(size);
   data = "This is a 64-byte string that will be used to test transmission.";
 
-  for(i = 0; i < 4; i++) {
+  for(i = 0; i < 0; i++) {
     NE2K_Send(regs, src_addr, dest_addr, 0x01, data, size);
   }
 
-  Free(data);
+  //Free(data);  // Why does this crash?
 
   return 0;
 }
@@ -245,83 +306,18 @@ int NE2K_Send(struct NE2K_REGS *regs, uchar_t src[], uchar_t dest[], uint_t type
   return 0;
 }
 
-int NE2K_Transmit(struct NE2K_REGS *regs)
-{
-  while(!send_done);
-  send_done = 0;
-
-  struct _CR * cr = (struct _CR*)&(regs->cr);
-  uint_t packet_size = 80;
-  regs->cr = 0x21;
-  cr->stp = 0x0;  //toggle start on
-  cr->sta = 0x1;
-  Out_Byte(NE2K_CR, regs->cr);
-  
-  // Read-before-write bug fix?
-  Out_Byte(NE2K_RBCR0, 0x42);
-  Out_Byte(NE2K_RBCR1, 0x00);
-  Out_Byte(NE2K_RSAR0, 0x42);
-  Out_Byte(NE2K_RSAR1, 0x00);
-
-  cr->rd = 0x01;  // set remote DMA to 'remote read'
-  Out_Byte(NE2K_CR, regs->cr);
-
-  regs->isr = 0x40;  // clear and set Remote DMA high
-  Out_Byte(NE2K_ISR, regs->isr);
-  
-  Out_Byte(NE2K_RBCR0, packet_size);
-  Out_Byte(NE2K_RBCR1, 0x00);
-
-  Out_Byte(NE2K_TBCR0, packet_size);
-  Out_Byte(NE2K_TBCR1, 0x00);
-
-  Out_Byte(NE2K_RSAR0, 0x00);
-  Out_Byte(NE2K_RSAR1, 0x40);
-
-  regs->cr = 0x16;
-  Out_Byte(NE2K_CR, regs->cr);
-
-  /* Begin pushing the packet into the dataport (located at 0x10 from the base address) */
-  /* Destination address = 52:54:00:12:34:56 */
-  Out_Word(NE2K_CR+0x10, 0x5452);
-  Out_Word(NE2K_CR+0x10, 0x1200);
-  Out_Word(NE2K_CR+0x10, 0x5634);
-
-  /* Source address = 52:54:00:12:34:58 */
-  Out_Word(NE2K_CR+0x10, 0x5452);
-  Out_Word(NE2K_CR+0x10, 0x1200);
-  Out_Word(NE2K_CR+0x10, 0x5834);
-
-  /* Type length and data; currently random data */
-  uint_t i;
-  uint_t n = 0;
-  for(i = 1; i <= packet_size/2-12; i++, n+=2) {
-    //Out_Word(NE2K_CR+0x10, 0x0f0b);
-    Out_Word(NE2K_CR+0x10, (n<<8) | (n+1));
-  }
-
-  //regs->isr = 0x40;
-  //Out_Byte(NE2K_ISR, regs->isr); /* Do we need this here? */
-
-  return 0;
-}
-
 int NE2K_Receive()
 {
   PrintBoth("Packet Received\n");
 
   Out_Byte(NE2K_CR, 0x22);
-
-  Out_Byte(NE2K_RBCR1, 0x00); 
-//  Out_Byte(NE2K_RBCR0, 0x60);
-  
-//  Out_Byte(NE2K_RSAR0, 0x42);
-  Out_Byte(NE2K_RSAR1, next >> 8);
+  /* Set RSAR to the start address of the received packet. */
   Out_Byte(NE2K_RSAR0, next & 0xff);
+  Out_Byte(NE2K_RSAR1, next >> 8);
   Out_Byte(NE2K_CR, 0x0a);
 
   /* 
-   * A four byte header is added to the beginning of each received packet.
+   * A four byte header is added to the beginning of each received packet by the NIC.
    * The first byte is the location of the next packet in the ring buffer.
    * The second byte is the receive status code.
    * The third and fourth bytes are the size of the packet.
@@ -337,7 +333,9 @@ int NE2K_Receive()
   /* Get the location of the next packet */
   next = data & 0xff00;
 
+  /* Retrieve the packet size from the header, and store it in RBCR. */
   uint_t packet_size =  In_Word(NE2K_CR + 0x10) - 4;
+  uchar_t *packet = Malloc(packet_size);
   Out_Byte(NE2K_RBCR0, packet_size & 0xff);
   Out_Byte(NE2K_RBCR1, (packet_size>>8) & 0xff);
 
@@ -348,8 +346,9 @@ int NE2K_Receive()
   /* Copy the received packet over from the ring buffer. */
   for(i = 0; i < packet_size; i+=2) {
     data = In_Word(NE2K_CR + 0x10);
-    PrintBoth("%x ", data);
-    
+    //PrintBoth("%x ", data);
+    *(packet + i) = data & 0x00ff;
+    *(packet + i + 1) = (data & 0xff00) >> 8;
 #if 0
     PrintBoth("BNRY = %x\n", In_Byte(NE2K_BNRY));
     Out_Byte(NE2K_CR, 0x4a);
@@ -357,8 +356,8 @@ int NE2K_Receive()
     Out_Byte(NE2K_CR, 0x0a);
 #endif
 
-    if(!(i%10))
-      PrintBoth("\n\t");
+    //if(!(i%10))
+      //PrintBoth("\n\t");
   }
 
 //Out_Byte(NE2K_RBCR0, (In_Byte(NE2K_RBCR0))-2);
@@ -367,11 +366,18 @@ int NE2K_Receive()
   PrintBoth("\n%d packets have been received", ++received);
   PrintBoth("\n\n");
 
-  Out_Byte(NE2K_ISR, 0x40);
+  Out_Byte(NE2K_ISR, 0x40); /* Clear the remote DMA complete interrupt. */
 
   /* The BNRY register stores the location of the first packet that hasn't been read yet */
   Out_Byte(NE2K_BNRY, next >> 8);
 
+  struct NE2K_Packet_Info *info = Malloc(sizeof(struct NE2K_Packet_Info));
+  info->size = packet_size;
+  info->status = 0;
+  memcpy(info->dest, packet, 6);
+  memcpy(info->src, packet + 6, 6);
+  callbacks.packet_received(info, packet);
+
   return 0;
 }