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.


Fixed the bug that caused the first packet sent to always be malformed.
[palacios.git] / palacios / src / geekos / ne2k.c
index 1cc5457..8810895 100644 (file)
@@ -14,10 +14,13 @@ uint_t next = (RX_START_BUFF << 8);
 static uint_t received = 0;
 static uint_t send_done = 1;
 
+struct NE2K_REGS* regs;
+
 struct callback {
   int (*packet_received)(struct NE2K_Packet_Info *info, uchar_t *packet);
 } callbacks;
 
+#if DEBUG
 static void Dump_Registers()
 {
   uint_t data;
@@ -28,7 +31,8 @@ static void Dump_Registers()
     PrintBoth("\t%x: %x\n", NE2K_BASE_ADDR + i, data);
   }
 }
-
+#endif
+#if 0
 static int NE2K_Transmit(struct NE2K_REGS *regs)
 {
   while(!send_done);
@@ -89,7 +93,7 @@ static int NE2K_Transmit(struct NE2K_REGS *regs)
 
   return 0;
 }
-
+#endif
 static void NE2K_Interrupt_Handler(struct Interrupt_State * state)
 {
   Begin_IRQ(state);
@@ -101,14 +105,15 @@ static void NE2K_Interrupt_Handler(struct Interrupt_State * state)
   if(isr_content & 0x01) /* A packet has been received. */
   {
         uchar_t current;
-       do{
-         Out_Byte(NE2K_CR, 0x4a);      
-         current = In_Byte(NE2K_CURR);
-         Out_Byte(NE2K_CR, 0x0a);
-         NE2K_Receive();
-         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));
+       Out_Byte(NE2K_CR, 0x4a);        /* Page 1 */
+       current = In_Byte(NE2K_CURR);
+       Out_Byte(NE2K_CR, 0x0a);        /* Page 0 */
+        NE2K_Receive();
+
+        /* When CURR equals BNRY, all packets in the receive ring buffer have been read, and
+           the packet received bit in the interrupt status register can be cleared. */
+        if(current == In_Byte(NE2K_BNRY))
+          Out_Byte(NE2K_ISR, 0x01);
   }
 
   End_IRQ(state);
@@ -117,7 +122,8 @@ static void NE2K_Interrupt_Handler(struct Interrupt_State * state)
     send_done = 1;  
     Out_Byte(NE2K_ISR, 0x02);
   }
-  Out_Byte(NE2K_ISR, 0xff); /* Clear all interrupts. */
+
+  //Out_Byte(NE2K_ISR, 0xff); /* Clear all interrupts. */
 }
 
 int Init_Ne2k(int (*rcvd_fn)(struct NE2K_Packet_Info *info, uchar_t *packet))
@@ -127,7 +133,7 @@ int Init_Ne2k(int (*rcvd_fn)(struct NE2K_Packet_Info *info, uchar_t *packet))
   PrintBoth("Initializing network card...\n");
   Out_Byte(NE2K_CR+0x1f, In_Byte(NE2K_CR+0x1f));  /* Reset? */
 
-  struct NE2K_REGS* regs = Malloc(sizeof(struct NE2K_REGS));
+  regs = Malloc(sizeof(struct NE2K_REGS));
   struct _CR * cr = (struct _CR *)&(regs->cr);
   struct _RCR * rcr = (struct _RCR*)&(regs->rcr);
   struct _IMR * imr = (struct _IMR *)&(regs->imr);
@@ -210,29 +216,32 @@ int Init_Ne2k(int (*rcvd_fn)(struct NE2K_Packet_Info *info, uchar_t *packet))
   cr->sta = 0x1;  // toggle start bit
   cr->stp = 0x0;
   Out_Byte(NE2K_CR, regs->cr);
-  
+
+#if DEBUG
   Dump_Registers();
 
-  cr->ps = NE2K_PAGE1;
+  cr->ps = 0x01;
   Out_Byte(NE2K_CR, regs->cr);
   Dump_Registers();
 
-  cr->ps = NE2K_PAGE2;  
+  cr->ps = 0x02;
   Out_Byte(NE2K_CR, regs->cr);
   Dump_Registers();
 
-  cr->ps = NE2K_PAGE0;
+  cr->ps = 0x00;
   Out_Byte(NE2K_CR, regs->cr);
+#endif
 
   Install_IRQ(NE2K_IRQ, NE2K_Interrupt_Handler);
   Enable_IRQ(NE2K_IRQ);
-
+#if 0
   for(i = 0; i < 0; i++)
   {
     NE2K_Transmit(regs);
     PrintBoth("Transmitting a packet\n");
   }
-
+#endif
+/*
   uchar_t src_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x58 };
   uchar_t dest_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x56 };
 
@@ -243,18 +252,18 @@ int Init_Ne2k(int (*rcvd_fn)(struct NE2K_Packet_Info *info, uchar_t *packet))
   for(i = 0; i < 0; i++) {
     NE2K_Send(regs, src_addr, dest_addr, 0x01, data, size);
   }
-
+*/
   //Free(data);  // Why does this crash?
 
   return 0;
 }
 
 /* Assumes src and dest are arrays of 6 characters. */
-int NE2K_Send(struct NE2K_REGS *regs, uchar_t src[], uchar_t dest[], uint_t type, uchar_t *data, uint_t size)
+int NE2K_Send(uchar_t src[], uchar_t dest[], uint_t type, uchar_t *data, uint_t size)
 {
   struct _CR * cr = (struct _CR*)&(regs->cr);
   uint_t packet_size = size + 16;
-  regs->cr = 0x21;
+  regs->cr = 0x21; /* Turn off remote DMA, stop command */
   cr->stp = 0x0;  //toggle start on
   cr->sta = 0x1;
   Out_Byte(NE2K_CR, regs->cr);
@@ -282,7 +291,7 @@ int NE2K_Send(struct NE2K_REGS *regs, uchar_t src[], uchar_t dest[], uint_t type
   Out_Byte(NE2K_RSAR0, 0x00);
   Out_Byte(NE2K_RSAR1, TX_START_BUFF);
 
-  regs->cr = 0x16;
+  cr->rd = 0x02; /* Set remote DMA to write */
   Out_Byte(NE2K_CR, regs->cr);
 
   /* Destination Address */
@@ -303,6 +312,9 @@ int NE2K_Send(struct NE2K_REGS *regs, uchar_t src[], uchar_t dest[], uint_t type
     Out_Word(NE2K_CR + 0x10, (*(data + i + 1) << 8) | *(data + i));
   }
 
+  cr->txp = 0x1; /* Start transmission */
+  Out_Byte(NE2K_CR, regs->cr);
+
   return 0;
 }
 
@@ -346,7 +358,6 @@ 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);
     *(packet + i) = data & 0x00ff;
     *(packet + i + 1) = (data & 0xff00) >> 8;
 #if 0
@@ -355,9 +366,6 @@ int NE2K_Receive()
     PrintBoth("CURR = %x\n", In_Byte(NE2K_CURR));  
     Out_Byte(NE2K_CR, 0x0a);
 #endif
-
-    //if(!(i%10))
-      //PrintBoth("\n\t");
   }
 
 //Out_Byte(NE2K_RBCR0, (In_Byte(NE2K_RBCR0))-2);