MODULES += Storage/FDDv2
MODULES += Network/NE2000 Network/RTL8139
MODULES += Network/VIARhineII
+MODULES += Network/PCnetFAST3
MODULES += Network/E1000
MODULES += Display/VESA
MODULES += Display/BochsGA
ACPI_STATUS AcpiOsPurgeCache(ACPI_CACHE_T *Cache)
{
- if( Cache == NULL )
+ ENTER("pCache", Cache);
+ if( Cache == NULL ) {
+ LEAVE('i', AE_BAD_PARAMETER);
return AE_BAD_PARAMETER;
+ }
memset(Cache->ObjectStates, 0, sizeof(char)*Cache->nObj);
+ LEAVE('i', AE_OK);
return AE_OK;
}
}
}
- Log_Debug("ACPICA", "AcpiOsAcquireObject: %i objects used in cache '%s'", Cache->nObj, Cache->Name);
+ Log_Debug("ACPICA", "AcpiOsAcquireObject: All %i objects used in '%s'",
+ Cache->nObj, Cache->Name);
LEAVE('n');
return NULL;
{
if( Cache == NULL || Object == NULL )
return AE_BAD_PARAMETER;
+ ENTER("pCache pObject", Cache, Object);
tVAddr delta = (tVAddr)Object - (tVAddr)Cache->First;
delta /= Cache->ObjectSize;
Cache->ObjectStates[delta] = 0;
+ LEAVE('i', AE_OK);
return AE_OK;
}
int Multiboot_LoadMemoryMap(tMBoot_Info *MBInfo, tVAddr MapOffset, tPMemMapEnt *Map, const int MapSize, tPAddr KStart, tPAddr KEnd)
{
int nPMemMapEnts = 0;
- tMBoot_MMapEnt *ent = (void*)((tVAddr)MBInfo->MMapAddr + MapOffset);
- tMBoot_MMapEnt *last = (void*)((tVAddr)ent + MBInfo->MMapLength);
ENTER("pMBInfo pMapOffset pMap iMapSize PKStart PKEnd",
MBInfo, MapOffset, Map, MapSize, KStart, KEnd);
// Check that the memory map is present
if( MBInfo->Flags & (1 << 6) )
{
+ tMBoot_MMapEnt *ent = (void*)((tVAddr)MBInfo->MMapAddr + MapOffset);
+ tMBoot_MMapEnt *last = (void*)((tVAddr)ent + MBInfo->MMapLength);
// Build up memory map
nPMemMapEnts = 0;
while( ent < last && nPMemMapEnts < MapSize )
nPMemMapEnts ++;
ent = (void*)( (tVAddr)ent + ent->Size + 4 );
}
+ if( ent < last )
+ {
+ Log_Warning("MBoot", "Memory map has >%i entries, internal version is truncated",
+ MapSize);
+ }
}
else if( MBInfo->Flags & (1 << 0) )
{
Log_Warning("MBoot", "No memory map passed, using mem_lower and mem_upper");
+ ASSERT(MapSize >= 2);
nPMemMapEnts = 2;
Map[0].Start = 0;
Map[0].Length = MBInfo->LowMem * 1024;
MaxBits = PHYS_BITS;
// Sanity Check
- if(MaxBits < 12 || !PhysAddr) {
+ if(MaxBits < 12) {
LEAVE('i', 0);
return 0;
}
if(Pages == 1 && MaxBits >= PHYS_BITS)
{
phys = MM_AllocPhys();
+ if( PhysAddr )
+ *PhysAddr = phys;
if( !phys ) {
- *PhysAddr = 0;
LEAVE_RET('i', 0);
}
- *PhysAddr = phys;
ret = MM_MapHWPages(phys, 1);
if(ret == 0) {
MM_DerefPhys(phys);
return 0;
}
- *PhysAddr = phys;
+ if( PhysAddr )
+ *PhysAddr = phys;
LEAVE('x', ret);
return ret;
}
// Checksum offloading
#define ADAPTERFLAG_OFFLOAD_MAC (1 << 0)
#define ADAPTERFLAG_OFFLOAD_IP4 (1 << 1)
-#define ADAPTERFLAG_OFFLOAD_IP6 (1 << 2)
+#define ADAPTERFLAG_OFFLOAD_80211q (1 << 2)
#define ADAPTERFLAG_OFFLOAD_TCP (1 << 3)
#define ADAPTERFLAG_OFFLOAD_UDP (1 << 4)
void Link_SendPacket(tAdapter *Adapter, Uint16 Type, tMacAddr To, tIPStackBuffer *Buffer)
{
int length = IPStack_Buffer_GetLength(Buffer);
- int ofs = 4 - (length & 3);
+ int ofs = (4 - (length & 3)) & 3;
Uint8 buf[sizeof(tEthernetHeader) + ofs + 4];
+ Uint32 *checksum = (void*)(buf + sizeof(tEthernetHeader) + ofs);
tEthernetHeader *hdr = (void*)buf;
- if( ofs == 4 ) ofs = 0;
-
Log_Log("Net Link", "Sending %i bytes to %02x:%02x:%02x:%02x:%02x:%02x (Type 0x%x)",
length, To.B[0], To.B[1], To.B[2], To.B[3], To.B[4], To.B[5], Type);
hdr->Dest = To;
memcpy(&hdr->Src, Adapter->HWAddr, 6); // TODO: Remove hard coded 6
hdr->Type = htons(Type);
- *(Uint32*)(buf + sizeof(tEthernetHeader) + ofs) = 0;
+ memset(hdr, 0, ofs+4); // zero padding and checksum
- IPStack_Buffer_AppendSubBuffer(Buffer, sizeof(tEthernetHeader), ofs + 4, hdr, NULL, NULL);
-
- *(Uint32*)(buf + sizeof(tEthernetHeader) + ofs) = htonl( Link_CalculateCRC(Buffer) );
+ if( (Adapter->Type->Flags & ADAPTERFLAG_OFFLOAD_MAC) )
+ IPStack_Buffer_AppendSubBuffer(Buffer, sizeof(tEthernetHeader), ofs, hdr, NULL, NULL);
+ else
+ {
+ IPStack_Buffer_AppendSubBuffer(Buffer, sizeof(tEthernetHeader), ofs + 4, hdr, NULL, NULL);
+ *checksum = htonl( Link_CalculateCRC(Buffer) );
+ Log_Debug("Net Link", "Non-Offloaded: 0x%x, 0x%x", *checksum, ntohl(*checksum));
+ }
Log_Log("Net Link", " from %02x:%02x:%02x:%02x:%02x:%02x",
hdr->Src.B[0], hdr->Src.B[1], hdr->Src.B[2],
* - By John Hodge (thePowersGang)
*
* e1000.c
- * - Intel E1000 Network Card Driver (core)
+ * - Intel 8254x Network Card Driver (core)
*/
#define DEBUG 1
#define VERSION VER2(0,1)
#include <modules.h>
#include <drv_pci.h>
#include <IPStack/include/adapters_api.h>
+#include <timers.h> // Time_Delay
+
+const struct sSupportedCard {
+ Uint16 Vendor, Device;
+} caSupportedCards[] = {
+ {0x8086, 0x100E}, // 82540EM-A Desktop
+ {0x8086, 0x1010}, // 82546EB-A1 Copper Dual Port
+ {0x8086, 0x1012}, // 82546EB-A1 Fiber
+ {0x8086, 0x1019}, // 82547[EG]I Copper
+ {0x8086, 0x101A}, // 82547EI Mobile
+ {0x8086, 0x101D}, // 82546EB-A1 Copper Quad Port
+};
+const int ciNumSupportedCards = sizeof(caSupportedCards)/sizeof(caSupportedCards[0]);
// === PROTOTYPES ===
int E1000_Install(char **Arguments);
tIPStackBuffer *E1000_WaitForPacket(void *Ptr);
int E1000_SendPacket(void *Ptr, tIPStackBuffer *Buffer);
void E1000_IRQHandler(int Num, void *Ptr);
+ int E1000_int_InitialiseCard(tCard *Card);
+Uint16 E1000_int_ReadEEPROM(tCard *Card, Uint8 WordIdx);
// === GLOBALS ===
MODULE_DEFINE(0, VERSION, E1000, E1000_Install, E1000_Cleanup, NULL);
tIPStack_AdapterType gE1000_AdapterType = {
.Name = "E1000",
- .Type = 0, // TODO: Differentiate differnet wire protos and speeds
- .Flags = 0, // TODO: IP checksum offloading, MAC checksum offloading etc
+ .Type = ADAPTERTYPE_ETHERNET_1G, // TODO: Differentiate differnet wire protos and speeds
+ .Flags = ADAPTERFLAG_OFFLOAD_MAC, // TODO: IP/TCP/UDP checksum offloading
.SendPacket = E1000_SendPacket,
.WaitForPacket = E1000_WaitForPacket
};
+tCard *gaE1000_Cards;
// === CODE ===
int E1000_Install(char **Arguments)
{
- for( int id = -1; (id = PCI_GetDevice(0x8086, 0x100E, id)) != -1; )
+ int card_count = 0;
+ for( int modelidx = 0; modelidx < ciNumSupportedCards; modelidx ++ )
{
-
+ const struct sSupportedCard *cardtype = &caSupportedCards[modelidx];
+ card_count += PCI_CountDevices(cardtype->Vendor, cardtype->Device);
+ }
+ LOG("card_count = %i", card_count);
+ if( card_count == 0 ) {
+ LOG("Zero cards located");
+ return MODULE_ERR_NOTNEEDED;
+ }
+
+ // Allocate card array
+ gaE1000_Cards = calloc(sizeof(tCard), card_count);
+ if( !gaE1000_Cards ) {
+ return MODULE_ERR_MALLOC;
+ }
+
+ // Initialise cards
+ int card_idx = 0;
+ for( int modelidx = 0; modelidx < ciNumSupportedCards; modelidx ++ )
+ {
+ const struct sSupportedCard *cardtype = &caSupportedCards[modelidx];
+ for( int id = -1, i = 0; (id = PCI_GetDevice(cardtype->Vendor, cardtype->Device, i)) != -1; i ++ )
+ {
+ tCard *card = &gaE1000_Cards[card_idx++];
+ Uint32 mmiobase = PCI_GetBAR(id, 0);
+ if( mmiobase & (1|8) ) {
+ Log_Warning("E1000", "Dev %i: BAR0 should be non-prefetchable memory", id);
+ continue;
+ }
+ const int addrsize = (mmiobase>>1) & 3;
+ if( addrsize == 0 ) {
+ // Standard 32-bit
+ card->MMIOBasePhys = mmiobase & ~0xF;
+ }
+ else if( addrsize == 2 ) {
+ // 64-bit
+ card->MMIOBasePhys = (mmiobase & ~0xF) | ((Uint64)PCI_GetBAR(id, 1)<<32);
+ }
+ else {
+ Log_Warning("E1000", "Dev %i: Unknown memory address size %i", id, (mmiobase>>1)&3);
+ continue;
+ }
+
+ card->IRQ = PCI_GetIRQ(id);
+ IRQ_AddHandler(card->IRQ, E1000_IRQHandler, card);
+
+ Log_Debug("E1000", "Card %i: %P IRQ %i", card_idx, card->MMIOBasePhys, card->IRQ);
+
+ if( E1000_int_InitialiseCard(card) ) {
+ return MODULE_ERR_MALLOC;
+ }
+
+ card->IPStackHandle = IPStack_Adapter_Add(&gE1000_AdapterType, card, card->MacAddr);
+ }
}
- return MODULE_ERR_NOTNEEDED;
+ return MODULE_ERR_OK;
}
int E1000_Cleanup(void)
return 0;
}
+void E1000_int_ReleaseRXD(void *Arg, size_t HeadLen, size_t FootLen, const void *Data)
+{
+ tCard **cardptr = Arg;
+ tCard *Card = *cardptr;
+ int rxd = (Arg - (void*)Card->RXDescs) / sizeof(tRXDesc);
+
+ Card->RXDescs[rxd].Status = 0;
+ Mutex_Acquire(&Card->lRXDescs);
+ if( rxd == REG32(Card, REG_RDT) ) {
+ while( rxd != Card->FirstUnseenRXD && !(Card->RXDescs[rxd].Status & RXD_STS_DD) ) {
+ rxd ++;
+ if( rxd == NUM_RX_DESC )
+ rxd = 0;
+ }
+ REG32(Card, REG_RDT) = rxd;
+ LOG("Updated RDT=%i", rxd);
+ }
+ Mutex_Release(&Card->lRXDescs);
+}
+
tIPStackBuffer *E1000_WaitForPacket(void *Ptr)
{
- return NULL;
+ tCard *Card = Ptr;
+
+ if( Semaphore_Wait(&Card->AvailPackets, 1) != 1 )
+ return NULL;
+
+ ENTER("pPtr", Ptr);
+
+ Mutex_Acquire(&Card->lRXDescs);
+ int first_rxd = Card->FirstUnseenRXD;
+ int last_rxd = first_rxd;
+ int nDesc = 1;
+ while( last_rxd != Card->LastUnseenRXD ) {
+ if( !(Card->RXDescs[last_rxd].Status & RXD_STS_DD) )
+ break; // Oops, should ahve found an EOP first
+ if( Card->RXDescs[last_rxd].Status & RXD_STS_EOP )
+ break;
+ nDesc ++;
+ last_rxd = (last_rxd + 1) % NUM_RX_DESC;
+ }
+ Card->FirstUnseenRXD = (last_rxd + 1) % NUM_RX_DESC;
+ Mutex_Release(&Card->lRXDescs);
+
+ LOG("nDesc = %i, first_rxd = %i", nDesc, first_rxd);
+ tIPStackBuffer *ret = IPStack_Buffer_CreateBuffer(nDesc);
+ int rxd = first_rxd;
+ for( int i = 0; i < nDesc; i ++ )
+ {
+ IPStack_Buffer_AppendSubBuffer(ret, 0, Card->RXDescs[rxd].Length, Card->RXBuffers[rxd],
+ E1000_int_ReleaseRXD, &Card->RXBackHandles[rxd]);
+ }
+
+ LEAVE('p', ret);
+ return ret;
}
int E1000_SendPacket(void *Ptr, tIPStackBuffer *Buffer)
{
- return -1;
+ tCard *Card = Ptr;
+
+ ENTER("pPtr pBuffer", Ptr, Buffer);
+
+ int nDesc = 0;
+ size_t len;
+ const void *ptr;
+ // Count sub-buffers (including splitting cross-page entries)
+ int idx = -1;
+ while( (idx = IPStack_Buffer_GetBuffer(Buffer, idx, &len, &ptr)) != -1 )
+ {
+ if( len > PAGE_SIZE ) {
+ LOG("len=%i > PAGE_SIZE", len);
+ LEAVE('i', EINVAL);
+ return EINVAL;
+ }
+ if( MM_GetPhysAddr(ptr) + len-1 != MM_GetPhysAddr((char*)ptr + len-1) ) {
+ LOG("Buffer %p+%i spans non-contig physical pages", ptr, len);
+ nDesc ++;
+ }
+ nDesc ++;
+ }
+
+ // Request set of TX descriptors
+ int rv = Semaphore_Wait(&Card->FreeTxDescs, nDesc);
+ if(rv != nDesc) {
+ LEAVE('i', EINTR);
+ return EINTR;
+ }
+ Mutex_Acquire(&Card->lTXDescs);
+ int first_txd = Card->FirstFreeTXD;
+ Card->FirstFreeTXD = (first_txd + nDesc) % NUM_TX_DESC;
+ int last_txd = (first_txd + nDesc-1) % NUM_TX_DESC;
+
+ LOG("first_txd = %i, last_txd = %i", first_txd, last_txd);
+
+ // Populate buffers
+ idx = -1;
+ int txd = first_txd;
+ while( (idx = IPStack_Buffer_GetBuffer(Buffer, idx, &len, &ptr)) != -1 )
+ {
+ if( MM_GetPhysAddr(ptr) + len-1 != MM_GetPhysAddr((char*)ptr + len-1) )
+ {
+ size_t remlen = PAGE_SIZE - ((tVAddr)ptr & (PAGE_SIZE-1));
+ // Split in two
+ // - First Page
+ Card->TXDescs[txd].Buffer = MM_GetPhysAddr(ptr);
+ Card->TXDescs[txd].Length = remlen;
+ Card->TXDescs[txd].CMD = TXD_CMD_RS;
+ txd = (txd + 1) % NUM_TX_DESC;
+ // - Second page
+ Card->TXDescs[txd].Buffer = MM_GetPhysAddr((char*)ptr + remlen);
+ Card->TXDescs[txd].Length = len - remlen;
+ Card->TXDescs[txd].CMD = TXD_CMD_RS;
+ }
+ else
+ {
+ // Single
+ Card->TXDescs[txd].Buffer = MM_GetPhysAddr(ptr);
+ Card->TXDescs[txd].Length = len;
+ Card->TXDescs[txd].CMD = TXD_CMD_RS;
+ }
+ txd = (txd + 1) % NUM_TX_DESC;
+ }
+ Card->TXDescs[last_txd].CMD |= TXD_CMD_EOP|TXD_CMD_IDE|TXD_CMD_IFCS;
+ Card->TXSrcBuffers[last_txd] = Buffer;
+
+ // Trigger TX
+ IPStack_Buffer_LockBuffer(Buffer);
+ REG32(Card, REG_TDT) = Card->FirstFreeTXD;
+ Mutex_Release(&Card->lTXDescs);
+ LOG("Waiting for TX");
+
+ // Wait for completion (lock will block, then release straight away)
+ IPStack_Buffer_LockBuffer(Buffer);
+ IPStack_Buffer_UnlockBuffer(Buffer);
+
+ // TODO: Check status bits
+
+ LEAVE('i', 0);
+ return 0;
}
void E1000_IRQHandler(int Num, void *Ptr)
{
+ tCard *Card = Ptr;
+
+ Uint32 icr = REG32(Card, REG_ICR);
+ if( icr == 0 )
+ return ;
+ LOG("icr = %x", icr);
+
+ // Transmit descriptor written
+ if( (icr & ICR_TXDW) || (icr & ICR_TXQE) )
+ {
+ int nReleased = 0;
+ // Walk descriptors looking for the first non-complete descriptor
+ LOG("TX %i:%i", Card->LastFreeTXD, Card->FirstFreeTXD);
+ while( Card->LastFreeTXD != Card->FirstFreeTXD && (Card->TXDescs[Card->LastFreeTXD].Status & TXD_STS_DD) )
+ {
+ nReleased ++;
+ if( Card->TXSrcBuffers[Card->LastFreeTXD] ) {
+ IPStack_Buffer_UnlockBuffer( Card->TXSrcBuffers[Card->LastFreeTXD] );
+ Card->TXSrcBuffers[Card->LastFreeTXD] = NULL;
+ }
+ Card->LastFreeTXD ++;
+ if(Card->LastFreeTXD == NUM_TX_DESC)
+ Card->LastFreeTXD = 0;
+ }
+ Semaphore_Signal(&Card->FreeTxDescs, nReleased);
+ LOG("nReleased = %i", nReleased);
+ }
+
+ if( icr & ICR_LSC )
+ {
+ // Link status change
+ LOG("LSC");
+ // TODO: Detect link drop/raise and poke IPStack
+ }
+
+ // Pending packet (s)
+ if( icr & ICR_RXT0 )
+ {
+ int nPackets = 0;
+ LOG("RX %i:%i", Card->LastUnseenRXD, Card->FirstUnseenRXD);
+ while( (Card->RXDescs[Card->LastUnseenRXD].Status & RXD_STS_DD) )
+ {
+ if( Card->RXDescs[Card->LastUnseenRXD].Status & RXD_STS_EOP )
+ nPackets ++;
+ Card->LastUnseenRXD ++;
+ if( Card->LastUnseenRXD == NUM_RX_DESC )
+ Card->LastUnseenRXD = 0;
+
+ if( Card->LastUnseenRXD == Card->FirstUnseenRXD )
+ break;
+ }
+ Semaphore_Signal(&Card->AvailPackets, nPackets);
+ LOG("nPackets = %i", nPackets);
+ }
+
+ icr &= ~(ICR_RXT0|ICR_LSC|ICR_TXQE|ICR_TXDW);
+ if( icr )
+ Log_Warning("E1000", "Unhandled ICR bits 0x%x", icr);
+}
+
+// TODO: Move this function into Kernel/drvutil.c
+/**
+ * \brief Allocate a set of buffers in hardware mapped space
+ *
+ * Allocates \a NumBufs buffers using shared pages (if \a BufSize is less than a page) or
+ * as a set of contiugious allocations.
+ */
+int DrvUtil_AllocBuffers(void **Buffers, int NumBufs, int PhysBits, size_t BufSize)
+{
+ if( BufSize >= PAGE_SIZE )
+ {
+ const int pages_per_buf = BufSize / PAGE_SIZE;
+ ASSERT(pages_per_buf * PAGE_SIZE == BufSize);
+ for( int i = 0; i < NumBufs; i ++ ) {
+ Buffers[i] = (void*)MM_AllocDMA(pages_per_buf, PhysBits, NULL);
+ if( !Buffers[i] ) return 1;
+ }
+ }
+ else
+ {
+ size_t ofs = 0;
+ const int bufs_per_page = PAGE_SIZE / BufSize;
+ ASSERT(bufs_per_page * BufSize == PAGE_SIZE);
+ void *page;
+ for( int i = 0; i < NumBufs; i ++ )
+ {
+ if( ofs == 0 ) {
+ page = (void*)MM_AllocDMA(1, PhysBits, NULL);
+ if( !page ) return 1;
+ }
+ Buffers[i] = (char*)page + ofs;
+ ofs += BufSize;
+ if( ofs >= PAGE_SIZE )
+ ofs = 0;
+ }
+ }
+ return 0;
+}
+
+int E1000_int_InitialiseCard(tCard *Card)
+{
+ ENTER("pCard", Card);
+
+ // Map required structures
+ Card->MMIOBase = (void*)MM_MapHWPages( Card->MMIOBasePhys, 7 );
+ if( !Card->MMIOBase ) {
+ Log_Error("E1000", "%p: Failed to map MMIO Space (7 pages)", Card);
+ LEAVE('i', 1);
+ return 1;
+ }
+
+ // --- Read MAC address from EEPROM ---
+ {
+ Uint16 macword;
+ macword = E1000_int_ReadEEPROM(Card, 0);
+ Card->MacAddr[0] = macword & 0xFF;
+ Card->MacAddr[1] = macword >> 8;
+ macword = E1000_int_ReadEEPROM(Card, 1);
+ Card->MacAddr[2] = macword & 0xFF;
+ Card->MacAddr[3] = macword >> 8;
+ macword = E1000_int_ReadEEPROM(Card, 2);
+ Card->MacAddr[4] = macword & 0xFF;
+ Card->MacAddr[5] = macword >> 8;
+ }
+ Log_Log("E1000", "%p: MAC Address %02x:%02x:%02x:%02x:%02x:%02x",
+ Card,
+ Card->MacAddr[0], Card->MacAddr[1],
+ Card->MacAddr[2], Card->MacAddr[3],
+ Card->MacAddr[4], Card->MacAddr[5]);
+
+ // --- Prepare for RX ---
+ LOG("RX Preparation");
+ Card->RXDescs = (void*)MM_AllocDMA(1, 64, NULL);
+ if( !Card->RXDescs ) {
+ LEAVE('i', 2);
+ return 2;
+ }
+ if( DrvUtil_AllocBuffers(Card->RXBuffers, NUM_RX_DESC, 64, RX_DESC_BSIZE) ) {
+ LEAVE('i', 3);
+ return 3;
+ }
+ for( int i = 0; i < NUM_RX_DESC; i ++ )
+ {
+ Card->RXDescs[i].Buffer = MM_GetPhysAddr(Card->RXBuffers[i]);
+ Card->RXDescs[i].Status = 0; // Clear RXD_STS_DD, gives it to the card
+ Card->RXBackHandles[i] = Card;
+ }
+
+ REG64(Card, REG_RDBAL) = MM_GetPhysAddr((void*)Card->RXDescs);
+ REG32(Card, REG_RDLEN) = NUM_RX_DESC * 16;
+ REG32(Card, REG_RDH) = 0;
+ REG32(Card, REG_RDT) = NUM_RX_DESC;
+ // Hardware size, Multicast promisc, Accept broadcast, Interrupt at 1/4 Rx descs free
+ REG32(Card, REG_RCTL) = RX_DESC_BSIZEHW | RCTL_MPE | RCTL_BAM | RCTL_RDMTS_1_4;
+ Card->FirstUnseenRXD = 0;
+ Card->LastUnseenRXD = 0;
+
+ // --- Prepare for TX ---
+ LOG("TX Preparation");
+ Card->TXDescs = (void*)MM_AllocDMA(1, 64, NULL);
+ if( !Card->RXDescs ) {
+ LEAVE('i', 4);
+ return 4;
+ }
+ for( int i = 0; i < NUM_TX_DESC; i ++ )
+ {
+ Card->TXDescs[i].Buffer = 0;
+ Card->TXDescs[i].CMD = 0;
+ }
+ REG64(Card, REG_TDBAL) = MM_GetPhysAddr((void*)Card->TXDescs);
+ REG32(Card, REG_TDLEN) = NUM_TX_DESC * 16;
+ REG32(Card, REG_TDH) = 0;
+ REG32(Card, REG_TDT) = 0;
+ // Enable, pad short packets
+ REG32(Card, REG_TCTL) = TCTL_EN | TCTL_PSP | (0x0F << TCTL_CT_ofs) | (0x40 << TCTL_COLD_ofs);
+ Card->FirstFreeTXD = 0;
+
+ // -- Prepare Semaphores
+ Semaphore_Init(&Card->FreeTxDescs, NUM_TX_DESC, NUM_TX_DESC, "E1000", "TXDescs");
+ Semaphore_Init(&Card->AvailPackets, 0, NUM_RX_DESC, "E1000", "RXDescs");
+
+ // --- Prepare for full operation ---
+ LOG("Starting card");
+ REG32(Card, REG_CTRL) = CTRL_SLU|CTRL_ASDE; // Link up, auto speed detection
+ REG32(Card, REG_IMS) = 0x1F6DC; // Interrupt mask
+ (void)REG32(Card, REG_ICR); // Discard pending interrupts
+ REG32(Card, REG_RCTL) |= RCTL_EN;
+ LEAVE('i', 0);
+ return 0;
+}
+
+Uint16 E1000_int_ReadEEPROM(tCard *Card, Uint8 WordIdx)
+{
+ REG32(Card, REG_EERD) = ((Uint32)WordIdx << 8) | 1;
+ Uint32 tmp;
+ while( !((tmp = REG32(Card, REG_EERD)) & (1 << 4)) ) {
+ // TODO: use something like Time_MicroDelay instead
+ Time_Delay(1);
+ }
+
+ return tmp >> 16;
}
#ifndef _E1000_H_
#define _E1000_H_
+#include "e1000_hw.h"
+
+#include <semaphore.h>
+#include <mutex.h>
+#include <IPStack/include/buffer.h>
+
+#define NUM_TX_DESC (PAGE_SIZE/sizeof(struct sTXDesc))
+#define NUM_RX_DESC (PAGE_SIZE/sizeof(struct sRXDesc))
+
+#define RX_DESC_BSIZE 4096
+#define RX_DESC_BSIZEHW RCTL_BSIZE_4096
+
+typedef struct sCard
+{
+ tPAddr MMIOBasePhys;
+ int IRQ;
+ Uint16 IOBase;
+ volatile void *MMIOBase;
+
+ tMutex lRXDescs;
+ int FirstUnseenRXD;
+ int LastUnseenRXD;
+ void *RXBuffers[NUM_RX_DESC];
+ volatile tRXDesc *RXDescs;
+ tSemaphore AvailPackets;
+ struct sCard *RXBackHandles[NUM_RX_DESC]; // Pointers to this struct, offset used to select desc
+
+ tMutex lTXDescs;
+ int FirstFreeTXD;
+ int LastFreeTXD;
+ volatile tTXDesc *TXDescs;
+ tSemaphore FreeTxDescs;
+
+ tIPStackBuffer *TXSrcBuffers[NUM_TX_DESC];
+
+ Uint8 MacAddr[6];
+
+ void *IPStackHandle;
+} tCard;
#endif
--- /dev/null
+/*
+ * Acess2 E1000 Network Driver
+ * - By John Hodge (thePowersGang)
+ *
+ * e1000_hw.h
+ * - Hardware Definitions
+ */
+#ifndef _E1000_HW_H_
+#define _E1000_HW_H_
+
+typedef struct sRXDesc tRXDesc;
+typedef struct sTXDesc tTXDesc;
+
+#define RXD_STS_PIF (1<<7) // Passed inexact filter (multicast, probably)
+#define RXD_STS_IPCS (1<<6) // IP Checksum was calculated
+#define RXD_STS_TCPCS (1<<5) // TCP Checksum was calculated
+#define RXD_STS_RSV (1<<4) // reserved
+#define RXD_STS_VP (1<<3) // Packet was 802.1q tagged
+#define RXD_STS_IXSM (1<<2) // Ignore IPCS/TCPS
+#define RXD_STS_EOP (1<<1) // Last descriptor in apcket
+#define RXD_STS_DD (1<<0) // Descriptor Done, buffer data is now valid
+
+#define RXD_ERR_RXE (1<<7) // RX Error
+#define RXD_ERR_IPE (1<<6) // IP Checksum Error
+#define RXD_ERR_TCPE (1<<5) // TCP/UDP Checksum Error
+#define RXD_ERR_CXE (1<<4) // Carrier Extension Error (GMII cards [82544GC/EI] only)
+#define RXD_ERR_SEQ (1<<2) // Sequence Error (aka Framing Error)
+#define RXD_ERR_SE (1<<1) // Symbol error (TBI mode)
+#define RXD_ERR_CE (1<<0) // CRC Error / Alignmnet Error
+
+struct sRXDesc
+{
+ Uint64 Buffer;
+ Uint16 Length;
+ Uint16 Checksum;
+ Uint8 Status;
+ Uint8 Errors;
+ Uint16 Special;
+} PACKED;
+
+#define TXD_CMD_IDE (1<<7) // Interrupt delay enable
+#define TXD_CMD_VLE (1<<6) // VLAN Packet enable
+#define TXD_CMD_DEXT (1<<5) // Use extended descriptor format (TODO)
+#define TXD_CMD_RPS (1<<4) // GC/EI Report Packet Set
+#define TXD_CMD_RS (1<<3) // Report Status
+#define TXD_CMD_IC (1<<2) // Insert checksum at indicated offset
+#define TXD_CMD_IFCS (1<<1) // Insert frame check sum
+#define TXD_CMD_EOP (1<<0) // End of packet
+
+#define TXD_STS_TU (1<<3) // [GC/EI] Transmit Underrun
+#define TXD_STS_LC (1<<2) // Late collision
+#define TXD_STS_EC (1<<1) // Excess collisions
+#define TXD_STS_DD (1<<0) // Descriptor Done
+
+struct sTXDesc
+{
+ Uint64 Buffer;
+ Uint16 Length;
+ Uint8 CSO; // TCP Checksum offset
+ Uint8 CMD;
+ Uint8 Status;
+ Uint8 CSS; // TCP Checksum start
+ Uint16 Special;
+} PACKED;
+
+#define TXCD_CMD_IDE (1<<(24+7)) // Interrupt Delay
+#define TXCD_CMD_DEXT (1<<(24+5)) // Descriptor Extension (Must be one)
+#define TXCD_CMD_RS (1<<(24+3)) // Report Status
+#define TXCD_CMD_TSE (1<<(24+2)) // TCP Segmentation Enable
+#define TXCD_CMD_IP (1<<(24+1)) // IP version (1=IPv4, 0=IPv6)
+#define TXCD_CMD_TCP (1<<(24+0)) // Packet Type (1=TCP, 0=Other)
+
+#define TXCD_STS_DD (1<<0) // Descriptor Done
+
+struct sTXCtxDesc
+{
+ Uint8 IPCSS; // IP Checksum Start
+ Uint8 IPCSO; // IP Checksum Offset
+ Uint16 IPCSE; // IP Checksum Ending (last byte)
+ Uint8 TUCSS; // TCP/UDP Checksum Start
+ Uint8 TUCSO; // TCP/UDP Checksum Offset
+ Uint16 TUCSE; // TCP/UDP Checksum Ending
+ Uint32 CmdLen; // [0:19] Length, [20:23] DTYP (0), [24:31] TUCMD
+ Uint8 Status;
+ Uint8 HdrLen; // Header length
+ Uint16 MSS; // Maximum segment size
+} PACKED;
+
+#define TXDD_CMD_IDE (1<<(24+7)) // Interrupt Delay
+#define TXDD_CMD_VLE (1<<(24+6)) // VLAN Enable
+#define TXDD_CMD_DEXT (1<<(24+5)) // Descriptor Extension
+#define TXDD_CMD_RPS (1<<(24+4)) // [GC/EI] Report Packet Sent
+#define TXDD_CMD_RS (1<<(24+3)) // Report Status
+#define TXDD_CMD_TSE (1<<(24+2)) // TCP Segmentation Enable
+#define TXDD_CMD_IFCS (1<<(24+1)) // Insert FCS
+#define TXDD_CMD_EOP (1<<(24+0)) // End of packet
+
+#define TXDD_STS_TU (1<<3) // [GC/EI] Transmit Underrun
+#define TXDD_STS_LC (1<<2) // Late collision
+#define TXDD_STS_EC (1<<1) // Excess collisions
+#define TXDD_STS_DD (1<<0) // Descriptor Done
+
+#define TXDD_POPTS_TXSM (1<<1) // Insert TCP/UDP Checksum
+#define TXDD_POPTS_IXSM (1<<0) // Insert IP Checksum
+
+struct sTXDataDesc
+{
+ Uint64 Buffer;
+ Uint32 CmdLen; // [0:19] Length, [20:23] DTYP (1), [24:31] DCMD
+ Uint8 Status;
+ Uint8 POpts; // Packet option field
+ Uint16 Special;
+};
+
+#define REG32(card,ofs) (((volatile Uint32*)card->MMIOBase)[ofs/4])
+#define REG64(card,ofs) (((volatile Uint64*)card->MMIOBase)[ofs/8])
+
+enum eRegs
+{
+ REG_CTRL = 0x000,
+ REG_STATUS = 0x008,
+ REG_EECD = 0x010,
+ REG_EERD = 0x014,
+ REG_CTRL_EXT = 0x018,
+ REG_FLA = 0x01C,
+ REG_MDIC = 0x020,
+ REG_FCAL = 0x028, // 64-bit value
+ REG_FCAH = 0x02C,
+ REG_FCT = 0x030,
+
+ REG_ICR = 0x0C0, // Interrupt cause read
+ REG_ITR = 0x0C4, // Interrupt throttling
+ REG_ICS = 0x0C8, // Interrupt cause set
+ REG_IMS = 0x0D0, // Interrupt mask set/read
+ REG_IMC = 0x0D8, // Interrupt mask clear
+
+ REG_TXCW = 0x178, // N/A for 82540EP/EM, 82541xx and 82547GI/EI
+ REG_RXCW = 0x180, // ^^
+ REG_LEDCTL = 0xE00,
+
+ REG_RCTL = 0x100,
+ REG_RDBAL = 0x2800,
+ REG_RDLEN = 0x2808,
+ REG_RDH = 0x2810,
+ REG_RDT = 0x2818,
+ REG_RDTR = 0x2820,
+ REG_RXDCTL = 0x2820, // Receive Descriptor Control
+
+ REG_TCTL = 0x400,
+ REG_TDBAL = 0x3800,
+ REG_TDLEN = 0x3808,
+ REG_TDH = 0x3810,
+ REG_TDT = 0x3818,
+ REG_TDIV = 0x3820, // Transmit Interrupt Delay Value
+ REG_TXDCTL = 0x3828, // Transmit Descriptor Control
+
+ REG_MTA0 = 0x5200, // 128 entries
+ REG_RA0 = 0x5400, // 16 entries of ?
+ REG_VFTA0 = 0x6500, // 128 entries
+};
+
+#define CTRL_FD (1 << 0) // Full-Duplex
+#define CTRL_LRST (1 << 3) // Link Reset
+#define CTRL_ASDE (1 << 5) // Auto-Speed Detection Enable
+#define CTRL_SLU (1 << 6) // Set link up
+// TODO: CTRL_*
+#define CTRL_SDP0_DATA (1 << 18) // Software Programmable IO #0 (Data)
+#define CTRL_SDP1_DATA (1 << 19) // Software Programmable IO #1 (Data)
+// TODO: CTRL_*
+#define CTRL_RST (1 << 26) // Software reset (cleared by hw once complete)
+#define CTRL_RFCE (1 << 27) // Receive Flow Control Enable
+#define CTRL_TFCE (1 << 28) // Transmit Flow Control Enable
+#define CTRL_VME (1 << 30) // VLAN Mode Enable
+#define CTRL_PHY_RST (1 << 31) // PHY Reset (3uS)
+
+#define ICR_TXDW (1 << 0) // Transmit Descriptor Written Back
+#define ICR_TXQE (1 << 1) // Transmit Queue Empty
+#define ICR_LSC (1 << 2) // Link Status Change
+#define ICR_RXSEQ (1 << 3) // Receive Sequence Error (Framing Error)
+#define ICR_RXDMT0 (1 << 4) // Receive Descriptor Minimum Threshold Reached (need more RX descs)
+#define ICR_XRO (1 << 6) // Receiver overrun
+#define ICR_RXT0 (1 << 7) // Receiver Timer Interrupt
+#define ICR_MDAC (1 << 9) // MDI/O Access Complete
+#define ICR_RXCFG (1 << 10) // Receiving /C/ ordered sets
+#define ICR_PHYINT (1 << 12) // PHY Interrupt
+#define ICR_GPI_SDP6 (1 << 13) // GP Interrupt SDP6/SDP2
+#define ICR_GPI_SDP7 (1 << 14) // GP Interrupt SDP7/SDP3
+#define ICR_TXD_LOW (1 << 15) // Transmit Descriptor Low Threshold hit
+#define ICR_SRPD (1 << 16) // Small Receive Packet Detected
+
+#define RCTL_EN (1 << 1) // Receiver Enable
+#define RCTL_SBP (1 << 2) // Store Bad Packets
+#define RCTL_UPE (1 << 3) // Unicast Promiscuous Enabled
+#define RCTL_MPE (1 << 4) // Multicast Promiscuous Enabled
+#define RCTL_LPE (1 << 5) // Long Packet Reception Enable
+#define RCTL_LBM (3 << 6) // Loopback mode
+enum {
+ RCTL_LBM_NONE = 0 << 6, // - No Loopback
+ RCTL_LBM_UD1 = 1 << 6, // - Undefined
+ RCTL_LBM_UD2 = 2 << 6, // - Undefined
+ RCTL_LBM_PHY = 3 << 6, // - PHY or external SerDes loopback
+};
+#define RCTL_RDMTS (3 << 8) // Receive Descriptor Minimum Threshold Size
+enum {
+ RCTL_RDMTS_1_2 = 0 << 8, // - 1/2 RDLEN free
+ RCTL_RDMTS_1_4 = 1 << 8, // - 1/4 RDLEN free
+ RCTL_RDMTS_1_8 = 2 << 8, // - 1/8 RDLEN free
+ RCTL_RDMTS_RSVD = 3 << 8, // - Reserved
+};
+#define RCTL_MO (3 << 12) // Multicast Offset
+enum {
+ RCTL_MO_36 = 0 << 12, // bits [47:36] of multicast address
+ RCTL_MO_35 = 1 << 12, // bits [46:35] of multicast address
+ RCTL_MO_34 = 2 << 12, // bits [45:34] of multicast address
+ RCTL_MO_32 = 3 << 12, // bits [43:32] of multicast address
+};
+#define RCTL_BAM (1 << 15) // Broadcast Accept Mode
+#define RCTL_BSIZE (1 << 16) // Receive Buffer Size
+enum {
+ RCTL_BSIZE_2048 = (0 << 16), // - 2048 bytes
+ RCTL_BSIZE_1024 = (1 << 16), // - 1024 bytes
+ RCTL_BSIZE_512 = (2 << 16), // - 512 bytes
+ RCTL_BSIZE_256 = (3 << 16), // - 256 bytes
+
+ RCTL_BSIZE_RSVD = (0 << 16)|(1 << 25), // - Reserved
+ RCTL_BSIZE_16K = (1 << 16)|(1 << 25), // - 16384 bytes
+ RCTL_BSIZE_8192 = (2 << 16)|(1 << 25), // - 8192 bytes
+ RCTL_BSIZE_4096 = (3 << 16)|(1 << 25), // - 4096 bytes
+};
+#define RCTL_VFE (1 << 18) // VLAN Filter Enable
+#define RCTL_CFIEN (1 << 19) // Canoical Form Indicator Enable
+#define RCTL_CFI (1 << 20) // Value to check the CFI for [Valid if CFIEN]
+#define RCTL_DPF (1 << 22) // Discard Pause Frames
+#define RCTL_PMCF (1 << 23) // Pass MAC Control Frames
+#define RCTL_BSEX (1 << 25) // Buffer Size Extension (multply BSIZE by 16, used in BSIZE enum)
+#define RCTL_SECRC (1 << 26) // Strip Ethernet CRC
+
+#define TCTL_EN (1 << 1) // Transmit Enable
+#define TCTL_PSP (1 << 3) // Pad Short Packets
+#define TCTL_CT (255 << 4) // Collision Threshold
+#define TCTL_CT_ofs 4
+#define TCTL_COLD (1023 << 12) // Collision Distance
+#define TCTL_COLD_ofs 12
+#define TCTL_SWXOFF (1 << 22) // Software XOFF Transmission
+#define TCTL_RTLC (1 << 24) // Retransmit on Late Collision
+#define TCTL_NRTU (1 << 25) // No retransmit on underrun [82544GC/EI]
+
+#endif
+
MODULE_DEFINE(0, VERSION, Network_PCnetFAST3, PCnet3_Install, PCnet3_Cleanup, "IPStack", NULL);
tIPStack_AdapterType gPCnet3_AdapterType = {
.Name = "PCnet-FAST III",
- .Type = 0, // TODO: Differentiate differnet wire protos and speeds
- .Flags = 0, // TODO: IP checksum offloading, MAC checksum offloading etc
+ .Type = ADAPTERTYPE_ETHERNET_100M,
+ //.Flags = ADAPTERFLAG_OFFLOAD_MAC,
+ .Flags = 0,
.SendPacket = PCnet3_SendPacket,
.WaitForPacket = PCnet3_WaitForPacket
};
outd(card->IOBase + REG_RDP, 0);
// Get MAC address
- #if 0
- Uint16 macword;
- //macword = _ReadCSR(card, CSR_MAC0);
- card->MacAddr[0] = macword & 0xFF;
- card->MacAddr[1] = macword >> 8;
- //macword = _ReadCSR(card, CSR_MAC1);
- card->MacAddr[2] = macword & 0xFF;
- card->MacAddr[3] = macword >> 8;
- //macword = _ReadCSR(card, CSR_MAC2);
- card->MacAddr[4] = macword & 0xFF;
- card->MacAddr[5] = macword >> 8;
- #else
Uint32 macword;
macword = ind(card->IOBase + REG_APROM0);
card->MacAddr[0] = macword & 0xFF;
macword = ind(card->IOBase + REG_APROM4);
card->MacAddr[4] = macword & 0xFF;
card->MacAddr[5] = macword >> 8;
- #endif
// Install IRQ Handler
IRQ_AddHandler(card->IRQ, PCnet3_IRQHandler, card);
- // Soft reset (read from RESET)
+ // Initialise the card state
PCnet3_int_InitCard(card);
-
- Semaphore_Init(&card->ReadSemaphore, 0, 0, "PCnet3", "CardRead");
-
// Register
card->IPStackHandle = IPStack_Adapter_Add(&gPCnet3_AdapterType, card, card->MacAddr);
return ret;
}
+int PCnet3_int_FillTD(tTxDesc_3 *td, Uint32 BufAddr, Uint32 Len, int bBounced)
+{
+ td->Flags0 = 0;
+ td->Flags1 = 0xF000 | (4096 - (Len & 0xFFF));
+ td->Buffer = BufAddr;
+ td->_avail = bBounced;
+ return 0;
+}
+
int PCnet3_SendPacket(void *Ptr, tIPStackBuffer *Buffer)
{
tCard *card = Ptr;
; // will be bounce-buffered
else
#endif
- if( MM_GetPhysAddr(sbuf_ptr)+sbuf_len != MM_GetPhysAddr(sbuf_ptr+sbuf_len) )
+ if( MM_GetPhysAddr(sbuf_ptr)+sbuf_len-1 != MM_GetPhysAddr(sbuf_ptr+sbuf_len-1) )
{
// Split
nDesc ++;
void *bounce_virt = MM_AllocDMA(1, 32, &bounce_phys);
memcpy(bounce_virt, sbuf_ptr, sbuf_len);
// Copy to bounce buffer
- td->Flags0 = 0;
- td->Flags1 = 0xF000 | sbuf_len;
- td->Buffer = bounce_phys;
- td->_avail = 1;
+ PCnet3_int_FillTD(td, bounce_phys, sbuf_len, 1);
LOG("%i: Bounce buffer %P+%i (orig %P,%P) - %p",
idx, bounce_phys, sbuf_len, start_phys, end_phys, td);
}
assert( !(td2->Flags1 & TXDESC_FLG1_OWN) );
td_idx = (td_idx + 1) % TLEN;
- td->Flags0 = 0;
- td->Flags1 = 0xF000 | page1_maxsize;
- td->Buffer = start_phys;
- td->_avail = 0;
+ PCnet3_int_FillTD(td, start_phys, page1_maxsize, 0);
- td2->Flags0 = 0;
- td2->Flags1 = 0xF000 | (sbuf_len - page1_maxsize);
- td2->Buffer = end_phys - (sbuf_len-page1_maxsize-1);
- td2->_avail = 0;
+ size_t page2_size = sbuf_len - page1_maxsize;
+ PCnet3_int_FillTD(td2, end_phys - (page2_size-1), page2_size, 0);
+ // - Explicitly set OWN on td2 because it's never the first, and `td` gets set below
td2->Flags1 |= TXDESC_FLG1_OWN;
LOG("%i: Split (%P,%P)+%i - %p,%p",
}
else
{
- td->Flags0 = 0;
- td->Flags1 = 0xF000 | sbuf_len;
- td->Buffer = start_phys;
- td->_avail = 0;
+ PCnet3_int_FillTD(td, start_phys, sbuf_len, 0);
LOG("%i: Straight %P+%i - %p",
idx, td->Buffer, sbuf_len, td);
}
// On every descriptor except the first, set OWN
// - OWN set later once all are filled
- if( (td_idx+TLEN-1)%TLEN != first_desc )
+ if( td != &card->TxQueue[first_desc] )
td->Flags1 |= TXDESC_FLG1_OWN;
}
if( status & CSR_STATUS_IDON )
{
Log_Debug("PCnet3", "Card %p initialisation done", card);
- }
+ LOG("CSR15 reads as 0x%x", _ReadCSR(card, 15));
+ }
// ERR set?
if( status & 0xBC00 )
_NETTYPE="user"
+_EVAL=eval
+
while [ $# -ne 0 ]; do
case $1 in
-gdb)
shift
QEMU_PARAMS=$QEMU_PARAMS" "$1
;;
+ -n)
+ _EVAL=echo
+ ;;
-fwd)
_NETTYPE=$_NETTYPE",hostfwd=tcp::10023-10.0.2.10:23"
;;
# qemu-system-x86_64 $QEMU_PARAMS -serial stdio | tee QemuLog.txt
#echo $QEMU $BOOTOPT $QEMU_PARAMS
if [ "x$_NOGRAPHIC" = "xyes" ] ; then
- eval $QEMU $BOOTOPT $QEMU_PARAMS -nographic | tee QemuLog.txt
+ $_EVAL $QEMU $BOOTOPT $QEMU_PARAMS -nographic | tee QemuLog.txt
exit
fi
if [ "x$_NOTEE" = "xyes" ] ; then
- eval $QEMU $BOOTOPT $QEMU_PARAMS -serial stdio
+ $_EVAL $QEMU $BOOTOPT $QEMU_PARAMS -serial stdio
exit
fi
-eval $QEMU $BOOTOPT $QEMU_PARAMS -serial stdio | tee QemuLog.txt
+$_EVAL $QEMU $BOOTOPT $QEMU_PARAMS -serial stdio | tee QemuLog.txt
return $?
}
+_ldflags="-lposix -lpsocket "$_ldflags
+
cfgfile=`mktemp`
make --no-print-directory -f $BASEDIR/getconfig.mk ARCH=x86 TYPE=$_linktype > $cfgfile
. $cfgfile
rm $tmpout
exit $_rv
else
- run $_LD$_ldflags $_miscargs $_outfile $LDFLAGS $_libs
+ run $_LD $_ldflags $_miscargs $_outfile $LDFLAGS $LIBGCC_PATH $_libs
fi
void mainmenu_run_dialog(void *unused);
void mainmenu_app_terminal(void *unused);
void mainmenu_app_textedit(void *unused);
+void update_time(void);
// === GLOBALS ===
tHWND gSidebar;
tHWND gSystemMenu;
tHWND gRunDialog;
tAxWin3_Widget *gRunInput;
+tAxWin3_Widget *gTimeDisplay;
int giScreenWidth;
int giScreenHeight;
char **gEnvion;
ELEFLAG_VERTICAL|ELEFLAG_ALIGN_CENTER|ELEFLAG_NOSTRETCH,
"Version/Time"
);
- txt = AxWin3_Widget_AddWidget(ele, ELETYPE_TEXT, ELEFLAG_NOSTRETCH, "Version String");
- AxWin3_Widget_SetSize(txt, 20);
- AxWin3_Widget_SetText(txt, "3.0");
+ gTimeDisplay = AxWin3_Widget_AddWidget(ele, ELETYPE_TEXT, ELEFLAG_NOSTRETCH, "Time");
+ AxWin3_Widget_SetSize(gTimeDisplay, 20);
+ //AxWin3_Widget_SetText(gTimeDisplay, "--:--");
+ update_time();
// Turn off decorations
AxWin3_DecorateWindow(gSidebar, 0);
}
+void update_time(void)
+{
+ char tmpbuf[2+1+2+1] = "--:--";
+ //strftime(tmpbuf, sizeof(tmpbuf), "%H:%M", NULL);
+ AxWin3_Widget_SetText(gTimeDisplay, tmpbuf);
+}
+
void mainmenu_app_textedit(void *unused)
{
// _SysDebug("TODO: Launch text editor");
// stty <devpath> [78][NOE][012][bB]<baud> <command...>
char path_seg[32+1];
char modespec[4+6+1];
- if( fscanf(fp, "%32s %6s ", path_seg, modespec) != 2 ) {
+ if( fscanf(fp, "%32s %10s ", path_seg, modespec) != 2 ) {
goto lineError;
}
char **command = ReadCommand(fp);
// - Runs a daemon (respawning) that logs to the specified files
// - Will append a header whenever the daemon starts
char *stdout_path = ReadQuotedString(fp);
+ if( !stdout_path )
+ goto lineError;
char *stderr_path = ReadQuotedString(fp);
+ if( !stderr_path )
+ goto lineError;
char **command = ReadCommand(fp);
+ if( !command )
+ goto lineError;
AddDaemon(stdout_path, stderr_path, command);
}
int baud;
// Parse mode string
- if( sscanf(ModeStr, "%1[78]%1[NOE]%1[012]%*1[bB]%d", &dbit, &parity, &sbit, &baud) != 5 ) {
+ if( sscanf(ModeStr, "%1[78]%1[NOE]%1[012]%*1[bB]%d", &dbit, &parity, &sbit, &baud) != 4 ) {
// Oops?
+ _SysDebug("Serial mode string is invalid ('%s')", ModeStr);
return -1;
}
int in = _SysOpen(Program->TypeInfo.STerm.Path, OPENFLAG_READ);
int out = _SysOpen(Program->TypeInfo.STerm.Path, OPENFLAG_WRITE);
+ if(in == -1 || out == -1 ) {
+ _SysDebug("Unable to open serial '%s' for '%s'", Program->TypeInfo.STerm.Path, Program->Command);
+ return -1;
+ }
+
#if 0
if( _SysIOCtl(in, 0, NULL) != DRV_TYPE_SERIAL )
{
return -2;
}
+ // Log spawn header
+ {
+ char buffer[101];
+ size_t len = snprintf(buffer, 100, "[%i] init spawning '%s'\n", _SysTimestamp(), Program->Command);
+ _SysWrite(out, buffer, len);
+ }
+
return SpawnCommand(in, out, err, Program->Command);
}
exec /Acess/SBin/dhcpc
+daemon /Devices/null /Devices/null /Acess/SBin/telnetd
+
ktty 0 /Acess/SBin/login
ktty 1 /Acess/SBin/login
-stty serial/0 /Acess/SBin/login
+stty serial/0 8N1b115200 /Acess/SBin/login
# vim: ft=text
SYSCALL2(_SysOpen, SYS_OPEN) // char*, int
SYSCALL3(_SysOpenChild, SYS_OPENCHILD) // int, char*, int
SYSCALL3(_SysReopen, SYS_REOPEN) // int, char*, int
+SYSCALL2(_SysCopyFD, SYS_COPYFD) // int, int
SYSCALL1(_SysClose, SYS_CLOSE) // int
SYSCALL3(_SysRead, SYS_READ) // int, uint, void*
SYSCALL3(_SysWrite, SYS_WRITE) // int, uint, void*
} caLocalExports[];
extern const int ciNumLocalExports;
extern char **gEnvP;
+extern char gLinkedBase[];
// === GLOABLS ===
tLoadedLib gLoadedLibraries[MAX_LOADED_LIBRARIES];
{
int i;
DEBUGS("IsFileLoaded: (file='%s')", file);
+
+ // Applications link against either libld-acess.so or ld-acess.so
+ if( strcmp(file, "/Acess/Libs/libld-acess.so") == 0
+ || strcmp(file, "/Acess/Libs/ld-acess.so") == 0 )
+ {
+ DEBUGS("IsFileLoaded: Found local (%p)", &gLinkedBase);
+ return &gLinkedBase;
+ }
+
for( i = 0; i < MAX_LOADED_LIBRARIES; i++ )
{
if(gLoadedLibraries[i].Base == 0) break; // Last entry has Base set to NULL
}
// Entry 0 is ld-acess, ignore it
- for(i = 1; i < MAX_LOADED_LIBRARIES; i ++)
+ for(i = 0; i < MAX_LOADED_LIBRARIES; i ++)
{
if(gLoadedLibraries[i].Base == 0)
break;
\r
// === Imports ===\r
extern char gLinkedBase[];\r
-extern tLoadedLib gLoadedLibraries[];\r
char **gEnvP;\r
extern int memcmp(const void *m1, const void *m2, size_t size);\r
\r
for(;;);\r
}\r
\r
- gLoadedLibraries[0].Base = &gLinkedBase;\r
- // 'libld-acess.so' because that is what applications link against\r
- gLoadedLibraries[0].Name = "/Acess/Libs/libld-acess.so";\r
- \r
// Otherwise do relocations\r
//ret = DoRelocate( base, envp, "Executable" );\r
ret = DoRelocate( base, NULL, "Executable" );\r
EOK,
ENOSYS, // Invalid Instruction
EINVAL, // Invalid Paramater
+ EBADF, // Bad FD
ENOMEM, // No free memory
EACCES, // Not permitted
EBUSY, // Resource is busy
ENOTDIR, // Not a directory
EIO, // IO Error
EINTR, // Operation interrupted (signal)
+ ENODEV, // ???
+ EADDRNOTAVAIL, // ?
+ EINPROGRESS, // ?
+
+ EAGAIN, // Try again
EALREADY, // Operation was a NOP
EINTERNAL, // Internal Error
#define SIG_DFL ((void*)0)
#define SIG_ERR ((void*)-1)
+#define SIGHUP 1
+#define SIGINT 2
+#define SIGQUIT 3
+#define SIGILL 4
#define SIGABRT 6
+#define SIGFPE 8
+#define SIGKILL 9
+#define SIGSEGV 11
+//#define SIGPIPE 13
+#define SIGALRM 14
+#define SIGTERM 15
+#define SIGUSR1 16
+#define SIGUSR2 17
#define SIGPIPE 1001
#define SIGCHLD 1002
+extern sighandler_t signal(int signum, sighandler_t handler);
+
extern int raise(int sig);
#endif
while( num -- )\r
{\r
bytes = _SysWrite(fp->FD, data, size);\r
+ if( bytes == (size_t)-1 ) {\r
+ // Oops.\r
+ // TODO: Set error flag\r
+ break;\r
+ }\r
if( bytes != size ) {\r
_SysDebug("_fwrite_unbuffered: Oops, rollback %i/%i bytes!", bytes, size);\r
_SysSeek(fp->FD, -bytes, SEEK_CUR);\r
#ifndef _FCNTL_H_
#define _FCNTL_H_
-#include <sys/sys.h>
+//#include <sys/sys.h>
// Hacks to handle different behaviors in Acess
// Open doesn't take a chmod
-#define open(_1,_2,...) open(_1, _2)
+//#define open(_1,_2,...) open(_1, _2)
// Close returns void
-#define close(_1) (close(_1),0)
+//#define close(_1) (close(_1),0)
// Acess doesn't implement lseek
#define lseek(_1,_2,_3) (seek(_1,_2,_3),tell(_1))
F_SETFL
};
-int fcntl(int fd, int cmd, ...) { return -1; }
+static inline int fcntl(int fd __attribute__((unused)), int cmd __attribute__((unused)), ...) { return -1; }
#endif
gid_t pw_gid;
char *pw_dir;
char *pw_shell;
+ char *pw_passwd;
};
extern struct passwd *getpwnam(const char *);
--- /dev/null
+/*
+ * Acess2 POSIX Emulation
+ * - By John Hodge (thePowersGang)
+ *
+ * ioctl.h
+ * - IOCtl hacks
+ */
+#ifndef _LIBPOSIX__IOCTL_H_
+#define _LIBPOSIX__IOCTL_H_
+
+
+
+#endif
+
#define _SYS__SELECT_H_
#include <acess/fd_set.h>
+#include <sys/time.h>
extern int select(int nfds, fd_set *readfds, fd_set *writefds, struct timeval *timeout);
// TODO: pselect?
typedef unsigned int nlink_t;
typedef uint32_t mode_t;
+#ifndef uid_t
typedef uint32_t uid_t;
+#endif
+#ifndef gid_t
typedef uint32_t gid_t;
+#endif
#define S_IFMT 0170000 /* type of file */
#define S_IFDIR 0040000 /* directory */
#ifndef _LIBPOSIX__SYS__WAIT_H_
#define _LIBPOSIX__SYS__WAIT_H_
+#include <sys/types.h>
+
// POSIX, waitpid()
#define WNOHANG 0x01
#define WUNTRACED 0x02
typedef unsigned long speed_t;
typedef unsigned short tcflag_t;
-enum {
+// c_iflag
+#define IGNBRK (1 << 0)
+#define BRKINT (1 << 1)
+#define IGNPAR (1 << 2) // Ignore parity failures
+#define PARMRK (1 << 3) // Mark parity failures with FFh 00h
+#define INPCK (1 << 4) // Enable input parity checks
+#define ISTRIP (1 << 5) // strip 8th bit
+#define INLCR (1 << 6) // Translate input newline into CR
+#define IGNCR (1 << 7) // Ignore input CR
+#define ICRNL (1 << 8) // Translate input CR into NL
+// (Linux) IUCLC // Map upper to lower case
+#define IXON (1 <<10) // Enable input XON/XOFF
+#define IXANY (1 <<11) // Any character will restart input
+#define IXOFF IXON
+// (Linux) IMAXBEL
+// (Linux) IUTF8
+
+// c_oflag
+#define OPOST (1 << 0) // Output processing
+// (Linux) OLCUC
+#define ONLCR (1 << 2) // (XSI) NL->CR
+#define OCRNL (1 << 3) // CR->NL
+#define ONOCR (1 << 4) // Don't output CR at column 0
+#define ONLRET (1 << 5) // Don't output CR
+#define OFILL (1 << 6) // Send fill chars for a delay, instead of timing
+// (Linux) OFDEL
+#define NLDLY (1 << 8) // Newline delay mask (NL0/NL1)
+#define NL0 (0 << 8)
+#define NL1 (1 << 8)
+#define NCDLY (3 << 9) // Carriage return delay mask (CR0-CR3)
+#define CR0 (0 << 9)
+#define CR1 (1 << 9)
+#define CR2 (2 << 9)
+#define CR3 (3 << 9)
+#define TABDLY (3 << 11) // Horizontal tab delay mask
+#define TAB0 (0 << 11)
+#define TAB1 (1 << 11)
+#define TAB2 (2 << 11)
+#define TAB3 (3 << 11)
+#define BSDLY (1 << 13) // Backspace delay
+#define BS0 (0 << 13)
+#define BS1 (1 << 13)
+#define VTDLY (1 << 14) // Vertical tab delay
+#define VT0 (0 << 14)
+#define VT1 (1 << 14)
+#define FFDLY (1 << 15) // Form feed delay
+#define FF0 (0 << 15)
+#define VFF1 (1 << 15)
+
+// c_cflag
+#define CBAUD (037 << 0) // Baud speed
+#define CSIZE (3 << 5) // Character size mask
+#define CS5 (0 << 5)
+#define CS6 (1 << 5)
+#define CS7 (2 << 5)
+#define CS8 (3 << 5)
+#define CSTOPB (1 << 7) // 1/2 stop bits
+#define CREAD (1 << 8) // Enable receiver
+#define PARENB (1 << 9) // Enable parity generation / checking
+#define PARODD (1 << 10) // Odd parity
+#define HUPCL (1 << 11) // Hang up on close
+#define CLOCAL (1 << 12) // Ignore modem control lines
+// LOBLK
+// CIBAUD
+// CMSPAR
+// CRTSCTS
+
+// c_lflag
+#define ISIG (1 << 0) // Generate signals for INTR, QUIT, SUSP and DSUSP
+#define ICANON (1 << 1) // Input canonical mode
+// XCASE
+#define ECHO (1 << 3) // Echo input characters
+#define ECHOE (1 << 4) // Enable ERASE and WERASE on echoed input [ICANON]
+#define ECHOK (1 << 5) // Enable KILL char on echoed input [ICANON]
+#define ECHONL (1 << 6) // Echo NL even if ECHO is unset [ICANON]
+#define ECHOCTL (1 << 7) // (non-POSIX) If ECHO set specials are echoed as val+0x40 (BS=^H)
+// ECHOPRT
+#define ECHOKE (1 << 9) // (non-POSIX) KILL implimented by sequential erase [ICANON]
+// DEFECHO
+// FLUSHO
+#define NOFLSH (1 << 11) // Disable flush of IO when generating INT, QUIT and SUSP
+#define TOSTOP (1 << 12) // ?
+// PENDIN
+#define IEXTEN (1 << 14)
+
+// - Indexes for c_cc
+enum
+{
+ VDISCARD,
+ VDSUSP,
VEOF,
VEOL,
+ VEOL2,
VERASE,
VINTR,
VKILL,
+ VLNEXT,
VMIN,
VQUIT,
+ // VREPRINT, // (non-POSIX)
VSTART,
+ // VSTATUS, // (non-POSIX)
VSTOP,
VSUSP,
+ // VSWITCH, // (non-POSIX)
VTIME,
+ VWERASE,
NCCS
};
extern int fork(void);
extern int execv(const char *b, char *v[]);
+extern int dup2(int oldfd, int newfd);
+
#endif
#include <stdarg.h>
// === CODE ===
+int unlink(const char *pathname)
+{
+ return _SysUnlink(pathname);
+}
+
int open(const char *path, int openmode, ...)
{
mode_t create_mode = 0;
return _SysRead(fd, buf, count);
}
+int seek(int fd, int whence, off_t dest)
+{
+ return _SysSeek(fd, whence, dest);
+}
+
+off_t tell(int fd)
+{
+ return _SysTell(fd);
+}
+
int fork(void)
{
return _SysClone(CLONE_VM, 0);
{
return _SysExecVE(b, v, NULL);
}
+
+int dup2(int oldfd, int newfd)
+{
+ // NOTE: Acess's CopyFD doesn't cause offset sharing
+ return _SysCopyFD(oldfd, newfd);
+}
+
}
+int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
+{
+ // Determine hostname
+ if( host )
+ {
+ if( hostlen == 0 )
+ return EAI_OVERFLOW;
+ host[0] = '\0';
+ if( !(flags & NI_NUMERICHOST) )
+ {
+ // Handle NI_NOFQDN
+ }
+ // Numeric hostname or the hostname was unresolvable
+ if( host[0] == '\0' )
+ {
+ if( (flags & NI_NAMEREQD) )
+ return EAI_NONAME;
+ }
+ }
+
+ // Determine service name
+ if( serv )
+ {
+ if( servlen == 0 )
+ return EAI_OVERFLOW;
+ serv[0] = '\0';
+ if( !(flags & NI_NUMERICSERV) )
+ {
+ // Handle NI_DGRAM
+ }
+ if( serv[0] == '\0' )
+ {
+
+ }
+ }
+ return EAI_SUCCESS;
+}
+
+
const char *gai_strerror(int errnum)
{
switch(errnum)
#define AI_ADDRCONFIG 0x004
#define AI_NUMERICHOST 0x008
+#define NI_NAMEREQD (1<<0)
+#define NI_DGRAM (1<<1)
+#define NI_NOFQDN (1<<2)
+#define NI_NUMERICHOST (1<<3)
+#define NI_NUMERICSERV (1<<4)
+
enum
{
EAI_SUCCESS,
EAI_NODATA,
EAI_NONAME,
EAI_SERVICE,
- EAI_SYSTEM
+ EAI_SYSTEM,
+ EAI_OVERFLOW
};
struct addrinfo
struct addrinfo *ai_next;
};
+extern int getnameinfo(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags);
extern int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
extern void freeaddrinfo(struct addrinfo *res);
const char *gai_strerror(int errorcode);
+/*
+ * Acess2 POSIX Sockets Emulation
+ * - By John Hodge (thePowersGang)
+ *
+ * netinet/in.h
+ * - ?Addressing?
+ */
#ifndef _LIBPSOCKET__NETINET__IN_H_
#define _LIBPSOCKET__NETINET__IN_H_
--- /dev/null
+/*
+ * Acess2 POSIX Sockets Emulation
+ * - By John Hodge (thePowersGang)
+ *
+ * netinet/ip.h
+ * - ???
+ */
+#ifndef _LIBPSOCKET__NETINET__IP_H_
+#define _LIBPSOCKET__NETINET__IP_H_
+
+#endif
+
#define _SYS_SOCKETS_H_
#include <sys/types.h>
+#ifndef size_t
#include <stddef.h> // size_t
+#endif
#include <stdint.h> // uint32_t
typedef uint32_t socklen_t;
enum
{
SO_REUSEADDR,
- SO_LINGER
+ SO_LINGER,
+ SO_ERROR
+};
+
+// shutdown how
+enum
+{
+ SHUT_RD,
+ SHUT_WR,
+ SHUT_RDWR
};
/**
*/
extern int socket(int domain, int type, int protocol);
+/**
+ *
+ */
+extern int shutdown(int socket, int how);
+
/**
* \brief Bind a socket to an address
*/
extern int getsockname(int socket, struct sockaddr *addr, socklen_t *addrlen);
extern int getpeername(int socket, struct sockaddr *addr, socklen_t *addrlen);
+extern struct hostent *gethostbyaddr(const void *addr, socklen_t len, int type);
+extern void sethostent(int stayopen);
+extern void endhostent(void);
+extern void herror(const char *s);
+extern const char *hstrerror(int err);
+extern struct hostent *gethostent(void);
+
#endif