replace nob with ms' build, move disk creation to build.bat, major comment cleanup, remove old and stupid tests, overhaul interrupt management with per-CPU vector allocation, affinity migration and safe teardown, add proper IOAPIC routing and PCI MSI/MSI-X/INTx support, migrate drivers to the new interrupt API, integrate ACPICA with a proper OS services layer, move ACPI firmware events, power button handling and S5 shutdown into acpi.sys, add parallel driver startup and atomic publication, replace PnP arrays with dynamic lists, redesign service startup again to be asynchronous, add delayed startup mode for services, allow omitting keys in services.ini, fix acpi ec deferred work handling, fix kernel threads having garbage exit code.
This commit is contained in:
1 parent
d36f19509c
commit
36eef8f58d
696 files changed
+147281
-7530
No files matched your search
@@ -0,0 +1 @@
|
||||
DIRS=lwip rtl8139 rtl816x
|
||||
@@ -146,7 +146,6 @@ static NET_STACK_PROVIDER gLwipProvider = {
|
||||
LwipProviderReceiveFrame,
|
||||
};
|
||||
|
||||
// Implements the err To Status operation.
|
||||
static KSTATUS LwipErrToStatus(err_t err) {
|
||||
switch (err) {
|
||||
case ERR_OK: return NTLSTATUS_SUCCESS;
|
||||
@@ -167,7 +166,6 @@ static KSTATUS LwipErrToStatus(err_t err) {
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the ascii Is Digit operation.
|
||||
static bool LwipAsciiIsDigit(char c) {
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
@@ -365,20 +363,17 @@ static KSTATUS LwipLoadNetifConfig(const NET_DEVICE* device, LWIP_NETIF_CONFIG*
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the socket Lock operation.
|
||||
static KSTATUS LwipSocketLock(LWIP_PROVIDER_SOCKET* s) {
|
||||
if (!s || !s->Lock)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
return KeWaitSemaphore(s->Lock, KE_WAIT_INFINITE);
|
||||
}
|
||||
|
||||
// Implements the socket Unlock operation.
|
||||
static void LwipSocketUnlock(LWIP_PROVIDER_SOCKET* s) {
|
||||
if (s && s->Lock)
|
||||
KeSignalSemaphore(s->Lock);
|
||||
}
|
||||
|
||||
// Implements the socket Callback operation.
|
||||
static void LwipSocketCallback(struct netconn* conn, enum netconn_evt evt, u16_t len) {
|
||||
(void)len;
|
||||
if (!conn)
|
||||
@@ -571,7 +566,6 @@ static bool LwipSocketFamilyMatches(const LWIP_PROVIDER_SOCKET* s, const SYS_SOC
|
||||
return false;
|
||||
}
|
||||
|
||||
// Implements the socket Make Ip operation.
|
||||
static KSTATUS LwipSocketMakeIp(const SYS_SOCKET_ADDRESS_K* address, ip_addr_t* out) {
|
||||
if (!address || !out)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
@@ -595,7 +589,6 @@ static KSTATUS LwipSocketMakeIp(const SYS_SOCKET_ADDRESS_K* address, ip_addr_t*
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
// Implements the socket Fill Address operation.
|
||||
static void LwipSocketFillAddress(SYS_SOCKET_ADDRESS_K* out, const ip_addr_t* ip, u16_t port) {
|
||||
if (!out)
|
||||
return;
|
||||
@@ -624,7 +617,6 @@ static void LwipSocketFillAddress(SYS_SOCKET_ADDRESS_K* out, const ip_addr_t* ip
|
||||
out->Address[3] = (uint8_t)ip4_addr4(ip_2_ip4(ip));
|
||||
}
|
||||
|
||||
// Implements the low Level Output operation.
|
||||
static err_t LwipLowLevelOutput(struct netif* netif, struct pbuf* p) {
|
||||
LWIP_BINDING* b = (LWIP_BINDING*)netif->state;
|
||||
if (!b || !b->Device || !p || p->tot_len < NET_ETHERNET_HEADER_LENGTH)
|
||||
@@ -652,7 +644,6 @@ static err_t LwipLowLevelOutput(struct netif* netif, struct pbuf* p) {
|
||||
return KSUCCESS(st) ? ERR_OK : ERR_IF;
|
||||
}
|
||||
|
||||
// Implements the netif Init operation.
|
||||
static err_t LwipNetifInit(struct netif* netif) {
|
||||
LWIP_BINDING* b = (LWIP_BINDING*)netif->state;
|
||||
if (!b || !b->Device)
|
||||
@@ -773,7 +764,6 @@ static KSTATUS LwipDelayThread(uint64_t milliseconds) {
|
||||
return KeDelayThread(milliseconds);
|
||||
}
|
||||
|
||||
// Implements the stack Initialize operation.
|
||||
static KSTATUS LwipStackInitialize(void) {
|
||||
if (gLwipInitialized)
|
||||
return NTLSTATUS_SUCCESS;
|
||||
@@ -796,7 +786,6 @@ static KSTATUS LwipStackInitialize(void) {
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the provider Attach Device operation.
|
||||
static KSTATUS LwipProviderAttachDevice(NET_DEVICE* device) {
|
||||
if (!gLwipInitialized)
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
@@ -855,7 +844,6 @@ static KSTATUS LwipProviderAttachDevice(NET_DEVICE* device) {
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the provider Receive Frame operation.
|
||||
static KSTATUS LwipProviderReceiveFrame(NET_DEVICE* device, const void* frame, size_t length) {
|
||||
if (!gLwipInitialized)
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
@@ -889,7 +877,6 @@ static KSTATUS LwipProviderReceiveFrame(NET_DEVICE* device, const void* frame, s
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the provider Socket Create operation.
|
||||
static KSTATUS LwipProviderSocketCreate(uint32_t domain, uint32_t type, uint32_t protocol, void** outSocket) {
|
||||
if (!outSocket)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
@@ -937,7 +924,6 @@ static KSTATUS LwipProviderSocketCreate(uint32_t domain, uint32_t type, uint32_t
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the provider Socket Close operation.
|
||||
static void LwipProviderSocketClose(void* socket) {
|
||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||
if (!s)
|
||||
@@ -964,7 +950,6 @@ static void LwipProviderSocketClose(void* socket) {
|
||||
MmFreePool(s);
|
||||
}
|
||||
|
||||
// Implements the provider Bind operation.
|
||||
static KSTATUS LwipProviderBind(void* socket, const SYS_SOCKET_ADDRESS_K* address, size_t addressSize) {
|
||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||
if (!s || !address)
|
||||
@@ -999,7 +984,6 @@ static KSTATUS LwipProviderBind(void* socket, const SYS_SOCKET_ADDRESS_K* addres
|
||||
return LwipErrToStatus(err);
|
||||
}
|
||||
|
||||
// Implements the provider Listen operation.
|
||||
static KSTATUS LwipProviderListen(void* socket, uint32_t backlog) {
|
||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||
if (!s)
|
||||
@@ -1028,7 +1012,6 @@ static KSTATUS LwipProviderListen(void* socket, uint32_t backlog) {
|
||||
return LwipErrToStatus(err);
|
||||
}
|
||||
|
||||
// Implements the provider Accept operation.
|
||||
static KSTATUS LwipProviderAccept(void* socket, void** acceptedOut, SYS_SOCKET_ADDRESS_K* remoteOut, volatile uint8_t* cancelRequested) {
|
||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||
if (!s || !acceptedOut)
|
||||
@@ -1087,7 +1070,6 @@ static KSTATUS LwipProviderAccept(void* socket, void** acceptedOut, SYS_SOCKET_A
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the provider Connect operation.
|
||||
static KSTATUS LwipProviderConnect(void* socket, const SYS_SOCKET_ADDRESS_K* address, size_t addressSize, volatile uint8_t* cancelRequested) {
|
||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||
if (!s || !address)
|
||||
@@ -1173,7 +1155,6 @@ static KSTATUS LwipProviderConnect(void* socket, const SYS_SOCKET_ADDRESS_K* add
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the provider Send operation.
|
||||
static KSTATUS LwipProviderSend(void* socket, const void* buffer, size_t length, uint32_t flags, size_t* sentOut) {
|
||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||
if (sentOut)
|
||||
@@ -1257,7 +1238,6 @@ static KSTATUS LwipReceiveFromBuffered(LWIP_PROVIDER_SOCKET* s, uint8_t* out,
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the provider Receive operation.
|
||||
static KSTATUS LwipProviderReceive(void* socket, void* buffer, size_t length, uint32_t flags, size_t* receivedOut, volatile uint8_t* cancelRequested) {
|
||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||
if (receivedOut)
|
||||
@@ -1462,7 +1442,6 @@ static KSTATUS LwipProviderReceiveFrom(void* socket, void* buffer, size_t length
|
||||
return LwipErrToStatus(err);
|
||||
}
|
||||
|
||||
// Implements the provider Set Option operation.
|
||||
static KSTATUS LwipProviderSetOption(void* socket, uint32_t option, const void* value, size_t valueSize) {
|
||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||
if (!s || !value)
|
||||
@@ -1501,7 +1480,6 @@ static KSTATUS LwipProviderSetOption(void* socket, uint32_t option, const void*
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the provider Get Option operation.
|
||||
static KSTATUS LwipProviderGetOption(void* socket, uint32_t option, void* value, size_t valueSize, size_t* actualSizeOut) {
|
||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||
if (actualSizeOut)
|
||||
@@ -1538,7 +1516,6 @@ static KSTATUS LwipProviderGetOption(void* socket, uint32_t option, void* value,
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the provider Poll operation.
|
||||
static KSTATUS LwipProviderPoll(void* socket, uint32_t events, uint32_t* returnedEventsOut) {
|
||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||
if (!s || !returnedEventsOut)
|
||||
@@ -1577,7 +1554,6 @@ static KSTATUS LwipProviderPoll(void* socket, uint32_t events, uint32_t* returne
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the provider Shutdown operation.
|
||||
static KSTATUS LwipProviderShutdown(void* socket, uint32_t how) {
|
||||
LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket;
|
||||
if (!s)
|
||||
@@ -1648,7 +1624,6 @@ static void LwipResolveStartCallback(void* argument) {
|
||||
LwipResolveRelease(context);
|
||||
}
|
||||
|
||||
// Implements the provider Resolve Host operation.
|
||||
static KSTATUS LwipProviderResolveHost(const char* name, uint32_t family, SYS_SOCKET_ADDRESS_K* addressOut) {
|
||||
if (!name || !addressOut)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
@@ -1819,7 +1794,6 @@ static KSTATUS LwipDispatchInternalDeviceControl(DEVICE_OBJECT* device, IRP* irp
|
||||
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
||||
(void)module;
|
||||
|
||||
DbgPrint("lwIP: driver loading...\n");
|
||||
|
||||
LWIP_NETIF_CONFIG defaultConfig;
|
||||
KSTATUS st = LwipLoadConfigFromSection(LWIP_SETTINGS_DEFAULT_SECTION, &defaultConfig);
|
||||
@@ -1852,7 +1826,6 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
||||
return st;
|
||||
}
|
||||
|
||||
DbgPrint("lwIP: driver initialized\n");
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,7 +43,6 @@ struct sys_mbox {
|
||||
static uint64_t (*gLwipQueryTicksUs)(void) = 0;
|
||||
static uint32_t gRandState = 0x4b4e4554u; // 'KNET'
|
||||
|
||||
// Implements the port Set Timer Query operation.
|
||||
void LwipPortSetTimerQuery(uint64_t (*query_ticks_us)(void)) {
|
||||
gLwipQueryTicksUs = query_ticks_us;
|
||||
}
|
||||
@@ -54,7 +53,6 @@ unsigned int lwip_port_rand(void) {
|
||||
return gRandState;
|
||||
}
|
||||
|
||||
// Implements the sys init operation.
|
||||
void sys_init(void) {
|
||||
}
|
||||
|
||||
@@ -81,7 +79,6 @@ u32_t sys_jiffies(void) {
|
||||
#undef errno
|
||||
#endif
|
||||
int errno;
|
||||
// Implements the errno operation.
|
||||
int* __cdecl _errno(void) { return &errno; }
|
||||
|
||||
err_t sys_sem_new(sys_sem_t* sem, u8_t count) {
|
||||
@@ -104,7 +101,6 @@ err_t sys_sem_new(sys_sem_t* sem, u8_t count) {
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
// Implements the sys sem signal operation.
|
||||
void sys_sem_signal(sys_sem_t* sem) {
|
||||
if (sem && *sem && (*sem)->Sem)
|
||||
KeSignalSemaphore((*sem)->Sem);
|
||||
@@ -127,7 +123,6 @@ u32_t sys_arch_sem_wait(sys_sem_t* sem, u32_t timeout) {
|
||||
: SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
|
||||
// Implements the sys sem free operation.
|
||||
void sys_sem_free(sys_sem_t* sem) {
|
||||
if (!sem || !*sem)
|
||||
return;
|
||||
@@ -157,19 +152,16 @@ err_t sys_mutex_new(sys_mutex_t* mutex) {
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
// Implements the sys mutex lock operation.
|
||||
void sys_mutex_lock(sys_mutex_t* mutex) {
|
||||
if (mutex && *mutex && (*mutex)->Sem)
|
||||
(void)KeWaitSemaphore((*mutex)->Sem, KE_WAIT_INFINITE);
|
||||
}
|
||||
|
||||
// Implements the sys mutex unlock operation.
|
||||
void sys_mutex_unlock(sys_mutex_t* mutex) {
|
||||
if (mutex && *mutex && (*mutex)->Sem)
|
||||
KeSignalSemaphore((*mutex)->Sem);
|
||||
}
|
||||
|
||||
// Implements the sys mutex free operation.
|
||||
void sys_mutex_free(sys_mutex_t* mutex) {
|
||||
if (!mutex || !*mutex)
|
||||
return;
|
||||
@@ -179,7 +171,6 @@ void sys_mutex_free(sys_mutex_t* mutex) {
|
||||
*mutex = 0;
|
||||
}
|
||||
|
||||
// Implements the mbox Try Post operation.
|
||||
static err_t LwipMboxTryPost(sys_mbox_t* mbox, void* msg) {
|
||||
if (!mbox || !*mbox || !(*mbox)->Valid)
|
||||
return ERR_ARG;
|
||||
@@ -232,7 +223,6 @@ err_t sys_mbox_new(sys_mbox_t* mbox, int size) {
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
// Implements the sys mbox post operation.
|
||||
void sys_mbox_post(sys_mbox_t* mbox, void* msg) {
|
||||
// lwIP promises this is not called from ISR context.
|
||||
while (LwipMboxTryPost(mbox, msg) != ERR_OK)
|
||||
@@ -247,7 +237,6 @@ err_t sys_mbox_trypost_fromisr(sys_mbox_t* mbox, void* msg) {
|
||||
return LwipMboxTryPost(mbox, msg);
|
||||
}
|
||||
|
||||
// Implements the mbox Pop After Item operation.
|
||||
static u32_t LwipMboxPopAfterItem(sys_mbox_t* mbox, void** msg, u32_t waited) {
|
||||
struct sys_mbox* m = *mbox;
|
||||
uintptr_t flags = KeAcquireSpinlock(&m->Lock);
|
||||
@@ -296,7 +285,6 @@ u32_t sys_arch_mbox_tryfetch(sys_mbox_t* mbox, void** msg) {
|
||||
return LwipMboxPopAfterItem(mbox, msg, 0);
|
||||
}
|
||||
|
||||
// Implements the sys mbox free operation.
|
||||
void sys_mbox_free(sys_mbox_t* mbox) {
|
||||
if (!mbox || !*mbox)
|
||||
return;
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
!include $(BASEDIR)\makefile.def
|
||||
@@ -0,0 +1,15 @@
|
||||
TARGETNAME=lwip
|
||||
TARGETPATH=obj
|
||||
TARGETTYPE=DRIVER
|
||||
FLAVOR=LWIP
|
||||
TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib"
|
||||
EXTRA_LFLAGS=/NOENTRY
|
||||
INCLUDES=$(BASEDIR)\code\drivers\net\lwip\include;$(BASEDIR)\code\drivers\net\lwip\third_party\lwip\src\include
|
||||
SOURCES=@/code/drivers/net/lwip/lwip_sys_arch.c @/code/drivers/net/lwip/lwip_stack.c @/code/drivers/net/lwip/third_party/lwip/src/core/init.c @/code/drivers/net/lwip/third_party/lwip/src/core/def.c @/code/drivers/net/lwip/third_party/lwip/src/core/dns.c @/code/drivers/net/lwip/third_party/lwip/src/core/inet_chksum.c \
|
||||
@/code/drivers/net/lwip/third_party/lwip/src/core/ip.c @/code/drivers/net/lwip/third_party/lwip/src/core/mem.c @/code/drivers/net/lwip/third_party/lwip/src/core/memp.c @/code/drivers/net/lwip/third_party/lwip/src/core/netif.c @/code/drivers/net/lwip/third_party/lwip/src/core/pbuf.c @/code/drivers/net/lwip/third_party/lwip/src/core/raw.c \
|
||||
@/code/drivers/net/lwip/third_party/lwip/src/core/stats.c @/code/drivers/net/lwip/third_party/lwip/src/core/sys.c @/code/drivers/net/lwip/third_party/lwip/src/core/altcp.c @/code/drivers/net/lwip/third_party/lwip/src/core/altcp_alloc.c @/code/drivers/net/lwip/third_party/lwip/src/core/altcp_tcp.c @/code/drivers/net/lwip/third_party/lwip/src/core/tcp.c \
|
||||
@/code/drivers/net/lwip/third_party/lwip/src/core/tcp_in.c @/code/drivers/net/lwip/third_party/lwip/src/core/tcp_out.c @/code/drivers/net/lwip/third_party/lwip/src/core/timeouts.c @/code/drivers/net/lwip/third_party/lwip/src/core/udp.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/acd.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/autoip.c \
|
||||
@/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/dhcp.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/etharp.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/icmp.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/igmp.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/ip4_frag.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/ip4.c \
|
||||
@/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/ip4_addr.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/dhcp6.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/ethip6.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/icmp6.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/inet6.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/ip6_frag.c \
|
||||
@/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/ip6.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/ip6_addr.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/mld6.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/nd6.c @/code/drivers/net/lwip/third_party/lwip/src/api/api_lib.c @/code/drivers/net/lwip/third_party/lwip/src/api/api_msg.c \
|
||||
@/code/drivers/net/lwip/third_party/lwip/src/api/err.c @/code/drivers/net/lwip/third_party/lwip/src/api/netbuf.c @/code/drivers/net/lwip/third_party/lwip/src/api/tcpip.c @/code/drivers/net/lwip/third_party/lwip/src/netif/ethernet.c
|
||||
@@ -0,0 +1 @@
|
||||
!include $(BASEDIR)\makefile.def
|
||||
@@ -4,9 +4,6 @@
|
||||
#include "rtl8139.h"
|
||||
|
||||
static DRIVER_OBJECT gRtl8139Driver;
|
||||
static RTL8139_DEVICE* gRtl8139Devices[RTL8139_MAX_DEVICES];
|
||||
static uint32_t gRtl8139DeviceCount;
|
||||
static SPINLOCK gRtl8139RegistryLock = SPINLOCK_INIT;
|
||||
|
||||
static const IO_DEVICE_ID gRtl8139Ids[] = {
|
||||
{ IoBusPci, { "PCI\\VEN_10EC&DEV_8139", sizeof("PCI\\VEN_10EC&DEV_8139") - 1 } },
|
||||
@@ -17,53 +14,45 @@ static const IO_DRIVER_ID_TABLE gRtl8139IdTable = {
|
||||
sizeof(gRtl8139Ids) / sizeof(gRtl8139Ids[0]),
|
||||
};
|
||||
|
||||
// Implements the memory Barrier operation.
|
||||
static __forceinline void Rtl8139MemoryBarrier(void) {
|
||||
_ReadWriteBarrier();
|
||||
_mm_mfence();
|
||||
_ReadWriteBarrier();
|
||||
}
|
||||
|
||||
// Implements the read8 operation.
|
||||
static uint8_t Rtl8139Read8(RTL8139_DEVICE* r, uint32_t reg) {
|
||||
if (r->UseMmio)
|
||||
return *(volatile uint8_t*)(r->Mmio + reg);
|
||||
return __inbyte((unsigned short)(r->IoBase + reg));
|
||||
}
|
||||
|
||||
// Implements the read16 operation.
|
||||
static uint16_t Rtl8139Read16(RTL8139_DEVICE* r, uint32_t reg) {
|
||||
if (r->UseMmio)
|
||||
return *(volatile uint16_t*)(r->Mmio + reg);
|
||||
return __inword((unsigned short)(r->IoBase + reg));
|
||||
}
|
||||
|
||||
// Implements the read32 operation.
|
||||
static uint32_t Rtl8139Read32(RTL8139_DEVICE* r, uint32_t reg) {
|
||||
if (r->UseMmio)
|
||||
return *(volatile uint32_t*)(r->Mmio + reg);
|
||||
return __indword((unsigned short)(r->IoBase + reg));
|
||||
}
|
||||
|
||||
// Implements the write8 operation.
|
||||
static void Rtl8139Write8(RTL8139_DEVICE* r, uint32_t reg, uint8_t value) {
|
||||
if (r->UseMmio) *(volatile uint8_t*)(r->Mmio + reg) = value;
|
||||
else __outbyte((unsigned short)(r->IoBase + reg), value);
|
||||
}
|
||||
|
||||
// Implements the write16 operation.
|
||||
static void Rtl8139Write16(RTL8139_DEVICE* r, uint32_t reg, uint16_t value) {
|
||||
if (r->UseMmio) *(volatile uint16_t*)(r->Mmio + reg) = value;
|
||||
else __outword((unsigned short)(r->IoBase + reg), value);
|
||||
}
|
||||
|
||||
// Implements the write32 operation.
|
||||
static void Rtl8139Write32(RTL8139_DEVICE* r, uint32_t reg, uint32_t value) {
|
||||
if (r->UseMmio) *(volatile uint32_t*)(r->Mmio + reg) = value;
|
||||
else __outdword((unsigned short)(r->IoBase + reg), value);
|
||||
}
|
||||
|
||||
// Implements the reset operation.
|
||||
static KSTATUS Rtl8139Reset(RTL8139_DEVICE* r) {
|
||||
Rtl8139Write8(r, RTL8139_REG_CMD, RTL8139_CMD_RST);
|
||||
for (uint32_t i = 0; i < 1000; i++) {
|
||||
@@ -157,7 +146,6 @@ static KSTATUS Rtl8139AllocateDma(RTL8139_DEVICE* r) {
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the rx Read16 operation.
|
||||
static uint16_t Rtl8139RxRead16(RTL8139_DEVICE* r, uint32_t offset) {
|
||||
offset %= RTL8139_RX_RING_SIZE;
|
||||
uint16_t lo = r->RxBuffer[offset];
|
||||
@@ -165,7 +153,6 @@ static uint16_t Rtl8139RxRead16(RTL8139_DEVICE* r, uint32_t offset) {
|
||||
return (uint16_t)(lo | (hi << 8));
|
||||
}
|
||||
|
||||
// Implements the rx Copy operation.
|
||||
static void Rtl8139RxCopy(RTL8139_DEVICE* r, uint32_t offset, void* dst, uint32_t length) {
|
||||
uint8_t* out = (uint8_t*)dst;
|
||||
offset %= RTL8139_RX_RING_SIZE;
|
||||
@@ -178,7 +165,6 @@ static void Rtl8139RxCopy(RTL8139_DEVICE* r, uint32_t offset, void* dst, uint32_
|
||||
memcpy(out + first, r->RxBuffer, length - first);
|
||||
}
|
||||
|
||||
// Implements the program Hardware operation.
|
||||
static void Rtl8139ProgramHardware(RTL8139_DEVICE* r) {
|
||||
// Wake the device and clear stale interrupts before installing buffers.
|
||||
Rtl8139Write8(r, RTL8139_REG_CONFIG1, 0x00);
|
||||
@@ -252,7 +238,6 @@ static void Rtl8139HandleRx(RTL8139_DEVICE* r) {
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the dpc Routine operation.
|
||||
static void Rtl8139DpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2) {
|
||||
(void)dpc;
|
||||
(void)systemArgument1;
|
||||
@@ -273,74 +258,19 @@ static void Rtl8139DpcRoutine(KDPC* dpc, void* context, void* systemArgument1, v
|
||||
DbgPrint("RTL8139: interrupt error bits=0x%04x\n", status);
|
||||
}
|
||||
|
||||
// Registers device.
|
||||
static KSTATUS Rtl8139RegisterDevice(RTL8139_DEVICE* r) {
|
||||
if (!r) return NTLSTATUS_INVALID_PARAMETER;
|
||||
static void Rtl8139Isr(void* context) {
|
||||
RTL8139_DEVICE* r = (RTL8139_DEVICE*)context;
|
||||
if (!r || !r->Started || r->Removed || r->SurpriseRemoved) return;
|
||||
uint16_t status = Rtl8139Read16(r, RTL8139_REG_ISR);
|
||||
status &= RTL8139_INTR_ENABLES;
|
||||
if (!status || status == 0xFFFFu)
|
||||
return;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gRtl8139RegistryLock);
|
||||
for (uint32_t i = 0; i < gRtl8139DeviceCount; i++) {
|
||||
if (gRtl8139Devices[i] == r) {
|
||||
KeReleaseSpinlock(&gRtl8139RegistryLock, flags);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (gRtl8139DeviceCount >= RTL8139_MAX_DEVICES) {
|
||||
KeReleaseSpinlock(&gRtl8139RegistryLock, flags);
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
gRtl8139Devices[gRtl8139DeviceCount++] = r;
|
||||
KeReleaseSpinlock(&gRtl8139RegistryLock, flags);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
Rtl8139Write16(r, RTL8139_REG_ISR, status);
|
||||
r->PendingIsr |= status;
|
||||
KeInsertQueueDpc(&r->Dpc, (void*)0, (void*)0);
|
||||
}
|
||||
|
||||
// Implements the unregister Device operation.
|
||||
static void Rtl8139UnregisterDevice(RTL8139_DEVICE* r) {
|
||||
if (!r) return;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gRtl8139RegistryLock);
|
||||
for (uint32_t i = 0; i < gRtl8139DeviceCount; i++) {
|
||||
if (gRtl8139Devices[i] == r) {
|
||||
gRtl8139Devices[i] = gRtl8139Devices[gRtl8139DeviceCount - 1u];
|
||||
gRtl8139Devices[gRtl8139DeviceCount - 1u] = (RTL8139_DEVICE*)0;
|
||||
gRtl8139DeviceCount--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
KeReleaseSpinlock(&gRtl8139RegistryLock, flags);
|
||||
}
|
||||
|
||||
// Implements the isr operation.
|
||||
static void Rtl8139Isr(void) {
|
||||
RTL8139_DEVICE* snapshot[RTL8139_MAX_DEVICES];
|
||||
uint32_t count = 0;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gRtl8139RegistryLock);
|
||||
count = gRtl8139DeviceCount;
|
||||
if (count > RTL8139_MAX_DEVICES)
|
||||
count = RTL8139_MAX_DEVICES;
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
snapshot[i] = gRtl8139Devices[i];
|
||||
KeReleaseSpinlock(&gRtl8139RegistryLock, flags);
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
RTL8139_DEVICE* r = snapshot[i];
|
||||
if (!r || !r->Started || r->Removed || r->SurpriseRemoved)
|
||||
continue;
|
||||
|
||||
uint16_t status = Rtl8139Read16(r, RTL8139_REG_ISR);
|
||||
status &= RTL8139_INTR_ENABLES;
|
||||
if (!status || status == 0xFFFFu)
|
||||
continue;
|
||||
|
||||
Rtl8139Write16(r, RTL8139_REG_ISR, status);
|
||||
r->PendingIsr |= status;
|
||||
KeInsertQueueDpc(&r->Dpc, (void*)0, (void*)0);
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the send Frame operation.
|
||||
static KSTATUS Rtl8139SendFrame(NET_DEVICE* device, const void* frame, size_t length) {
|
||||
if (!device || !frame)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
@@ -377,7 +307,6 @@ static KSTATUS Rtl8139SendFrame(NET_DEVICE* device, const void* frame, size_t le
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the select Register Bar operation.
|
||||
static KSTATUS Rtl8139SelectRegisterBar(RTL8139_DEVICE* r) {
|
||||
if (!r || !r->Pdo)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
@@ -478,12 +407,10 @@ static KSTATUS Rtl8139StartDevice(RTL8139_DEVICE* r) {
|
||||
return st;
|
||||
}
|
||||
|
||||
st = PciGetInterrupt(r->Pdo, &r->Irq);
|
||||
if (!KSUCCESS(st) || r->Irq == 0xFFu) {
|
||||
DbgPrint("RTL8139: no legacy PCI IRQ line wired\n");
|
||||
return KSUCCESS(st) ? NTLSTATUS_NOT_SUPPORTED : st;
|
||||
}
|
||||
|
||||
r->InterruptRequest.Routine = Rtl8139Isr;
|
||||
r->InterruptRequest.Context = r;
|
||||
r->InterruptRequest.Affinity = 0;
|
||||
r->InterruptRequest.Interrupt = (KE_INTERRUPT*)0;
|
||||
Rtl8139Write8(r, RTL8139_REG_CONFIG1, 0x00);
|
||||
st = Rtl8139Reset(r);
|
||||
if (!KSUCCESS(st)) {
|
||||
@@ -492,11 +419,10 @@ static KSTATUS Rtl8139StartDevice(RTL8139_DEVICE* r) {
|
||||
}
|
||||
|
||||
Rtl8139ReadMac(r);
|
||||
DbgPrint("RTL8139: MAC %02x:%02x:%02x:%02x:%02x:%02x irq=%u\n",
|
||||
DbgPrint("RTL8139: MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
|
||||
r->NetDevice.HardwareAddress[0], r->NetDevice.HardwareAddress[1],
|
||||
r->NetDevice.HardwareAddress[2], r->NetDevice.HardwareAddress[3],
|
||||
r->NetDevice.HardwareAddress[4], r->NetDevice.HardwareAddress[5],
|
||||
r->Irq);
|
||||
r->NetDevice.HardwareAddress[4], r->NetDevice.HardwareAddress[5]);
|
||||
|
||||
st = Rtl8139AllocateDma(r);
|
||||
if (!KSUCCESS(st))
|
||||
@@ -508,13 +434,16 @@ static KSTATUS Rtl8139StartDevice(RTL8139_DEVICE* r) {
|
||||
r->NetDevice.DriverContext = r;
|
||||
r->NetDevice.SendFrame = Rtl8139SendFrame;
|
||||
|
||||
st = Rtl8139RegisterDevice(r);
|
||||
bool message;
|
||||
st = PciConnectInterrupts(r->Pdo, &r->InterruptRequest, 1u, &message);
|
||||
if (!KSUCCESS(st)) {
|
||||
Rtl8139ReleaseDma(r);
|
||||
return st;
|
||||
}
|
||||
|
||||
KeIrqRegister(r->Irq, Rtl8139Isr);
|
||||
KE_INTERRUPT_INFO route;
|
||||
if (KSUCCESS(KeInterruptQuery(r->InterruptRequest.Interrupt, &route)))
|
||||
DbgPrint("RTL8139: cpu=%u vector=0x%02x mode=%s\n",
|
||||
route.CpuIndex, route.Vector, message ? "MSI/MSI-X" : "INTx");
|
||||
r->Started = true;
|
||||
Rtl8139ProgramHardware(r);
|
||||
r->Fdo->PnpState = DevicePnpStarted;
|
||||
@@ -522,12 +451,13 @@ static KSTATUS Rtl8139StartDevice(RTL8139_DEVICE* r) {
|
||||
st = NetRegisterDevice(&r->NetDevice);
|
||||
if (!KSUCCESS(st)) {
|
||||
Rtl8139StopDma(r);
|
||||
Rtl8139UnregisterDevice(r);
|
||||
if (r->InterruptRequest.Interrupt)
|
||||
PciDisconnectInterrupts(r->Pdo, &r->InterruptRequest, 1u);
|
||||
Rtl8139ReleaseDma(r);
|
||||
return st;
|
||||
}
|
||||
|
||||
DbgPrint("RTL8139: initialized; RX/TX enabled on IRQ %u\n", r->Irq);
|
||||
DbgPrint("RTL8139: initialized; RX/TX interrupt connected\n");
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -562,7 +492,8 @@ KSTATUS Rtl8139DispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
||||
r->Removed = true;
|
||||
device->PnpState = DevicePnpDeleted;
|
||||
Rtl8139StopDma(r);
|
||||
Rtl8139UnregisterDevice(r);
|
||||
if (r->InterruptRequest.Interrupt)
|
||||
PciDisconnectInterrupts(r->Pdo, &r->InterruptRequest, 1u);
|
||||
Rtl8139ReleaseDma(r);
|
||||
IoDetachDevice(device);
|
||||
IoDeleteDevice(device);
|
||||
@@ -573,7 +504,6 @@ KSTATUS Rtl8139DispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the add Device operation.
|
||||
KSTATUS Rtl8139AddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
||||
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
@@ -589,7 +519,7 @@ KSTATUS Rtl8139AddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObj
|
||||
r->Magic = RTL8139_DEVICE_MAGIC;
|
||||
r->Fdo = fdo;
|
||||
r->Pdo = physicalDeviceObject;
|
||||
r->Irq = 0xFFu;
|
||||
r->PciInfo.InterruptLine = 0xFFu;
|
||||
r->TxLock = (SPINLOCK)SPINLOCK_INIT;
|
||||
|
||||
r->LowerDevice = IoAttachDeviceToDeviceStack(fdo, physicalDeviceObject);
|
||||
@@ -605,9 +535,7 @@ KSTATUS Rtl8139AddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObj
|
||||
static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
||||
(void)module;
|
||||
|
||||
DbgPrint("RTL8139: driver loading...\n");
|
||||
|
||||
gRtl8139DeviceCount = 0;
|
||||
|
||||
memset(&gRtl8139Driver, 0, sizeof(gRtl8139Driver));
|
||||
IoInitializeDriverObject(&gRtl8139Driver, SYS_SV_LITERAL("rtl8139"));
|
||||
|
||||
@@ -105,7 +105,7 @@ typedef struct RTL8139_DEVICE {
|
||||
PCI_DEVICE_INFO PciInfo;
|
||||
PCI_BAR RegisterBar;
|
||||
uint64_t RegisterBytes;
|
||||
uint8_t Irq;
|
||||
PCI_INTERRUPT_REQUEST InterruptRequest;
|
||||
|
||||
bool Started;
|
||||
bool Removed;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
TARGETNAME=rtl8139
|
||||
TARGETPATH=obj
|
||||
TARGETTYPE=DRIVER
|
||||
FLAVOR=DRIVER
|
||||
TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\pci.lib"
|
||||
EXTRA_LFLAGS=/NOENTRY
|
||||
SOURCES=@/code/drivers/net/rtl8139/rtl8139.c
|
||||
@@ -0,0 +1 @@
|
||||
!include $(BASEDIR)\makefile.def
|
||||
@@ -4,9 +4,6 @@
|
||||
#include "rtl816x.h"
|
||||
|
||||
static DRIVER_OBJECT gRtl816xDriver;
|
||||
static RTL816X_DEVICE* gRtl816xDevices[RTL816X_MAX_DEVICES];
|
||||
static uint32_t gRtl816xDeviceCount;
|
||||
static SPINLOCK gRtl816xRegistryLock = SPINLOCK_INIT;
|
||||
|
||||
static const IO_DEVICE_ID gRtl816xIds[] = {
|
||||
{ IoBusPci, { "PCI\\VEN_10EC&DEV_8168", sizeof("PCI\\VEN_10EC&DEV_8168") - 1 } },
|
||||
@@ -18,53 +15,45 @@ static const IO_DRIVER_ID_TABLE gRtl816xIdTable = {
|
||||
sizeof(gRtl816xIds) / sizeof(gRtl816xIds[0]),
|
||||
};
|
||||
|
||||
// Implements the rtl Memory Barrier operation.
|
||||
static __forceinline void RtlMemoryBarrier(void) {
|
||||
_ReadWriteBarrier();
|
||||
_mm_mfence();
|
||||
_ReadWriteBarrier();
|
||||
}
|
||||
|
||||
// Implements the rtl Read8 operation.
|
||||
static uint8_t RtlRead8(RTL816X_DEVICE* r, uint32_t reg) {
|
||||
if (r->UseMmio)
|
||||
return *(volatile uint8_t*)(r->Mmio + reg);
|
||||
return __inbyte((unsigned short)(r->IoBase + reg));
|
||||
}
|
||||
|
||||
// Implements the rtl Read16 operation.
|
||||
static uint16_t RtlRead16(RTL816X_DEVICE* r, uint32_t reg) {
|
||||
if (r->UseMmio)
|
||||
return *(volatile uint16_t*)(r->Mmio + reg);
|
||||
return __inword((unsigned short)(r->IoBase + reg));
|
||||
}
|
||||
|
||||
// Implements the rtl Read32 operation.
|
||||
static uint32_t RtlRead32(RTL816X_DEVICE* r, uint32_t reg) {
|
||||
if (r->UseMmio)
|
||||
return *(volatile uint32_t*)(r->Mmio + reg);
|
||||
return __indword((unsigned short)(r->IoBase + reg));
|
||||
}
|
||||
|
||||
// Implements the rtl Write8 operation.
|
||||
static void RtlWrite8(RTL816X_DEVICE* r, uint32_t reg, uint8_t value) {
|
||||
if (r->UseMmio) *(volatile uint8_t*)(r->Mmio + reg) = value;
|
||||
else __outbyte((unsigned short)(r->IoBase + reg), value);
|
||||
}
|
||||
|
||||
// Implements the rtl Write16 operation.
|
||||
static void RtlWrite16(RTL816X_DEVICE* r, uint32_t reg, uint16_t value) {
|
||||
if (r->UseMmio) *(volatile uint16_t*)(r->Mmio + reg) = value;
|
||||
else __outword((unsigned short)(r->IoBase + reg), value);
|
||||
}
|
||||
|
||||
// Implements the rtl Write32 operation.
|
||||
static void RtlWrite32(RTL816X_DEVICE* r, uint32_t reg, uint32_t value) {
|
||||
if (r->UseMmio) *(volatile uint32_t*)(r->Mmio + reg) = value;
|
||||
else __outdword((unsigned short)(r->IoBase + reg), value);
|
||||
}
|
||||
|
||||
// Implements the rtl Reset operation.
|
||||
static KSTATUS RtlReset(RTL816X_DEVICE* r) {
|
||||
RtlWrite8(r, RTL_REG_CHIP_CMD, RTL_CMD_RESET);
|
||||
for (uint32_t i = 0; i < 1000; i++) {
|
||||
@@ -75,7 +64,6 @@ static KSTATUS RtlReset(RTL816X_DEVICE* r) {
|
||||
return NTLSTATUS_TIMEOUT;
|
||||
}
|
||||
|
||||
// Implements the rtl Read Mac operation.
|
||||
static void RtlReadMac(RTL816X_DEVICE* r) {
|
||||
for (uint32_t i = 0; i < 6; i++)
|
||||
r->NetDevice.HardwareAddress[i] = RtlRead8(r, RTL_REG_MAC0 + i);
|
||||
@@ -179,7 +167,6 @@ fail:
|
||||
return status;
|
||||
}
|
||||
|
||||
// Implements the rtl Init Descriptors operation.
|
||||
static void RtlInitDescriptors(RTL816X_DEVICE* r) {
|
||||
for (uint32_t i = 0; i < RTL_RX_COUNT; i++) {
|
||||
uint64_t address = r->RxBuffersDeviceAddress + (uint64_t)i * RTL_BUF_SIZE;
|
||||
@@ -202,7 +189,6 @@ static void RtlInitDescriptors(RTL816X_DEVICE* r) {
|
||||
RtlMemoryBarrier();
|
||||
}
|
||||
|
||||
// Implements the rtl Program Hardware operation.
|
||||
static void RtlProgramHardware(RTL816X_DEVICE* r) {
|
||||
RtlWrite8(r, RTL_REG_CFG9346, 0xC0);
|
||||
|
||||
@@ -232,7 +218,6 @@ static void RtlProgramHardware(RTL816X_DEVICE* r) {
|
||||
RtlWrite16(r, RTL_REG_INTR_MASK, RTL_INTR_ENABLES);
|
||||
}
|
||||
|
||||
// Implements the rtl Handle Rx operation.
|
||||
static void RtlHandleRx(RTL816X_DEVICE* r) {
|
||||
for (uint32_t budget = 0; budget < RTL_RX_COUNT; budget++) {
|
||||
RTL_DESC* d = &r->RxRing[r->RxIndex];
|
||||
@@ -270,7 +255,6 @@ static void RtlHandleRx(RTL816X_DEVICE* r) {
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the rtl Dpc Routine operation.
|
||||
static void RtlDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2) {
|
||||
(void)dpc;
|
||||
(void)systemArgument1;
|
||||
@@ -295,74 +279,19 @@ static void RtlDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void*
|
||||
DbgPrint("RTL816X: interrupt status error bits=0x%04x\n", status);
|
||||
}
|
||||
|
||||
// Implements the rtl Register Device operation.
|
||||
static KSTATUS RtlRegisterDevice(RTL816X_DEVICE* r) {
|
||||
if (!r) return NTLSTATUS_INVALID_PARAMETER;
|
||||
static void RtlIsr(void* context) {
|
||||
RTL816X_DEVICE* r = (RTL816X_DEVICE*)context;
|
||||
if (!r || !r->Started || r->Removed || r->SurpriseRemoved) return;
|
||||
uint16_t status = RtlRead16(r, RTL_REG_INTR_STAT);
|
||||
status &= RTL_INTR_ENABLES;
|
||||
if (!status || status == 0xFFFFu)
|
||||
return;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gRtl816xRegistryLock);
|
||||
for (uint32_t i = 0; i < gRtl816xDeviceCount; i++) {
|
||||
if (gRtl816xDevices[i] == r) {
|
||||
KeReleaseSpinlock(&gRtl816xRegistryLock, flags);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (gRtl816xDeviceCount >= RTL816X_MAX_DEVICES) {
|
||||
KeReleaseSpinlock(&gRtl816xRegistryLock, flags);
|
||||
return NTLSTATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
gRtl816xDevices[gRtl816xDeviceCount++] = r;
|
||||
KeReleaseSpinlock(&gRtl816xRegistryLock, flags);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
RtlWrite16(r, RTL_REG_INTR_STAT, status);
|
||||
r->PendingIsr |= status;
|
||||
KeInsertQueueDpc(&r->Dpc, (void*)0, (void*)0);
|
||||
}
|
||||
|
||||
// Implements the rtl Unregister Device operation.
|
||||
static void RtlUnregisterDevice(RTL816X_DEVICE* r) {
|
||||
if (!r) return;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gRtl816xRegistryLock);
|
||||
for (uint32_t i = 0; i < gRtl816xDeviceCount; i++) {
|
||||
if (gRtl816xDevices[i] == r) {
|
||||
gRtl816xDevices[i] = gRtl816xDevices[gRtl816xDeviceCount - 1u];
|
||||
gRtl816xDevices[gRtl816xDeviceCount - 1u] = (RTL816X_DEVICE*)0;
|
||||
gRtl816xDeviceCount--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
KeReleaseSpinlock(&gRtl816xRegistryLock, flags);
|
||||
}
|
||||
|
||||
// Implements the rtl Isr operation.
|
||||
static void RtlIsr(void) {
|
||||
RTL816X_DEVICE* snapshot[RTL816X_MAX_DEVICES];
|
||||
uint32_t count = 0;
|
||||
|
||||
uintptr_t flags = KeAcquireSpinlock(&gRtl816xRegistryLock);
|
||||
count = gRtl816xDeviceCount;
|
||||
if (count > RTL816X_MAX_DEVICES)
|
||||
count = RTL816X_MAX_DEVICES;
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
snapshot[i] = gRtl816xDevices[i];
|
||||
KeReleaseSpinlock(&gRtl816xRegistryLock, flags);
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
RTL816X_DEVICE* r = snapshot[i];
|
||||
if (!r || !r->Started || r->Removed || r->SurpriseRemoved)
|
||||
continue;
|
||||
|
||||
uint16_t status = RtlRead16(r, RTL_REG_INTR_STAT);
|
||||
status &= RTL_INTR_ENABLES;
|
||||
if (!status || status == 0xFFFFu)
|
||||
continue;
|
||||
|
||||
RtlWrite16(r, RTL_REG_INTR_STAT, status);
|
||||
r->PendingIsr |= status;
|
||||
KeInsertQueueDpc(&r->Dpc, (void*)0, (void*)0);
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the rtl Send Frame operation.
|
||||
static KSTATUS RtlSendFrame(NET_DEVICE* device, const void* frame, size_t length) {
|
||||
if (!device || !frame)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
@@ -402,7 +331,6 @@ static KSTATUS RtlSendFrame(NET_DEVICE* device, const void* frame, size_t length
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
// Implements the rtl Select Register Bar operation.
|
||||
static KSTATUS RtlSelectRegisterBar(RTL816X_DEVICE* r) {
|
||||
if (!r || !r->Pdo)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
@@ -468,42 +396,15 @@ static KSTATUS RtlSelectRegisterBar(RTL816X_DEVICE* r) {
|
||||
return NTLSTATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
// Configures a dedicated MSI vector and falls back to a routed INTx line.
|
||||
// Connects a PCI message interrupt or a routed INTx source.
|
||||
static KSTATUS RtlConfigureInterrupt(RTL816X_DEVICE* r) {
|
||||
if (!r || !r->Pdo)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
|
||||
r->Irq = 0xFFu;
|
||||
r->UsingMsi = false;
|
||||
|
||||
KSTATUS msiStatus = PciEnableMsiAuto(r->Pdo, &r->Irq);
|
||||
if (KSUCCESS(msiStatus)) {
|
||||
r->UsingMsi = true;
|
||||
DbgPrint("RTL816X: using MSI IRQ slot %u\n", r->Irq);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
DbgPrint("RTL816X: MSI setup failed status=0x%x; attempting explicit INTx fallback\n",
|
||||
msiStatus);
|
||||
|
||||
KSTATUS intxStatus = PciGetInterrupt(r->Pdo, &r->Irq);
|
||||
if (!KSUCCESS(intxStatus))
|
||||
return intxStatus;
|
||||
if (r->Irq == 0xFFu || r->Irq >= 24u)
|
||||
return NTLSTATUS_NOT_SUPPORTED;
|
||||
|
||||
intxStatus = PciEnableDevice(r->Pdo,
|
||||
PCI_ENABLE_BUSMASTER |
|
||||
PCI_ENABLE_INTX |
|
||||
(r->UseMmio ? PCI_ENABLE_MEMORY : PCI_ENABLE_IO));
|
||||
if (!KSUCCESS(intxStatus))
|
||||
return intxStatus;
|
||||
|
||||
DbgPrint("RTL816X: using legacy INTx IRQ %u\n", r->Irq);
|
||||
return NTLSTATUS_SUCCESS;
|
||||
r->InterruptRequest.Routine = RtlIsr;
|
||||
r->InterruptRequest.Context = r;
|
||||
r->InterruptRequest.Affinity = 0;
|
||||
r->InterruptRequest.Interrupt = (KE_INTERRUPT*)0;
|
||||
return PciConnectInterrupts(r->Pdo, &r->InterruptRequest, 1u, &r->UsingMsi);
|
||||
}
|
||||
|
||||
// Implements the rtl Start Device operation.
|
||||
static KSTATUS RtlStartDevice(RTL816X_DEVICE* r) {
|
||||
if (!r || r->Magic != RTL816X_DEVICE_MAGIC || !r->Pdo || !r->Fdo)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
@@ -547,18 +448,7 @@ static KSTATUS RtlStartDevice(RTL816X_DEVICE* r) {
|
||||
return st;
|
||||
}
|
||||
|
||||
st = RtlConfigureInterrupt(r);
|
||||
if (!KSUCCESS(st)) {
|
||||
DbgPrint("RTL816X: no usable MSI or INTx interrupt status=0x%x\n", st);
|
||||
return st;
|
||||
}
|
||||
|
||||
RtlReadMac(r);
|
||||
DbgPrint("RTL816X: MAC %02x:%02x:%02x:%02x:%02x:%02x irq=%u mode=%s\n",
|
||||
r->NetDevice.HardwareAddress[0], r->NetDevice.HardwareAddress[1],
|
||||
r->NetDevice.HardwareAddress[2], r->NetDevice.HardwareAddress[3],
|
||||
r->NetDevice.HardwareAddress[4], r->NetDevice.HardwareAddress[5],
|
||||
r->Irq, r->UsingMsi ? "MSI" : "INTx");
|
||||
|
||||
st = RtlAllocateDma(r);
|
||||
if (!KSUCCESS(st))
|
||||
@@ -571,13 +461,21 @@ static KSTATUS RtlStartDevice(RTL816X_DEVICE* r) {
|
||||
r->NetDevice.DriverContext = r;
|
||||
r->NetDevice.SendFrame = RtlSendFrame;
|
||||
|
||||
st = RtlRegisterDevice(r);
|
||||
st = RtlConfigureInterrupt(r);
|
||||
if (!KSUCCESS(st)) {
|
||||
DbgPrint("RTL816X: no usable MSI or INTx interrupt status=0x%x\n", st);
|
||||
RtlReleaseDma(r);
|
||||
return st;
|
||||
}
|
||||
|
||||
KeIrqRegister(r->Irq, RtlIsr);
|
||||
KE_INTERRUPT_INFO route;
|
||||
if (KSUCCESS(KeInterruptQuery(r->InterruptRequest.Interrupt, &route)))
|
||||
DbgPrint("RTL816X: MAC %02x:%02x:%02x:%02x:%02x:%02x cpu=%u vector=0x%02x mode=%s\n",
|
||||
r->NetDevice.HardwareAddress[0], r->NetDevice.HardwareAddress[1],
|
||||
r->NetDevice.HardwareAddress[2], r->NetDevice.HardwareAddress[3],
|
||||
r->NetDevice.HardwareAddress[4], r->NetDevice.HardwareAddress[5],
|
||||
route.CpuIndex, route.Vector, r->UsingMsi ? "MSI/MSI-X" : "INTx");
|
||||
|
||||
r->Started = true;
|
||||
RtlProgramHardware(r);
|
||||
r->Fdo->PnpState = DevicePnpStarted;
|
||||
@@ -585,13 +483,14 @@ static KSTATUS RtlStartDevice(RTL816X_DEVICE* r) {
|
||||
st = NetRegisterDevice(&r->NetDevice);
|
||||
if (!KSUCCESS(st)) {
|
||||
RtlStopDma(r);
|
||||
RtlUnregisterDevice(r);
|
||||
if (r->InterruptRequest.Interrupt)
|
||||
PciDisconnectInterrupts(r->Pdo, &r->InterruptRequest, 1u);
|
||||
RtlReleaseDma(r);
|
||||
return st;
|
||||
}
|
||||
|
||||
DbgPrint("RTL816X: initialized; RX/TX enabled on %s IRQ %u\n",
|
||||
r->UsingMsi ? "MSI" : "INTx", r->Irq);
|
||||
DbgPrint("RTL816X: initialized; RX/TX enabled via %s\n",
|
||||
r->UsingMsi ? "MSI/MSI-X" : "INTx");
|
||||
return NTLSTATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -626,7 +525,8 @@ KSTATUS Rtl816xDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
||||
r->Removed = true;
|
||||
device->PnpState = DevicePnpDeleted;
|
||||
RtlStopDma(r);
|
||||
RtlUnregisterDevice(r);
|
||||
if (r->InterruptRequest.Interrupt)
|
||||
PciDisconnectInterrupts(r->Pdo, &r->InterruptRequest, 1u);
|
||||
RtlReleaseDma(r);
|
||||
IoDetachDevice(device);
|
||||
IoDeleteDevice(device);
|
||||
@@ -637,7 +537,6 @@ KSTATUS Rtl816xDispatchPnp(DEVICE_OBJECT* device, IRP* irp) {
|
||||
}
|
||||
}
|
||||
|
||||
// Implements the add Device operation.
|
||||
KSTATUS Rtl816xAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) {
|
||||
if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical)
|
||||
return NTLSTATUS_INVALID_PARAMETER;
|
||||
@@ -653,7 +552,7 @@ KSTATUS Rtl816xAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObj
|
||||
r->Magic = RTL816X_DEVICE_MAGIC;
|
||||
r->Fdo = fdo;
|
||||
r->Pdo = physicalDeviceObject;
|
||||
r->Irq = 0xFFu;
|
||||
r->PciInfo.InterruptLine = 0xFFu;
|
||||
r->TxLock = (SPINLOCK)SPINLOCK_INIT;
|
||||
|
||||
r->LowerDevice = IoAttachDeviceToDeviceStack(fdo, physicalDeviceObject);
|
||||
@@ -671,8 +570,6 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) {
|
||||
|
||||
DbgPrint("RTL816X: driver loading...\n");
|
||||
|
||||
gRtl816xDeviceCount = 0;
|
||||
|
||||
memset(&gRtl816xDriver, 0, sizeof(gRtl816xDriver));
|
||||
IoInitializeDriverObject(&gRtl816xDriver, SYS_SV_LITERAL("rtl816x"));
|
||||
gRtl816xDriver.IdTable = &gRtl816xIdTable;
|
||||
|
||||
@@ -116,7 +116,7 @@ typedef struct RTL816X_DEVICE {
|
||||
PCI_DEVICE_INFO PciInfo;
|
||||
PCI_BAR RegisterBar;
|
||||
uint64_t RegisterBytes;
|
||||
uint8_t Irq;
|
||||
PCI_INTERRUPT_REQUEST InterruptRequest;
|
||||
bool UsingMsi;
|
||||
|
||||
bool Started;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
TARGETNAME=rtl816x
|
||||
TARGETPATH=obj
|
||||
TARGETTYPE=DRIVER
|
||||
FLAVOR=DRIVER
|
||||
TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\pci.lib"
|
||||
EXTRA_LFLAGS=/NOENTRY
|
||||
SOURCES=@/code/drivers/net/rtl816x/rtl816x.c
|
||||
Reference in new issue
Block a user