Cleanup E1000 driver and read MAC from MMIO for Qemu.
This commit is contained in:
parent
f7c3993e2d
commit
4b926b6ca9
@ -24,6 +24,8 @@ typedef struct E1000Device
|
|||||||
static E1000Device deviceList[] =
|
static E1000Device deviceList[] =
|
||||||
{
|
{
|
||||||
{ 0x8086100e, "E1000", 0 }, // EERD is not supported
|
{ 0x8086100e, "E1000", 0 }, // EERD is not supported
|
||||||
|
{ 0x808610c9, "IGB", 0 },
|
||||||
|
{ 0x808610d3, "E1000E", 0 },
|
||||||
// { 0x80861209, "i82551", 0 }, // Doesn't seem to work on my qemu build
|
// { 0x80861209, "i82551", 0 }, // Doesn't seem to work on my qemu build
|
||||||
{ 0, "", 0 },
|
{ 0, "", 0 },
|
||||||
};
|
};
|
||||||
@ -62,6 +64,22 @@ void E1000_Configure(PCIDevice dev);
|
|||||||
|
|
||||||
#define E1000_REG_MTABASE 0x5200
|
#define E1000_REG_MTABASE 0x5200
|
||||||
|
|
||||||
|
#define E1000_REG_RAL 0x5400
|
||||||
|
#define E1000_REG_RAH 0x5404
|
||||||
|
|
||||||
|
// EEPROM Control and Data Register
|
||||||
|
#define EE_SK (1 << 0)
|
||||||
|
#define EE_CS (1 << 1)
|
||||||
|
#define EE_DI (1 << 2)
|
||||||
|
#define EE_DO (1 << 3)
|
||||||
|
// FWE (Flash Write Enable) 5:4
|
||||||
|
#define EE_REQ (1 << 6)
|
||||||
|
#define EE_GNT (1 << 7)
|
||||||
|
#define EE_PRES (1 << 8)
|
||||||
|
#define EE_SIZE (1 << 9)
|
||||||
|
#define EE_SIZE2 (1 << 10)
|
||||||
|
#define EE_TYPE (1 << 13)
|
||||||
|
|
||||||
// EEPROM Offsets
|
// EEPROM Offsets
|
||||||
#define NVM_MAC_ADDR 0x0000
|
#define NVM_MAC_ADDR 0x0000
|
||||||
#define NVM_DEVICE_ID 0x000D
|
#define NVM_DEVICE_ID 0x000D
|
||||||
@ -180,7 +198,7 @@ E1000_Init(uint32_t bus, uint32_t slot, uint32_t func)
|
|||||||
int deviceIdx = 0;
|
int deviceIdx = 0;
|
||||||
while (deviceList[deviceIdx].device != 0x0) {
|
while (deviceList[deviceIdx].device != 0x0) {
|
||||||
if (deviceList[deviceIdx].device == device) {
|
if (deviceList[deviceIdx].device == device) {
|
||||||
kprintf("E1000: Found %s\n", deviceList[deviceIdx].name);
|
Log(e1000, "Found %s\n", deviceList[deviceIdx].name);
|
||||||
// Configure and add disks
|
// Configure and add disks
|
||||||
E1000_Configure(dev);
|
E1000_Configure(dev);
|
||||||
}
|
}
|
||||||
@ -198,7 +216,7 @@ MMIO_Read32(E1000Dev *dev, uint64_t addr)
|
|||||||
static inline void
|
static inline void
|
||||||
MMIO_Write32(E1000Dev *dev, uint64_t addr, uint32_t val)
|
MMIO_Write32(E1000Dev *dev, uint64_t addr, uint32_t val)
|
||||||
{
|
{
|
||||||
*(uint32_t *)(dev->mmiobase + addr) = val;
|
*(uint32_t volatile *)(dev->mmiobase + addr) = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t
|
static uint16_t
|
||||||
@ -206,6 +224,13 @@ E1000_EEPROM_Read(E1000Dev *dev, uint8_t addr)
|
|||||||
{
|
{
|
||||||
uint16_t val;
|
uint16_t val;
|
||||||
|
|
||||||
|
uint32_t eecd = MMIO_Read32(dev, E1000_REG_EECD);
|
||||||
|
MMIO_Write32(dev, E1000_REG_EECD, eecd & ~(EE_REQ|EE_GNT));
|
||||||
|
if (!(eecd & EE_PRES)) {
|
||||||
|
DLOG(e1000, "EEPROM Not Present!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Write Address
|
// Write Address
|
||||||
MMIO_Write32(dev, E1000_REG_EERD, ((uint32_t)addr << 8) | 1);
|
MMIO_Write32(dev, E1000_REG_EERD, ((uint32_t)addr << 8) | 1);
|
||||||
|
|
||||||
@ -216,7 +241,7 @@ E1000_EEPROM_Read(E1000Dev *dev, uint8_t addr)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
kprintf("%08x\n", val);
|
DLOG(e1000, "EEPROM 0x%02x = %08x\n", addr, val);
|
||||||
|
|
||||||
return (uint16_t)((val >> 16) & 0x0000FFFF);
|
return (uint16_t)((val >> 16) & 0x0000FFFF);
|
||||||
}
|
}
|
||||||
@ -225,7 +250,7 @@ void
|
|||||||
E1000_TXPoll(E1000Dev *dev)
|
E1000_TXPoll(E1000Dev *dev)
|
||||||
{
|
{
|
||||||
// Free memory
|
// Free memory
|
||||||
kprintf("TXPOLL\n");
|
Log(e1000, "TXPOLL\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -249,8 +274,8 @@ E1000_RXPoll(E1000Dev *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dev->rxDesc[dev->rxTail].errors) {
|
if (dev->rxDesc[dev->rxTail].errors) {
|
||||||
kprintf("E1000: Error in RX Queue %x\n",
|
Alert(e1000, "Error in RX Queue %x\n",
|
||||||
dev->rxDesc[dev->rxTail].errors);
|
dev->rxDesc[dev->rxTail].errors);
|
||||||
dev->rxDesc[dev->rxTail].status = 0;
|
dev->rxDesc[dev->rxTail].status = 0;
|
||||||
dev->rxDesc[dev->rxTail].errors = 0;
|
dev->rxDesc[dev->rxTail].errors = 0;
|
||||||
MMIO_Write32(dev, E1000_REG_RDT, dev->rxTail);
|
MMIO_Write32(dev, E1000_REG_RDT, dev->rxTail);
|
||||||
@ -272,8 +297,8 @@ E1000_Interrupt(void *arg)
|
|||||||
{
|
{
|
||||||
E1000Dev *dev = (E1000Dev *)arg;
|
E1000Dev *dev = (E1000Dev *)arg;
|
||||||
|
|
||||||
kprintf("E1000 (%d:%d) Interrupt\n",
|
DLOG(e1000, "Interrupt (%d:%d)\n",
|
||||||
dev->dev.bus, dev->dev.slot);
|
dev->dev.bus, dev->dev.slot);
|
||||||
|
|
||||||
uint32_t cause = MMIO_Read32(dev, E1000_REG_ICR);
|
uint32_t cause = MMIO_Read32(dev, E1000_REG_ICR);
|
||||||
|
|
||||||
@ -292,7 +317,7 @@ E1000_Interrupt(void *arg)
|
|||||||
// Receive Overrun
|
// Receive Overrun
|
||||||
if (cause & ICR_RXO) {
|
if (cause & ICR_RXO) {
|
||||||
cause &= ~ICR_RXO;
|
cause &= ~ICR_RXO;
|
||||||
kprintf("underrun %u %u\n", MMIO_Read32(dev, E1000_REG_RDH), dev->rxTail);
|
DLOG(e1000, "underrun %u %u\n", MMIO_Read32(dev, E1000_REG_RDH), dev->rxTail);
|
||||||
|
|
||||||
E1000_RXPoll(dev);
|
E1000_RXPoll(dev);
|
||||||
}
|
}
|
||||||
@ -304,7 +329,7 @@ E1000_Interrupt(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cause != 0) {
|
if (cause != 0) {
|
||||||
kprintf("E1000: Unhandled cause %08x\n", cause);
|
Alert(e1000, "Unhandled cause %08x\n", cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
MMIO_Read32(dev, E1000_REG_ICR);
|
MMIO_Read32(dev, E1000_REG_ICR);
|
||||||
@ -460,9 +485,9 @@ E1000_Configure(PCIDevice dev)
|
|||||||
if (dev.bars[bar].size == 0)
|
if (dev.bars[bar].size == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
kprintf("E1000: BAR%d base=%08x size=%08x %s\n",
|
Log(e1000, "BAR%d base=%08x size=%08x %s\n",
|
||||||
bar, dev.bars[bar].base, dev.bars[bar].size,
|
bar, dev.bars[bar].base, dev.bars[bar].size,
|
||||||
dev.bars[bar].type == PCIBAR_TYPE_IO ? "IO" : "Mem");
|
dev.bars[bar].type == PCIBAR_TYPE_IO ? "IO" : "Mem");
|
||||||
}
|
}
|
||||||
|
|
||||||
ethDev->mmiobase = (uint8_t *)DMPA2VA(dev.bars[0].base);
|
ethDev->mmiobase = (uint8_t *)DMPA2VA(dev.bars[0].base);
|
||||||
@ -471,16 +496,31 @@ E1000_Configure(PCIDevice dev)
|
|||||||
MMIO_Write32(ethDev, E1000_REG_CTRL, MMIO_Read32(ethDev, E1000_REG_CTRL) | CTRL_SLU);
|
MMIO_Write32(ethDev, E1000_REG_CTRL, MMIO_Read32(ethDev, E1000_REG_CTRL) | CTRL_SLU);
|
||||||
|
|
||||||
// Register IRQs
|
// Register IRQs
|
||||||
kprintf("E1000: IRQ %d\n", dev.irq);
|
Log(e1000, "IRQ %d\n", dev.irq);
|
||||||
ethDev->irqHandle.irq = dev.irq;
|
ethDev->irqHandle.irq = dev.irq;
|
||||||
ethDev->irqHandle.cb = &E1000_Interrupt;
|
ethDev->irqHandle.cb = &E1000_Interrupt;
|
||||||
ethDev->irqHandle.arg = ethDev;
|
ethDev->irqHandle.arg = ethDev;
|
||||||
IRQ_Register(dev.irq, ðDev->irqHandle);
|
IRQ_Register(dev.irq, ðDev->irqHandle);
|
||||||
|
|
||||||
kprintf("E1000: MAC XX:XX:XX:XX:XX:XX\n");
|
// EEPROM's are really supported on Qemu or Virtualbox
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
E1000_EEPROM_Read(ethDev, NVM_MAC_ADDR + 2*i);
|
E1000_EEPROM_Read(ethDev, NVM_MAC_ADDR + 2*i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t ral = MMIO_Read32(ethDev, E1000_REG_RAL);
|
||||||
|
uint32_t rah = MMIO_Read32(ethDev, E1000_REG_RAH);
|
||||||
|
|
||||||
|
ethDev->nic.mac[0] = ral & 0xff;
|
||||||
|
ethDev->nic.mac[1] = (ral >> 8) & 0xff;
|
||||||
|
ethDev->nic.mac[2] = (ral >> 16) & 0xff;
|
||||||
|
ethDev->nic.mac[3] = (ral >> 24) & 0xff;
|
||||||
|
ethDev->nic.mac[4] = rah & 0xff;
|
||||||
|
ethDev->nic.mac[5] = (rah >> 8) & 0xff;
|
||||||
|
|
||||||
|
Log(e1000, "MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||||
|
ethDev->nic.mac[0], ethDev->nic.mac[1],
|
||||||
|
ethDev->nic.mac[2], ethDev->nic.mac[3],
|
||||||
|
ethDev->nic.mac[4], ethDev->nic.mac[5]);
|
||||||
|
|
||||||
// Device lock
|
// Device lock
|
||||||
Spinlock_Init(ðDev->lock, "E1000 Spinlock", SPINLOCK_TYPE_NORMAL);
|
Spinlock_Init(ðDev->lock, "E1000 Spinlock", SPINLOCK_TYPE_NORMAL);
|
||||||
|
@ -24,11 +24,12 @@
|
|||||||
SYSCTL_STR(kern_ostype, SYSCTL_FLAG_RO, "OS Type", "Castor") \
|
SYSCTL_STR(kern_ostype, SYSCTL_FLAG_RO, "OS Type", "Castor") \
|
||||||
SYSCTL_INT(kern_hz, SYSCTL_FLAG_RW, "Tick frequency", 100) \
|
SYSCTL_INT(kern_hz, SYSCTL_FLAG_RW, "Tick frequency", 100) \
|
||||||
SYSCTL_INT(time_tzadj, SYSCTL_FLAG_RW, "Time zone offset in seconds", 0) \
|
SYSCTL_INT(time_tzadj, SYSCTL_FLAG_RW, "Time zone offset in seconds", 0) \
|
||||||
SYSCTL_INT(log_syscall, SYSCTL_FLAG_RW, "Syscall log level", 0) \
|
SYSCTL_INT(log_e1000, SYSCTL_FLAG_RW, "E1000 log level", 10) \
|
||||||
|
SYSCTL_INT(log_ide, SYSCTL_FLAG_RW, "IDE log level", 0) \
|
||||||
SYSCTL_INT(log_loader, SYSCTL_FLAG_RW, "Loader log level", 0) \
|
SYSCTL_INT(log_loader, SYSCTL_FLAG_RW, "Loader log level", 0) \
|
||||||
SYSCTL_INT(log_vfs, SYSCTL_FLAG_RW, "VFS log level", 0) \
|
|
||||||
SYSCTL_INT(log_o2fs, SYSCTL_FLAG_RW, "O2FS log level", 0) \
|
SYSCTL_INT(log_o2fs, SYSCTL_FLAG_RW, "O2FS log level", 0) \
|
||||||
SYSCTL_INT(log_ide, SYSCTL_FLAG_RW, "IDE log level", 0)
|
SYSCTL_INT(log_syscall, SYSCTL_FLAG_RW, "Syscall log level", 0) \
|
||||||
|
SYSCTL_INT(log_vfs, SYSCTL_FLAG_RW, "VFS log level", 0)
|
||||||
|
|
||||||
#define SYSCTL_STR_MAXLENGTH 128
|
#define SYSCTL_STR_MAXLENGTH 128
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user