#include <geekos/irq.h>
#include <geekos/malloc.h>
#include <geekos/string.h>
+#include <uip/uip.h>
+#include <uip/uip_arp.h>
#define DEBUG 1
#define TX_START_BUFF 0x40
}
}
#endif
-#if 0
-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;
-}
-#endif
static void NE2K_Interrupt_Handler(struct Interrupt_State * state)
{
Begin_IRQ(state);
return 0;
}
-/* Assumes src and dest are arrays of 6 characters. */
-int NE2K_Send(uchar_t *packet, uint_t size)
+/*
+ * This function is called when there is data in uip_buf that's ready to be sent.
+ * uip_arp_out() is used to translate the destination IP address to a MAC address.
+ * If the corresponding MAC address isn't in the cache, the packet is replaced with
+ * an ARP packet, which is sent out instead. The original packet will need to be
+ * retransmitted at some point in the future.
+ */
+int NE2K_Transmit(uint_t size)
+{
+ uip_arp_out();
+ uchar_t *data;
+ data = Malloc(size);
+
+ /* Based on example code from the uIP documentation... */
+ if(size <= UIP_LLH_LEN + UIP_TCPIP_HLEN) {
+ memcpy(data, &uip_buf[0], size);
+ } else {
+ memcpy(data, &uip_buf[0], UIP_LLH_LEN + UIP_TCPIP_HLEN);
+ memcpy(data + UIP_LLH_LEN + UIP_TCPIP_HLEN, uip_appdata, size - UIP_TCPIP_HLEN - UIP_LLH_LEN);
+ }
+
+ /* Manually copy in the source MAC address for now. */
+ uchar_t src_addr[6] = { 0x52, 0x54, 0x00, 0x12, 0x34, 0x58 };
+ memcpy(data + 6, src_addr, 6);
+ if(*(data+12) != 0x08 || *(data+13) != 0x06)
+ {
+ /* This is not an ARP packet. Fill in te size of the packet manually. */
+ *(data+12) = size & 0xff;
+ *(data+13) = (size >> 8) & 0xff;
+ }
+
+ NE2K_Send_Packet(data, size);
+ Free(data);
+ return 0;
+}
+
+int NE2K_Send_Packet(uchar_t *packet, uint_t size)
{
struct _CR * cr = (struct _CR*)&(regs->cr);
regs->cr = 0x21; /* Turn off remote DMA, stop command */
return 0;
}
-#if 0
+#if 1
/* Assumes src and dest are arrays of 6 characters. */
-int NE2K_Send2(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;