summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--driver/e1000.c97
-rw-r--r--driver/e1000.h2
-rw-r--r--driver/keyboard.c14
-rw-r--r--kernel/interrupts.c1
4 files changed, 67 insertions, 47 deletions
diff --git a/driver/e1000.c b/driver/e1000.c
index 21d3924..8233993 100644
--- a/driver/e1000.c
+++ b/driver/e1000.c
@@ -14,6 +14,7 @@
// I have gathered those from different Hobby online operating systems instead of getting them one by one from the manual
#define REG_CTRL 0x0000
+#define REG_ICR 0x00C0 // interrupt cause register
#define REG_STATUS 0x0008
#define REG_EEPROM 0x0014
#define REG_CTRL_EXT 0x0018
@@ -269,49 +270,56 @@ void rxinit()
rx_cur = 0;
//enable receiving
- uint32_t flags = (2 << 16) | (1 << 25) | (1 << 26) | (1 << 15) | (1 << 5) | (0 << 8) | (0 << 4) | (0 << 3) | ( 1 << 2);
- writeCommand(REG_RCTRL, flags);
- //writeCommand(REG_RCTRL, RCTL_EN| RCTL_SBP| RCTL_UPE | RCTL_MPE | RCTL_LBM_NONE | RTCL_RDMTS_HALF | RCTL_BAM | RCTL_SECRC | RCTL_BSIZE_2048);
+ //uint32_t flags = (2 << 16) | (1 << 25) | (1 << 26) | (1 << 15) | (1 << 5) | (0 << 8) | (0 << 4) | (0 << 3) | ( 1 << 2);
+ //writeCommand(REG_RCTRL, flags);
+ writeCommand(REG_RCTRL, RCTL_EN| RCTL_SBP| RCTL_UPE | RCTL_MPE | RCTL_LBM_NONE | RTCL_RDMTS_HALF | RCTL_BAM | RCTL_SECRC | RCTL_BSIZE_2048);
}
void txinit()
{
uint8_t * ptr;
- struct e1000_tx_desc *descs;
// Allocate buffer for receive descriptors. For simplicity, in my case khmalloc returns a virtual address that is identical to it physical mapped address.
// In your case you should handle virtual and physical addresses as the addresses passed to the NIC should be physical ones
- //
+
uint32_t alloc_pages=1+(sizeof(struct e1000_tx_desc)*E1000_NUM_TX_DESC + 16)/4096;
ptr = kballoc(alloc_pages);
- descs = (struct e1000_tx_desc *)ptr;
+ struct e1000_tx_desc *descs=ptr;
for(int i = 0; i < E1000_NUM_TX_DESC; i++)
{
- tx_descs[i] = (struct e1000_tx_desc *)((uint8_t*)descs + i*16);
+ tx_descs[i] = descs++;
tx_descs[i]->addr = 0;
tx_descs[i]->cmd = 0;
tx_descs[i]->status = TSTA_DD;
}
- writeCommand(REG_TXDESCHI, (uint32_t)(0) );
- writeCommand(REG_TXDESCLO, (uint32_t)(ptr));
+ writeCommand(REG_TXDESCLO, ptr); //physical here
+ writeCommand(REG_TXDESCHI, 0);
//now setup total length of descriptors
- writeCommand(REG_TXDESCLEN, E1000_NUM_TX_DESC * 16);
+ writeCommand(REG_TXDESCLEN, E1000_NUM_TX_DESC * 16); //
//setup numbers
writeCommand( REG_TXDESCHEAD, 0);
writeCommand( REG_TXDESCTAIL, 0);
tx_cur = 0;
+
+
writeCommand(REG_TCTRL, TCTL_EN
| TCTL_PSP
| (15 << TCTL_CT_SHIFT)
| (64 << TCTL_COLD_SHIFT)
| TCTL_RTLC);
-
+/*
+ writeCommand(REG_TCTRL,
+ 1<<0 // enable transmitter
+ |1<<3 // pad short packets
+// ,64<<12 // collision distance
+ );
+ */
// This line of code overrides the one before it but I left both to
// highlight that the previous one works with e1000 cards, but for the
// e1000e cards you should set the TCTRL register as follows. For detailed
@@ -319,8 +327,8 @@ void txinit()
// of I217 and 82577LM packets will not be sent if the TCTRL is not
// configured using the following bits.
- // writeCommand(REG_TCTRL, 0b0110000000000111111000011111010);
- // writeCommand(REG_TIPG, 0x0060200A);
+ //writeCommand(REG_TCTRL, 0b0110000000000111111000011111010);
+ //writeCommand(REG_TIPG, 0x0060200A);
}
@@ -347,23 +355,29 @@ void e1000_handleReceive()
int e1000_sendPacket(const void * p_data, uint16_t p_len)
{
- tx_descs[tx_cur]->addr = p_data;
- tx_descs[tx_cur]->length = p_len;
- tx_descs[tx_cur]->cmd = CMD_EOP | CMD_IFCS | CMD_RS | CMD_RPS;
+ tx_descs[tx_cur]->addr = p_data; // physical addy of data
+ tx_descs[tx_cur]->length = p_len; // length in bytes
+ //tx_descs[tx_cur]->cmd = CMD_EOP | CMD_IFCS | CMD_RS | CMD_RPS;
+ tx_descs[tx_cur]->cmd = ((1<<3)|3);
tx_descs[tx_cur]->status = 0;
+
uint8_t old_cur = tx_cur;
tx_cur = (tx_cur + 1) % E1000_NUM_TX_DESC;
writeCommand(REG_TXDESCTAIL, tx_cur);
while(!(tx_descs[old_cur]->status & 0xff));
+ klog("SENT FIRST PACKET WOOOOW");
return 0;
}
void enableInterrupt()
{
- writeCommand(REG_IMASK ,0x1F6DC);
- writeCommand(REG_IMASK ,0xff & ~4);
- readCommand(0xc0);
+// uint32_t status = readCommand(REG_ICR); // check interrupt cause register.
+// klog("status before enabling e1000 interrupts=%d",status);
+
+// writeCommand(REG_IMASK ,0x1F6DC);
+// writeCommand(REG_IMASK ,0xff & ~4);
+ writeCommand(REG_IMASK,0xffffffff);
}
void e1000_linkup()
@@ -373,25 +387,34 @@ void e1000_linkup()
writeCommand(REG_CTRL, val | ECTRL_SLU);
}
+void e1000_linkdown()
+{
+ uint32_t val;
+ val = readCommand(REG_CTRL);
+ writeCommand(REG_CTRL, val | ~ECTRL_SLU);
+}
+
bool e1000_init(uint32_t base)
{
klog("init E1000");
- if(base!=0) mem_base=base;
+ if(base!=0){ mem_base=base; return true;}
+
detectEEProm();
if (! readMACAddress()) return false;
klog("mac : %02x:%02x:%02x:%02x:%02x:%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],mac[6]);
- e1000_linkup();
+// e1000_linkup();
for(int i = 0; i < 0x80; i++)writeCommand(0x5200 + i*4, 0);
enableInterrupt();
- rxinit();
txinit();
-
+ rxinit();
+
+
klog("E1000 initialized");
return true;
@@ -405,25 +428,15 @@ void e1000_irq (int irq)
Without this, the card will spam interrupts as the int-line will
stay high. */
- writeCommand(REG_IMASK, 0x1);
- enableInterrupt();
-
- uint32_t status = readCommand(0xc0);
+ //writeCommand(REG_IMASK, 0x1);
+ //enableInterrupt();
+ int status =0;
+// uint32_t status = readCommand(REG_ICR); // check interrupt cause register.
klog("e1000_irq status=%d",status);
- if(status & 0x04)
- {
- e1000_linkup();
-// startLink();
- }
- else if(status & 0x10)
- {
- // good threshold
- }
- else if(status & 0x80)
- {
- e1000_handleReceive();
- }
-
- //}
+ if(status & 0x1) klog ("transmit descriptor written back");
+ if(status & 0x2) klog ("transmit queue empty");
+ if(status & 0x4) klog ("link status change");
+ if(status & 0x8) klog ("receive sequence error");
+ //...
}
diff --git a/driver/e1000.h b/driver/e1000.h
index 8534b6d..ba7db7d 100644
--- a/driver/e1000.h
+++ b/driver/e1000.h
@@ -2,3 +2,5 @@
bool e1000_init(uint32_t base);
int e1000_sendPacket(const void * p_data, uint16_t p_len);
void e1000_irq (int irq);
+void e1000_linkup();
+void e1000_linkdown();
diff --git a/driver/keyboard.c b/driver/keyboard.c
index 2352532..90a18c9 100644
--- a/driver/keyboard.c
+++ b/driver/keyboard.c
@@ -18,11 +18,17 @@ static void put(uint8_t c)
{
uint16_t dat[]={
0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x52,0x5,0x50a,0x00,0x02,0x02,0x08,0x06,0x00,
- 0x01,0x08,0x00,0x06,0x04,0x00,0x01,0x52,0x5,0x50a,0x00,0x02,0x02,0x0a,0x00,0x02};
+ 0x01,0x08,0x00,0x06,0x04,0x00,0x01,0x52,0x5,0x50a,0x00,0x02,0x02,0x0a,0x00,0x02,
+ 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x52,0x5,0x50a,0x00,0x02,0x02,0x08,0x06,0x00,
+ 0x01,0x08,0x00,0x06,0x04,0x00,0x01,0x52,0x5,0x50a,0x00,0x02,0x02,0x0a,0x00,0x02
+ };
+
+ if(c=='p')e1000_sendPacket(dat,64); // packet
+ if(c=='s')e1000_init(0); // start
+ if(c=='i')e1000_irq(11); // interrupt
+ if(c=='u')e1000_linkup(); // up
+ if(c=='d')e1000_linkdown(); // down
- if(c=='y')e1000_sendPacket(dat,32);
- if(c=='x')e1000_init(0);
- if(c=='i')e1000_irq(11);
syscall_generic(SYSCALL_WRITE,kb_stream, (char *)&c , 1, 0);
}
diff --git a/kernel/interrupts.c b/kernel/interrupts.c
index 10537f7..4d3a2c4 100644
--- a/kernel/interrupts.c
+++ b/kernel/interrupts.c
@@ -79,7 +79,6 @@ uint32_t interrupt_handler(uint32_t esp, uint32_t irq)
break;
case INTERRUPT_E1000:
- klog("e1");
e1000_irq(INTERRUPT_E1000);
break;