Plumbing for raw packet reading

This commit is contained in:
Ali Mashtizadeh 2015-01-27 10:34:44 -08:00
parent d005029577
commit 8f24dbe6d0
6 changed files with 124 additions and 5 deletions

View File

@ -10,6 +10,7 @@
#define ENOENT 0xBAD6
#define ENOTDIR 0xBAD7
#define ENAMETOOLONG 0xBAD8
#define ENOSYS 0xBAD9
#endif /* __ERRNO_H__ */

View File

@ -4,6 +4,7 @@
#include <sys/stat.h>
#include <sys/nic.h>
#include <sys/mbuf.h>
uint64_t OSTime();
uint64_t OSGetPID();
@ -35,6 +36,8 @@ int OSThreadWait(uint64_t tid);
// Network
int OSNICStat(uint64_t nicNo, NIC *nic);
int OSNICSend(uint64_t nicNo, MBuf *mbuf);
int OSNICRecv(uint64_t nicNo, MBuf *mbuf);
#endif /* __SYSCALL_H__ */

View File

@ -127,3 +127,15 @@ OSNICStat(uint64_t nicNo, NIC *nic)
return syscall(SYSCALL_NICSTAT, nicNo, nic);
}
int
OSNICSend(uint64_t nicNo, MBuf *mbuf)
{
return syscall(SYSCALL_NICSEND, nicNo, mbuf);
}
int
OSNICRecv(uint64_t nicNo, MBuf *mbuf)
{
return syscall(SYSCALL_NICRECV, nicNo, mbuf);
}

View File

@ -6,6 +6,7 @@
#include <sys/kassert.h>
#include <sys/kdebug.h>
#include <sys/kmem.h>
#include <sys/semaphore.h>
#include <sys/pci.h>
#include <sys/irq.h>
#include <sys/mbuf.h>
@ -97,6 +98,9 @@ typedef struct PACKED E1000RXDesc {
#define RDESC_STATUS_EOP (1 << 1)
#define RDESC_STATUS_DD (1 << 0)
#define RDESC_ERROR_RDE (1 << 7) /* Receive Data Error */
#define RDESC_ERROR_CE (1 << 0) /* CRC Error */
typedef struct PACKED E1000TXDesc {
volatile uint64_t addr; // Address
volatile uint16_t len; // Length
@ -112,14 +116,16 @@ typedef struct PACKED E1000TXDesc {
*/
typedef struct E1000Dev {
NIC nic; // Must be first
PCIDevice dev;
NIC nic;
IRQHandler irqHandle;
uint8_t *mmiobase;
E1000RXDesc *rxDesc;
E1000TXDesc *txDesc;
uint32_t rxTail;
uint32_t txTail;
Spinlock lock;
Semaphore ioSema;
} E1000Dev;
#define E1000_TX_QLEN 128
@ -226,20 +232,32 @@ E1000_RXPoll(E1000Dev *dev)
// Look for packet fragments up to EOP set in status
if ((dev->rxDesc[dev->rxTail].status & RDESC_STATUS_EOP) &&
(dev->rxDesc[dev->rxTail].errors == 0)) {
Debug_PrintHex(data, len, 0, len);
// Process packet
/*
* XXX: Need to create a queue and copyout packets here, because
* I'm seeing multiple interrupts.
*
* kprintf("E1000: Int\n");
*/
Semaphore_Release(&dev->ioSema);
}
if (dev->rxDesc[dev->rxTail].errors) {
kprintf("E1000: Error in RX Queue %x\n",
dev->rxDesc[dev->rxTail].errors);
dev->rxDesc[dev->rxTail].status = 0;
dev->rxDesc[dev->rxTail].errors = 0;
MMIO_Write32(dev, E1000_REG_RDT, dev->rxTail);
dev->rxTail = (dev->rxTail + 1) % E1000_RX_QLEN;
}
/*
dev->rxDesc[dev->rxTail].status = 0;
dev->rxDesc[dev->rxTail].errors = 0;
// XXX: Should write this only once
MMIO_Write32(dev, E1000_REG_RDT, dev->rxTail);
dev->rxTail = (dev->rxTail + 1) % E1000_RX_QLEN;
*/
}
}
@ -289,12 +307,53 @@ E1000_Interrupt(void *arg)
/*
* Read packets from NIC
*/
//E1000_Dequeue(SGArray *sga)
int
E1000_Dequeue(NIC *nic, MBuf *mbuf, NICCB cb, void *arg)
{
E1000Dev *dev = (E1000Dev *)nic;
retry:
Semaphore_Acquire(&dev->ioSema);
Spinlock_Lock(&dev->lock);
if ((dev->rxDesc[dev->rxTail].status & RDESC_STATUS_EOP) &&
(dev->rxDesc[dev->rxTail].errors == 0)) {
void *data = (void *)DMPA2VA(dev->rxDesc[dev->rxTail].addr);
uint16_t len = dev->rxDesc[dev->rxTail].len;
//Debug_PrintHex(data, len, 0, len);
// Use CB instead
memcpy(mbuf->vaddr, data, len);
dev->rxDesc[dev->rxTail].status = 0;
dev->rxDesc[dev->rxTail].errors = 0;
// XXX: Should write this only once
MMIO_Write32(dev, E1000_REG_RDT, dev->rxTail);
dev->rxTail = (dev->rxTail + 1) % E1000_RX_QLEN;
} else {
/*
* XXX: Need to remove this once I do the copyout inside the interrupt
* handler.
*/
/*kprintf("Packet not ready %d %x %x\n",
dev->rxTail,
dev->rxDesc[dev->rxTail].status,
dev->rxDesc[dev->rxTail].errors);*/
Spinlock_Unlock(&dev->lock);
goto retry;
}
Spinlock_Unlock(&dev->lock);
return 0;
}
/*
* Transmit packets
*/
//E1000_Enqueue(SGArray *sga)
int
E1000_Enqueue(NIC *nic, MBuf *mbuf, NICCB cb, void *arg)
{
}
void
E1000_RXInit(E1000Dev *dev)
@ -393,6 +452,14 @@ E1000_Configure(PCIDevice dev)
kprintf("E1000: MAC XX:XX:XX:XX:XX:XX\n");
// Device lock
Spinlock_Init(&ethDev->lock, "E1000 Spinlock", SPINLOCK_TYPE_NORMAL);
// IO Semaphore
Semaphore_Init(&ethDev->ioSema, 0, "E1000 Semaphore");
ethDev->nic.tx = &E1000_Enqueue;
ethDev->nic.rx = &E1000_Dequeue;
// Enable interrupts
//MMIO_Write32(ethDev, E1000_REG_IMC, ~0);
MMIO_Write32(ethDev, E1000_REG_IMS, 0x1F6DC); //ICR_TXDW | ICR_RXO | ICR_RXT0);

View File

@ -36,11 +36,13 @@
// Network
#define SYSCALL_NICSTAT 0x40
#define SYSCALL_NICSEND 0x41
#define SYSCALL_NICRECV 0x42
uint64_t Syscall_Entry(uint64_t syscall, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5);
#define SYSCALL_PACK(_errcode, _val) ((_errcode << 32) | (_val))
#define SYSCALL_PACK(_errcode, _val) (((uint64_t)_errcode << 32) | (_val))
#define SYSCALL_ERRCODE(_result) (_result >> 32)
#define SYSCALL_VALUE(_result) (_result & 0xFFFFFFFF)

View File

@ -469,6 +469,36 @@ Syscall_NICStat(uint64_t nicNo, uint64_t user_stat)
return 0;
}
uint64_t
Syscall_NICSend(uint64_t nicNo, uint64_t user_mbuf)
{
return SYSCALL_PACK(ENOSYS, 0);
}
uint64_t
Syscall_NICRecv(uint64_t nicNo, uint64_t user_mbuf)
{
int status;
NIC *nic;
MBuf mbuf;
status = CopyIn(user_mbuf, &mbuf, sizeof(mbuf));
if (status != 0) {
return SYSCALL_PACK(status, 0);
}
nic = NIC_GetByID(nicNo);
if (nic == NULL) {
return SYSCALL_PACK(ENOENT, 0);
}
// Pin Memory
(nic->rx)(nic, &mbuf, NULL, NULL);
// Unpin Memory
return 0;
}
uint64_t
Syscall_Entry(uint64_t syscall, uint64_t a1, uint64_t a2,
uint64_t a3, uint64_t a4, uint64_t a5)
@ -519,6 +549,10 @@ Syscall_Entry(uint64_t syscall, uint64_t a1, uint64_t a2,
return Syscall_ThreadWait(a1);
case SYSCALL_NICSTAT:
return Syscall_NICStat(a1, a2);
case SYSCALL_NICSEND:
return Syscall_NICSend(a1, a2);
case SYSCALL_NICRECV:
return Syscall_NICRecv(a1, a2);
default:
return (uint64_t)-1;
}