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.


Initial working version of NE2K_Receive() added.
Matt Wojcik [Wed, 30 Jul 2008 16:58:22 +0000 (16:58 +0000)]
palacios/src/geekos/ne2k.c

index 5beb967..45fb49b 100644 (file)
@@ -4,92 +4,16 @@
 #include <geekos/irq.h>
 #include <geekos/malloc.h>
 
-static uint_t received = 0;
-
-struct _CR {  //COMMAND REG
-        uint_t stp: 1;  //STOP- software reset
-        uint_t sta: 1;  //START- activates NIC
-        uint_t txp: 1;  //TRANSMIT- set to send
-        uint_t rd:  3;  //REMOTE DMA
-        uint_t ps:  2;  //PAGE SELECT
-};
-
-struct _ISR{  //INTERRUPT STATUS REG
-        uint_t prx: 1;  //PACKET RECIEVED
-        uint_t ptx: 1;  //PACKET TRANSMITTED
-        uint_t rxe: 1;  //TRANSMIT ERROR
-        uint_t txe: 1;  //RECEIVE ERROR
-        uint_t ovw: 1;  //OVERWRITE WARNING
-        uint_t cnt: 1;  //COUNTER OVERFLOW
-        uint_t rdc: 1;  //REMOTE DMA COMPLETE
-        uint_t rst: 1;  //RESET STATUS
-};
-
-struct _IMR {  //INTERRUPT MASK REG
-        uint_t prxe: 1;  //PACKET RX INTRPT
-        uint_t ptxe: 1;  //PACKET TX INTRPT
-        uint_t rxee: 1;  //RX ERROR INTRPT
-        uint_t txee: 1;  //TX ERROR INTRPt
-        uint_t ovwe: 1;  //OVERWRITE WARNING INTRPT
-        uint_t cnte: 1;  //COUNTER OVERFLOW INTRPT
-        uint_t rdce: 1;  //DMA COMLETE INTRPT
-       uint_t rsvd: 1;
-};
-
-struct _DCR {  //DATA CONFIG REGISTER
-        uint_t wts: 1;  //WORD TRANSFER SELECT
-        uint_t bos: 1;  //BYTE ORDER SELECT
-        uint_t las: 1;  //LONG ADDR SELECT
-        uint_t ls:  1;  //LOOPBACK SELECT
-        uint_t arm: 1;  //AUTO-INITIALIZE REMOTE
-        uint_t ft:  2;  //FIFO THRESH SELECT
-};
-
-struct _TCR {  //TX CONFIG REGISTER
-        uint_t crc:  1;  //INHIBIT CRC
-        uint_t lb:   2;  //ENCODED LOOPBACK
-        uint_t atd:  1;  //AUTO TRANSMIT
-        uint_t ofst: 1;  //COLLISION OFFSET ENABLE
-       uint_t rsvd: 3;
-};
-
-struct _TSR {
-        uint_t ptx:  1;  //PACKET TX
-       uint_t rsvd: 1;
-        uint_t col:  1;  //TX COLLIDED
-        uint_t abt:  1;  //TX ABORTED
-        uint_t crs:  1;  //CARRIER SENSE LOST
-        uint_t fu:   1;  //FIFO UNDERRUN
-        uint_t cdh:  1;  //CD HEARTBEAT
-        uint_t owc:  1;  //OUT OF WINDOW COLLISION
-};
-
-struct _RCR {  //RECEIVE CONFIGURATION REGISTER
-        uint_t sep:  1;  //SAVE ERRORED PACKETS
-        uint_t ar:   1;  //ACCEPT RUNT PACKETS
-        uint_t ab:   1;  //ACCEPT BROADCAST
-        uint_t am:   1;  //ACCEPT MULTICAST
-        uint_t pro:  1;  //PROMISCUOUS PHYSICAL
-        uint_t mon:  1;  //MONITOR MODE
-       uint_t rsvd: 2;
-};  
-
-struct _RSR {  //RECEIVE STATUS REG
-        uint_t prx: 1;  //PACKET RX INTACT
-        uint_t crc: 1;  //CRC ERROR
-        uint_t fae: 1;  //FRAME ALIGNMENT ERROR
-        uint_t fo:  1;  //FIFO OVERRUN
-        uint_t mpa: 1;  //MISSED PACKET
-        uint_t phy: 1;  //PHYSICAL/MULTICAST ADDR
-        uint_t dis: 1;  //RX DISABLED
-        uint_t dfr: 1;  //DEFERRING
-};
+#define DEBUG 0
+#define RX_START_BUFF 0x4c
 
+static uint_t received = 0;
+static uint_t send_done = 1;
+uint_t next = (RX_START_BUFF<<8);
 
 static void Dump_Registers()
 {
   uint_t data;
-
   PrintBoth("Dumping NIC registers for page %x...\n", (In_Byte(NE2K_CR) & 0xc0) >> 6);
   uint_t i = 0;
   for(i = 0; i <= 0x0f; i += 0x01) {
@@ -102,70 +26,74 @@ static void NE2K_Interrupt_Handler(struct Interrupt_State * state)
 {
   Begin_IRQ(state);
   PrintBoth("NIC Interrupt Occured!\n");
-  uint_t isr_content = In_Byte(NE2K_ISR);
+  uchar_t isr_content = In_Byte(NE2K_ISR);
+  Out_Byte(NE2K_ISR, 0xff); /* Clear all interrupts */
+/*   if( !isr_content )
+       return;
+*/  
+
   PrintBoth("Contents of ISR: %x\n", isr_content);
-  if(In_Byte(NE2K_ISR) & 0x01)
+  if(isr_content & 0x01)
     NE2K_Receive();
 
-  Out_Byte(NE2K_ISR, 0xff);
   End_IRQ(state);
+  if(isr_content & 0x02)
+    send_done = 1;
 }
 
-
 int Init_Ne2k()
 {
-
-uint_t CR_START_VAL = 0x21;
-static const uint_t DCR_START_VAL = 0x49;
-static const uint_t ISR_START_VAL = 0xff;
-static const uint_t RCR_START_VAL = 0x20;
-static const uint_t TCR_START_VAL = 0x02;
-//static const uint_t IMR_START_VAL = 0x00;
-PrintBoth("location Startval first = %x\n", &CR_START_VAL);
-
   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));
+  struct _CR * cr = (struct _CR *)&(regs->cr);
+  struct _RCR * rcr = (struct _RCR*)&(regs->rcr);
+  struct _IMR * imr = (struct _IMR *)&(regs->imr);
+
+  regs->cr = 0x21;
+  regs->dcr = 0x49;
+  regs->isr = 0xff;
+  regs->rcr = 0x20;
+  regs->tcr = 0x02;
+
+  Out_Byte(NE2K_CR, regs->cr);
+  Out_Byte(NE2K_DCR, regs->dcr);
+  Out_Byte(NE2K_ISR, regs->isr);
+  Out_Byte(NE2K_RCR, regs->rcr);
+  Out_Byte(NE2K_TCR, regs->tcr);
+  Out_Byte(NE2K_IMR, regs->imr);
 
-  regs->cr = (struct _CR*)&CR_START_VAL;
-  regs->dcr = (struct _DCR*)&DCR_START_VAL;
-  regs->isr = (struct _ISR*)&ISR_START_VAL;
-  regs->rcr = (struct _RCR*)&RCR_START_VAL;
-  regs->tcr = (struct _TCR*)&TCR_START_VAL;
-
-  Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
-  Out_Byte(NE2K_DCR, *(uint_t *)regs->dcr);
-  Out_Byte(NE2K_ISR, *(uint_t *)regs->isr);
-  Out_Byte(NE2K_RCR, *(uint_t *)regs->rcr);
-  Out_Byte(NE2K_TCR, *(uint_t *)regs->tcr);
-  Out_Byte(NE2K_IMR, *(uint_t *)regs->imr);
   Out_Byte(NE2K_RBCR0, 0x00);
   Out_Byte(NE2K_RBCR1, 0x00);
   Out_Byte(NE2K_RSAR0, 0x00);
   Out_Byte(NE2K_RSAR1, 0x00);
 
   Out_Byte(NE2K_TPSR, 0x40);      // Set TPSR
-  Out_Byte(NE2K_PSTART, 0x42);    // Set PSTART
+  Out_Byte(NE2K_PSTART, RX_START_BUFF);    // Set PSTART
   Out_Byte(NE2K_BNRY, 0x59);      // Set BNRY
-  Out_Byte(NE2K_PSTOP, 0x60);     // Set PSTOP
+  Out_Byte(NE2K_PSTOP, 0x80);     // Set PSTOP
 
-  Out_Byte(NE2K_ISR, *(uint_t *)regs->isr);
+  cr->ps = 0x01;  //switch to reg page 1
+  Out_Byte(NE2K_CR, regs->cr);
+  Out_Byte(NE2K_CURR, RX_START_BUFF);
+  cr->ps = 0x00;
 
-  regs->imr->prxe = 0x1;
-  regs->imr->ptxe = 0x1;
-  regs->imr->rxee = 0x1;
-  regs->imr->txee = 0x1;
-  regs->imr->ovwe = 0x1;
-  regs->imr->cnte = 0x1;
-  Out_Byte(NE2K_IMR, *(uint_t *)regs->imr);
+  Out_Byte(NE2K_CR, regs->cr);
+  Out_Byte(NE2K_BNRY, RX_START_BUFF);
 
-  regs->cr->ps = 0x01;  //switch to reg page 1
-  Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
+  Out_Byte(NE2K_ISR, regs->isr);
 
-PrintBoth("Startval 2= %x\n", CR_START_VAL);
+  imr->prxe = 0x1;
+  imr->ptxe = 0x1;
+  imr->rxee = 0x1;
+  imr->txee = 0x1;
+  imr->ovwe = 0x1;
+  imr->cnte = 0x1;
+  Out_Byte(NE2K_IMR, regs->imr);
 
-PrintBoth("regs locat = %x\n", (uint_t *)regs->cr);
-PrintBoth("regs = %x\n", *(uint_t *)regs->cr);
+  cr->ps = 0x01;  //switch to reg page 1
+  Out_Byte(NE2K_CR, regs->cr);
 
   /* Set the physical address of the card to 52:54:00:12:34:58 */
   Out_Byte(NE2K_CR+0x01, 0x52);
@@ -175,62 +103,69 @@ PrintBoth("regs = %x\n", *(uint_t *)regs->cr);
   Out_Byte(NE2K_CR+0x05, 0x34);
   Out_Byte(NE2K_CR+0x06, 0x58);
 
+  /* Accept all multicast packets */
   uint_t i;
   for(i = 0x08; i <= 0x0f; i++) {
     Out_Byte(NE2K_CR+i, 0xff);
   }
 
-  *(uint_t *)regs->cr = 0x21;  //set CR to start value
-  Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
-
-PrintBoth("startval 3 = %x\n", CR_START_VAL); 
-PrintBoth("location Startval 2 = %x\n", &CR_START_VAL);
-PrintBoth("regs = %x\n", (uint_t *)regs->cr);
+  regs->cr = 0x21;  //set CR to start value
+  Out_Byte(NE2K_CR, regs->cr);
 
   regs->tcr = 0x00;
-  Out_Byte(NE2K_TCR, *(uint_t *)regs->tcr);
-
-  regs->rcr->sep = 0x1;
-  regs->rcr->ar = 0x1;
-  regs->rcr->ab = 0x1;
-  regs->rcr->am = 0x1;
-  regs->rcr->pro = 0x1; //promiscuous mode, accept all packets
-  regs->rcr->mon = 0x0;
-  Out_Byte(NE2K_RCR, *(uint_t *)regs->rcr);
-
-  regs->cr->sta = 0x1;  //toggle start bit
-  regs->cr->stp = 0x0;
-  Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
+  Out_Byte(NE2K_TCR, regs->tcr);
+
+  rcr->sep = 0x1;
+  rcr->ar = 0x1;
+  rcr->ab = 0x1;
+  rcr->am = 0x1;
+  rcr->pro = 0x1; // promiscuous mode, accept all packets
+  rcr->mon = 0x0;
+  Out_Byte(NE2K_RCR, regs->rcr);
+
+  cr->sta = 0x1;  // toggle start bit
+  cr->stp = 0x0;
+  Out_Byte(NE2K_CR, regs->cr);
   
   Dump_Registers();
 
-  Out_Byte(NE2K_CR, (*(uint_t *)regs->cr & 0x3f) | NE2K_PAGE1);
+  cr->ps = NE2K_PAGE1;
+  Out_Byte(NE2K_CR, regs->cr);
   Dump_Registers();
 
-  Out_Byte(NE2K_CR, (*(uint_t *)regs->cr & 0x3f) | NE2K_PAGE2);
+  cr->ps = NE2K_PAGE2;  
+  Out_Byte(NE2K_CR, regs->cr);
   Dump_Registers();
 
+  cr->ps = NE2K_PAGE0;
+  Out_Byte(NE2K_CR, regs->cr);
+
   // Reset?
-  Out_Byte(NE2K_CR+0x1f, In_Byte(NE2K_CR+0x1f));
+//  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 < 4; i++)
+/*
+  for(i = 0; i < 1; i++)
   {
     NE2K_Transmit(regs);
     PrintBoth("Transmitting a packet\n");
   }
-
+*/  
   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;
-  *(uint_t *)regs->cr = 0x21;
-  regs->cr->stp = 0x0;  //toggle start on
-  regs->cr->sta = 0x1;
-  Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
+  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);
@@ -238,11 +173,11 @@ int NE2K_Transmit(struct NE2K_REGS *regs)
   Out_Byte(NE2K_RSAR0, 0x42);
   Out_Byte(NE2K_RSAR1, 0x00);
 
-  regs->cr->rd = 0x01;  //set remote DMA to 'remote read'
-  Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
+  cr->rd = 0x01;  // set remote DMA to 'remote read'
+  Out_Byte(NE2K_CR, regs->cr);
 
-  *(uint_t*)regs->isr = 0x40;  //clear and set Remote DMA high
-  Out_Byte(NE2K_ISR, *(uint_t *)regs->isr);
+  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);
@@ -253,9 +188,9 @@ int NE2K_Transmit(struct NE2K_REGS *regs)
   Out_Byte(NE2K_RSAR0, 0x00);
   Out_Byte(NE2K_RSAR1, 0x40);
 
-  *(uint_t*)regs->cr = 0x16;
-  Out_Byte(NE2K_CR, *(uint_t *)regs->cr);
-  
+  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);
@@ -275,7 +210,8 @@ int NE2K_Transmit(struct NE2K_REGS *regs)
     Out_Word(NE2K_CR+0x10, (n<<8) | (n+1));
   }
 
-  Out_Byte(NE2K_ISR, 0x40);
+  //regs->isr = 0x40;
+  //Out_Byte(NE2K_ISR, regs->isr); /* Do we need this here? */
 
   return 0;
 }
@@ -290,30 +226,46 @@ int NE2K_Receive()
   Out_Byte(NE2K_RBCR0, packet_size);
   Out_Byte(NE2K_RBCR1, 0x00);
 //  Out_Byte(NE2K_RSAR0, 0x42);
-    Out_Byte(NE2K_RSAR0, 0x4c);
-  Out_Byte(NE2K_RSAR1, 0x00);
+  Out_Byte(NE2K_RSAR1, next >> 8);
+  Out_Byte(NE2K_RSAR0, next & 0xff);
   Out_Byte(NE2K_CR, 0x0a);
 
   uint_t i;
   uint_t data;
   PrintBoth("\nPacket data:\n\t");
 
-  for(i = 0; i < packet_size; i+=2) {
+  data = In_Word(NE2K_CR + 0x10);
+  PrintBoth("%x ", data);
+
+  /* The first byte is the page number where the next packet in the ring buffer is stored */
+  next = data & 0xff00;
+
+  for(i = 2; i < packet_size; i+=2) {
     data = In_Word(NE2K_CR + 0x10);
     PrintBoth("%x ", data);
+    
+#if DEBUG
+    PrintBoth("BNRY = %x\n", In_Byte(NE2K_BNRY));
+    Out_Byte(NE2K_CR, 0x4a);
+    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);
+//Out_Byte(NE2K_RSAR0, (In_Byte(NE2K_RSAR0))+2);
+
   PrintBoth("\n%d packets have been received", ++received);
   PrintBoth("\n\n");
 
   Out_Byte(NE2K_ISR, 0x40);
 
+  /* The BNRY register stores the location of the first packet that hasn't been read yet */
+  Out_Byte(NE2K_BNRY, next >> 8);
+
   return 0;
 }
 
-
-//int NE2K_Ringbuff_Overflow(){
-       
-