Plumbing for raw packet reading
This commit is contained in:
parent
d005029577
commit
8f24dbe6d0
@ -10,6 +10,7 @@
|
||||
#define ENOENT 0xBAD6
|
||||
#define ENOTDIR 0xBAD7
|
||||
#define ENAMETOOLONG 0xBAD8
|
||||
#define ENOSYS 0xBAD9
|
||||
|
||||
#endif /* __ERRNO_H__ */
|
||||
|
||||
|
@ -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__ */
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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(ðDev->lock, "E1000 Spinlock", SPINLOCK_TYPE_NORMAL);
|
||||
|
||||
// IO Semaphore
|
||||
Semaphore_Init(ðDev->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);
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user