From 1ba3b0dcaff0983044ab2a22f134df95dd3cc070 Mon Sep 17 00:00:00 2001 From: Void NV Date: Tue, 17 Mar 2020 09:40:18 -0500 Subject: [PATCH] SMBIOS parsing in progress. Partial AHCI definitions. Rename GetStr to StrGet Net code from TomAwezome --- ...o => Zenith-latest-2020-03-17-09_36_07.iso | Bin 34613248 -> 34658304 bytes src/Apps/Logic/Logic.CC | 2 +- src/Apps/Psalmody/PsalmodyMain.CC | 2 +- src/Apps/TimeClock/TimeClk.CC | 4 +- src/Compiler/CMisc.CC | 2 +- src/Demo/AcctExample/PersonalNotes.DD | 4 +- src/Demo/Define.CC | 2 +- src/Demo/Graphics/Cartesian.CC | 2 +- src/Demo/Lectures/MiniCompiler.CC | 2 +- src/Demo/PhoneNumWords.CC | 2 +- src/Demo/Prompt.CC | 2 +- src/Demo/SuggestSpelling.CC | 2 +- src/Doc/ChangeLog.DD | 5 + src/Home/K.CC | 2 +- src/Home/Net/ARP.CC | 235 ++++++++ src/Home/Net/Ethernet.CC | 52 ++ src/Home/Net/MappingShrineAlgs.DD | Bin 0 -> 1074 bytes src/Home/Net/Net.HH | 21 + src/Home/Net/NetFuncSummary.DD | 73 +++ src/Home/Net/NetHandlerTask.CC | 35 ++ src/Home/Net/NetQueue.CC | 85 +++ src/Home/Net/NetQueueDiagram.DD | Bin 0 -> 295 bytes src/Home/Net/NetworkingNotes.DD | 56 ++ src/Home/Net/PCNet.CC | 508 ++++++++++++++++++ src/Home/Net/ZenithStackNotes.DD | Bin 0 -> 199 bytes src/Home/SMBIOS.CC | 261 +++++++++ src/Kernel/KConfig.CC | 8 +- src/Kernel/KernelA.HH | 277 ++++++---- src/Kernel/KernelC.HH | 4 +- src/Kernel/SerialDev/Message.CC | 4 +- src/Misc/OSInstall.CC | 8 +- src/Zenith/Ctrls/CtrlsSlider.CC | 4 +- src/Zenith/DolDoc/DocGet.CC | 6 +- src/Zenith/DolDoc/DocPopUp.CC | 2 +- src/Zenith/ZBlkDev/Mount.CC | 2 +- src/Zenith/ZDebug.CC | 24 +- 36 files changed, 1539 insertions(+), 159 deletions(-) rename Zenith-latest-2020-03-12-22_41_57.iso => Zenith-latest-2020-03-17-09_36_07.iso (99%) create mode 100644 src/Home/Net/ARP.CC create mode 100644 src/Home/Net/Ethernet.CC create mode 100644 src/Home/Net/MappingShrineAlgs.DD create mode 100644 src/Home/Net/Net.HH create mode 100644 src/Home/Net/NetFuncSummary.DD create mode 100644 src/Home/Net/NetHandlerTask.CC create mode 100644 src/Home/Net/NetQueue.CC create mode 100644 src/Home/Net/NetQueueDiagram.DD create mode 100644 src/Home/Net/NetworkingNotes.DD create mode 100644 src/Home/Net/PCNet.CC create mode 100644 src/Home/Net/ZenithStackNotes.DD create mode 100644 src/Home/SMBIOS.CC diff --git a/Zenith-latest-2020-03-12-22_41_57.iso b/Zenith-latest-2020-03-17-09_36_07.iso similarity index 99% rename from Zenith-latest-2020-03-12-22_41_57.iso rename to Zenith-latest-2020-03-17-09_36_07.iso index 7c56772478b4e76be4d966eef5f2bcfe4e98f241..ecd75b5325d3629bd43d4fca21281c5bb0f63c27 100644 GIT binary patch delta 105124 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 a_>~yU;=o+a##bs4E?H@o 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 if (*st) { diff --git a/src/Apps/TimeClock/TimeClk.CC b/src/Apps/TimeClock/TimeClk.CC index 12cc2f36..3ce12579 100755 --- a/src/Apps/TimeClock/TimeClk.CC +++ b/src/Apps/TimeClock/TimeClk.CC @@ -124,7 +124,7 @@ public U0 PunchOut() tmpt->type=TET_PUNCH_OUT; tmpt->datetime=Now; "\nEnter Description.\nPress when done.\n"; - if (!(tmpt->desc=GetStr(,,GSF_WITH_NEW_LINE))) + if (!(tmpt->desc=StrGet(,,GSF_WITH_NEW_LINE))) tmpt->desc=CAlloc(1); QueueInsert(tmpt,header->last); TimeFileWrite(header); @@ -142,7 +142,7 @@ public U0 PunchIn() tmpt->type=TET_PUNCH_IN; tmpt->datetime=Now; "\nEnter Description.\nPress when done.\n"; - if (!(tmpt->desc=GetStr(,,GSF_WITH_NEW_LINE))) + if (!(tmpt->desc=StrGet(,,GSF_WITH_NEW_LINE))) tmpt->desc=CAlloc(1); QueueInsert(tmpt,header->last); TimeFileWrite(header); diff --git a/src/Compiler/CMisc.CC b/src/Compiler/CMisc.CC index 22a55527..8adc6506 100755 --- a/src/Compiler/CMisc.CC +++ b/src/Compiler/CMisc.CC @@ -149,7 +149,7 @@ U8 *CmdLinePrompt() RawDr; LBts(&Fs->task_flags,TASKf_CMD_LINE_PROMPT); - st=GetStr(,,GSF_SHIFT_ESC_EXIT); + st=StrGet(,,GSF_SHIFT_ESC_EXIT); LBtr(&Fs->task_flags,TASKf_CMD_LINE_PROMPT); i=StrLen(st); diff --git a/src/Demo/AcctExample/PersonalNotes.DD b/src/Demo/AcctExample/PersonalNotes.DD index c0cb9f88..e0f0bca7 100755 --- a/src/Demo/AcctExample/PersonalNotes.DD +++ b/src/Demo/AcctExample/PersonalNotes.DD @@ -77,7 +77,7 @@ $WW,1$$FG,5$$TX+CX,"TODO"$$FG$ * 12/25/2015 Copy-Paste index.html glitch if source window 40 columns. * 01/06/2016 Editor filter "str" applied to output from LineRep looks broken. -* Document, perhaps with video, $LK,"GetStr",A="MN:GetStr"$() all the way down into $LK,"PutKey",A="MN:PutKey"$() code. +* Document, perhaps with video, $LK,"StrGet",A="MN:StrGet"$() all the way down into $LK,"PutKey",A="MN:PutKey"$() code. * Better dictionary. * Good spell checker. @@ -379,7 +379,7 @@ $FG,5$$TX+CX,"Test"$$FG$ * Return ress for $LK,"GrBlot",A="MN:GrBlot"$, $LK,"GrRect",A="MN:GrRect"$, $LK,"GrPutChar",A="MN:GrPutChar"$? * Collision counts for $LK,"GrBlot",A="MN:GrBlot"$, $LK,"GrRect",A="MN:GrRect"$, $LK,"GrPutChar",A="MN:GrPutChar"$? -* $LK,"GetStr",A="MN:GetStr"$() or $LK,"GetChar",A="MN:GetChar"$() in $LK,"OSInstall",A="FI:::/Misc/OSInstall.CC"$ didn't like focus change. +* $LK,"StrGet",A="MN:StrGet"$() or $LK,"GetChar",A="MN:GetChar"$() in $LK,"OSInstall",A="FI:::/Misc/OSInstall.CC"$ didn't like focus change. * Test on Dad's computer or other people's? diff --git a/src/Demo/Define.CC b/src/Demo/Define.CC index 9c2678f5..1880a2d6 100755 --- a/src/Demo/Define.CC +++ b/src/Demo/Define.CC @@ -22,7 +22,7 @@ Bool Quit() I64 i; while (TRUE) { "%S %S?","ST_EXIT","ST_YES_NO"; - st=GetStr; + st=StrGet; i=DefineMatch(st,"ST_NO_YES_LIST",LMF_IGNORE_CASE); if (i>=0) { res=i; diff --git a/src/Demo/Graphics/Cartesian.CC b/src/Demo/Graphics/Cartesian.CC index 012ba9ae..eedd21b6 100755 --- a/src/Demo/Graphics/Cartesian.CC +++ b/src/Demo/Graphics/Cartesian.CC @@ -14,7 +14,7 @@ U0 Cartesian() "Enter algebraic equation to graph.\n" "Example: y=2*x\n" "y="; - if (st=GetStr) { + if (st=StrGet) { if (*st) { h=Fs->pix_width/2; v=Fs->pix_height/2; diff --git a/src/Demo/Lectures/MiniCompiler.CC b/src/Demo/Lectures/MiniCompiler.CC index 760c3d00..d14a629d 100755 --- a/src/Demo/Lectures/MiniCompiler.CC +++ b/src/Demo/Lectures/MiniCompiler.CC @@ -206,7 +206,7 @@ U0 Main() "This will compile an expression\n" "consisting of ints, parentheses\n" "and the operators +,-,* and /.\n"; - src=GetStr; + src=StrGet; if (*src) { src2=src; dst=code; diff --git a/src/Demo/PhoneNumWords.CC b/src/Demo/PhoneNumWords.CC index 393a270c..5dc7a1bb 100755 --- a/src/Demo/PhoneNumWords.CC +++ b/src/Demo/PhoneNumWords.CC @@ -53,7 +53,7 @@ U0 PhoneNumWords(U8 *num) U0 PNWDemo() { U8 *st; - while ((st=GetStr("Phone Num:")) && *st) { + while ((st=StrGet("Phone Num:")) && *st) { PhoneNumWords(st); Free(st); } diff --git a/src/Demo/Prompt.CC b/src/Demo/Prompt.CC index c4dd70a7..fffa067b 100755 --- a/src/Demo/Prompt.CC +++ b/src/Demo/Prompt.CC @@ -14,7 +14,7 @@ U0 PromptDemo() d=GetF64("Enter float expression(%12g):",1.2e3); "Float=%e\n",d; - name=GetStr("Name (%s):","John"); + name=StrGet("Name (%s):","John"); "Name:%s\n",name; Free(name); diff --git a/src/Demo/SuggestSpelling.CC b/src/Demo/SuggestSpelling.CC index 8289fba5..faa3d141 100755 --- a/src/Demo/SuggestSpelling.CC +++ b/src/Demo/SuggestSpelling.CC @@ -57,7 +57,7 @@ U0 SuggestSpellingDemo() { U8 *w; while (TRUE) { - w=GetStr("Word:"); + w=StrGet("Word:"); if (*w) { SuggestSpelling(w); Free(w); diff --git a/src/Doc/ChangeLog.DD b/src/Doc/ChangeLog.DD index 80aab20f..e7ebc926 100755 --- a/src/Doc/ChangeLog.DD +++ b/src/Doc/ChangeLog.DD @@ -1,4 +1,9 @@ $WW,1$$FG,5$$TX+CX,"ChangeLog"$$FG$ +$IV,1$----03/16/20 14:44:00----$IV,0$ +* Renamed GetStr() -> $LK,"StrGet",A="MN:StrGet"$(). + +* Added some $LK,"AHCI headers",A="MN:AHCI_SIG_ATA"$. + $IV,1$----03/12/20 22:00:36----$IV,0$ * Added $LK,"PaletteSetGruvboxDark",A="MN:PaletteSetGruvboxDark"$(). diff --git a/src/Home/K.CC b/src/Home/K.CC index 30cd0822..f2406881 100755 --- a/src/Home/K.CC +++ b/src/Home/K.CC @@ -1,6 +1,6 @@ Ed("/Doc/ChangeLog.DD"); -In("CC\n\n1\n\n6\n\n\n"); +In("CC\n\n1\n\n5\n\n\n"); BootHDIns; "\n\nSuccessful? "; if(YorN) diff --git a/src/Home/Net/ARP.CC b/src/Home/Net/ARP.CC new file mode 100644 index 00000000..3f99ce1c --- /dev/null +++ b/src/Home/Net/ARP.CC @@ -0,0 +1,235 @@ +#include "PCNet" +#include "Ethernet" + +#define ARP_HASHTABLE_SIZE 1024 + +#define HTT_ARP 0x00100 //identical to HTT_DICT_WORD + +#define ARP_REQUEST 0x01 +#define ARP_REPLY 0x02 + +class CARPHeader +{ + U16 hardware_type; + U16 protocol_type; + + U8 hardware_addr_len; + U8 protocol_addr_len; + + U16 operation; + + U8 sender_hardware_addr[MAC_ADDRESS_LENGTH]; + U32 sender_protocol_addr; + + U8 target_hardware_addr[MAC_ADDRESS_LENGTH]; + U32 target_protocol_addr; + +}; + +class CARPHash:CHash +{ //store U32 ip_address as CHash->str U8*, MStrPrint("%d") +// U32 ip_address; + U8 mac_address[MAC_ADDRESS_LENGTH]; +}; + +class CARPGlobals +{ + U32 local_ipv4; // stored in Big Endian + +} arp_globals; + +CHashTable *arp_cache = NULL; + +U0 ARPCacheInit() +{ + arp_cache = HashTableNew(ARP_HASHTABLE_SIZE); + arp_globals.local_ipv4 = 0; +} + + +I64 ARPSend(U16 operation, + U8 *dest_mac_address, + U8 *send_mac_address, + U32 send_ip, + U8 *target_mac_address, + U32 target_ip) +{//method currently assumes send_ and target_ip EndianU16 already... + + U8* ethernet_frame; + I64 de_index = EthernetFrameAllocate(ðernet_frame, + send_mac_address, + dest_mac_address, + ETHERTYPE_ARP, + sizeof(CARPHeader)); + if (de_index < 0) return de_index;// error state + + CARPHeader *header = ethernet_frame; + + header->hardware_type = EndianU16(HTYPE_ETHERNET); + header->protocol_type = EndianU16(ETHERTYPE_IPV4); + + header->hardware_addr_len = MAC_ADDRESS_LENGTH; + header->protocol_addr_len = IP_ADDRESS_LENGTH; + + header->operation = EndianU16(operation); + + MemCopy(header->sender_hardware_addr, send_mac_address, MAC_ADDRESS_LENGTH); + header->sender_protocol_addr = send_ip; + + MemCopy(header->target_hardware_addr, target_mac_address, MAC_ADDRESS_LENGTH); + header->target_protocol_addr = target_ip; + + EthernetFrameFinish(de_index); + return 0; +} + +CARPHash *ARPCacheFindByIP(U32 ip_address) +{ + U8 *ip_string = MStrPrint("%d", ip_address); + CARPHash *entry = HashFind(ip_string, arp_cache, HTT_ARP); + if (entry == NULL) + ZenithErr("Could not find an IP in ARP cache."); + + Free(ip_string); + return entry; +} + +CARPHash *ARPCachePut(U32 ip_address, U8 *mac_address) +{ + CARPHash *entry = ARPCacheFindByIP(ip_address); + Free(entry); + + entry = CAlloc(sizeof(CARPHash)); + entry->str = MStrPrint("%d", ip_address); + MemCopy(entry->mac_address, mac_address, 6); + return entry; +} + +U0 ARPSetIPV4Address(U32 ip_address) +{ // takes in little endian IP, stores into globals as Big Endian + arp_globals.local_ipv4 = EndianU32(ip_address); + + ARPSend(ARP_REPLY, + ethernet_globals.ethernet_broadcast, + EthernetGetMAC(), + arp_globals.local_ipv4, + ethernet_globals.ethernet_broadcast, + arp_globals.local_ipv4); +} + + + +//ARP Handler? Takes an eth_frame CEthFrame* ? +//Seems like a weird way to do this, +//and then it goes into a a RegisterL3Protocol +//function that does some function-handler +//magic. Idk why it _has_ to do that, it seems +//like a choice they made. I really do wonder if +//their is a slicker way to implement this. +//Less of this fucky function syntax mess. + +//We'll just make the ARP handle function +//and directly call it based on a switch in +//the NetQueueHandler +I64 ARPHandler(CEthernetFrame *ethernet_frame) +{ + // shrine checks if frame ethertype is ARP and ensures length is not less than CARPHeader + // since revising Shrine implement, will do same checks for now .. + if (ethernet_frame->ethertype != ETHERTYPE_ARP) + { + ZenithErr("ARP Handler caught wrong frame ethertype."); + return -1; // External use of ARPHandler must account for -1 error codes + } + if (ethernet_frame->length < sizeof(CARPHeader)) + { + ZenithErr("ARP Handler caught wrong frame length."); + return -1; // External use of ARPHandler must account for -1 error codes + } + + + CARPHeader *header = ethernet_frame->data; + U16 operation = EndianU16(header->operation); + + // shrine checks to ensure header->htype is 1, + // EndianU16(header->protocol_type) == ethertype ipv4, + // hlen(?) != 6(?), and that plen(?) == 4 (?) + if (EndianU16(header->hardware_type) != HTYPE_ETHERNET) + { + ZenithErr("ARP Handler caught wrong frame hardware type."); + return -1; // External use of ARPHandler must account for -1 error codes + } + + if (EndianU16(header->protocol_type) != ETHERTYPE_IPV4) + { + ZenithErr("ARP Handler caught wrong frame protocol type."); + return -1; // External use of ARPHandler must account for -1 error codes + } + if (header->hardware_addr_len != HLEN_ETHERNET) + { + ZenithErr("ARP Handler caught wrong frame hardware address length."); + return -1; // External use of ARPHandler must account for -1 error codes + } + if (header->protocol_addr_len != PLEN_IPV4) + { + ZenithErr("ARP Handler caught wrong frame protocol address length."); + return -1; // External use of ARPHandler must account for -1 error codes + } + + + + switch (operation) + { + case ARP_REQUEST: + if (header->target_protocol_addr == arp_globals.local_ipv4) + ARPSend(ARP_REPLY, + header->sender_hardware_addr, + EthernetGetMAC, + arp_globals.local_ipv4, + header->sender_hardware_addr, header->sender_protocol_addr); + break; + case ARP_REPLY: + ARPCachePut(EndianU32(header->sender_protocol_addr), header->sender_hardware_addr); + break; + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Home/Net/Ethernet.CC b/src/Home/Net/Ethernet.CC new file mode 100644 index 00000000..430a0b3b --- /dev/null +++ b/src/Home/Net/Ethernet.CC @@ -0,0 +1,52 @@ +class CEthernetFrame { + U8 source_address[6]; + U8 padding[2]; + U8 destination_address[6]; + U16 ethertype; + + U8 *data; + + I64 length; +}; + +class CEthernetGlobals +{ + U8 ethernet_null[6]; + U8 ethernet_broadcast[6]; + +} ethernet_globals; + +U0 EthernetInitGlobals() +{ + I64 i; + for (i=0;i<6;i++) + { + ethernet_globals.ethernet_null[i] = 0; + ethernet_globals.ethernet_broadcast[i] = 0xFF; + } +} + + + + +//This method is retarded. It needs help. +U0 EthernetFrameParse(CEthernetFrame *frame_out, U8 *frame, U16 length) +{ + //Shrine has a FIXME for check length! We need to figure out what + //lengths are appropriate ...... Shrine also says MemCopy has a + //high overhead. I'm almost tempted to say that means that a lot + //of the current system should be done with less extra allocation + //altogether, more passing. + + MemCopy(frame_out->destination_address, frame, 6); // 6 ? Why 6? Need a #define... + + MemCopy(frame_out->source_address, frame + 6, 6); // Ridiculous, what are those + + frame_out->ethertype = frame[13] | (frame[12] << 8); // This would be readable with #defines + + frame_out->data = frame + 14; // Fuck you Shrine + + frame_out->length = length - 14 + 4; //... He has a comment literally just saying "??". Wow. +} + +EthernetInitGlobals; \ No newline at end of file diff --git a/src/Home/Net/MappingShrineAlgs.DD b/src/Home/Net/MappingShrineAlgs.DD new file mode 100644 index 0000000000000000000000000000000000000000..d7098cd51b2e8d6a610a607c90b1312c936d38bb GIT binary patch literal 1074 zcmZ`&&ubGw6rPHgjCa9o506mNr0fQ3un1{`Ha4~x+F~1|sDvSz&92=a>CP-^`VZ*I zn->p)2f=?q!Mg|j54?&0f*#{H*`$$(%f5YY-@KXkee=zn_@`2FzH)SE7dF@H1$%pM zYkh?+vFy2al}+L$wtO9#CaiHR)G4ho>oI;Fz>WrD7?q0qQtyhW7s$jE*!%5P%P!25 zg>sE8TPPpF+Bcb1g};E!OUyiG-9YXo%%MRV1mq@hNRiak+-n|ihkTdhxv#XcDQk!M zP2Y`oBAtvdE(0ZPYHe#(DmIl<*I2aU2BNR*<9kOB-Ok?q)=s&`bGZ{=2E7`~zd^HO z*Z`(r%NJn(6oEncdK&-Ri&;aAg{T8kkthkMB9!DuI;O^s_L`I5;8tgn2eeR}N@}#K zhe@pCZXB#pP^B$=I)iCO)i~;go*zgvmJ#K-3G1Nh)TQ=hqDKQsTbMUpxpJ8WDF^eM zx|a!2D$Z)kW)U+I$#c!}OF;e#$j{(iL-_@Q-{bLk0o@!JcmDVAQ1lFI0%e&%smgA{ z=%na*sx%4e`bjqpL_%k&OrcF21tao=q6`gpa^|PKzCo8nY--=ZruKS%)PJ(^%qH;R zIe}S|14eEdb+sQyq{38rvS-?x?y|x;;~%atb`Dk_;eGi0r)lsW{;r|>6Q8dzqwpC1 z8|;zn<5HCE8*LLYP~_|Em;f`)w5Qd{ z{;Z-%DCPGfQ>Ny7f~+}bB3vk#^`8y1{3d9=1L^~a`UT#4i{LYYlJ+1AUN0Wba4SxI e+^(#p>{ZIl`h|mV8|Bc_#m(wWJ9NxdV(bs=Xfp%= literal 0 HcmV?d00001 diff --git a/src/Home/Net/Net.HH b/src/Home/Net/Net.HH new file mode 100644 index 00000000..8b0e6af6 --- /dev/null +++ b/src/Home/Net/Net.HH @@ -0,0 +1,21 @@ +//Generic Networking definitions + +#define ETHERNET_MIN_FRAME_SIZE 46 +#define ETHERNET_MAC_HEADER_LENGTH 14 +#define ETHERNET_ETHERTYPE_OFFSET 12 +#define ETHERNET_DATA_OFFSET 14 +#define MAC_ADDRESS_LENGTH 6 + +/* Ethernet Frame Size. + Linux uses 1544, OSDev and Shrine use 1548. Based on IEEE 802.3as, max frame size was agreed upon as 2000 bytes. */ +#define ETHERNET_FRAME_SIZE 2000 + +#define HTYPE_ETHERNET 1 +#define HLEN_ETHERNET 6 +#define PLEN_IPV4 4 + +#define ETHERTYPE_IPV4 0x0800 +#define ETHERTYPE_ARP 0x0806 + +#define IP_ADDRESS_LENGTH 4 + diff --git a/src/Home/Net/NetFuncSummary.DD b/src/Home/Net/NetFuncSummary.DD new file mode 100644 index 00000000..038827b8 --- /dev/null +++ b/src/Home/Net/NetFuncSummary.DD @@ -0,0 +1,73 @@ +PCNet + PCNetPCIDevFind + PCNetGetIOBase + PCNetReset + PCNetEnter32BitMode + PCNetWriteRAP + PCNetWriteCSR + PCNetReadCSR + PCNetSetSWStyle + PCNetGetMAC + PCNetInitDescriptorEntry + PCNetAllocateBuffers + PCNetDirectInit + PCNetSetInterruptCSR + PCNetEnableTXAutoPad + PCNetExitConfigMode + PCNetDriverOwns + PCNetAllocateTransmitPacket + PCNetFinishTransmitPacket + PCNetReceivePacket + PCNetReleasePacket + PCNetIRQ + PCIRerouteInterrupts + PCNetSetupInterrupts + PCNetInit + + EthernetFrameFinish (driver alias of PCNetFinishTransmitPacket) + EthernetFrameAllocate + EthernetGetMAC + + +NetQueue + NetQueueInit + NetQueuePull + NetQueuePushCopy + + +Ethernet + EthernetFrameParse (Needs refining!) + + +ARP + ARPCacheInit + ARPSend + ARPCacheFindByIP + ARPCachePut + ARPHandler + ARPSetIPV4Address + + +Sockets + + +IPV4 + + +ICMP + + +TCP + + +UDP + + +DNS + + +NetHandlerTask + NetHandlerTask + HandleNetQueueEntry (4 million context swaps per second!) + +NetConfig \ No newline at end of file diff --git a/src/Home/Net/NetHandlerTask.CC b/src/Home/Net/NetHandlerTask.CC new file mode 100644 index 00000000..38edf7f8 --- /dev/null +++ b/src/Home/Net/NetHandlerTask.CC @@ -0,0 +1,35 @@ + +U0 HandleNetQueueEntry(CNetQueueEntry *entry) +{ + CEthernetFrame ethernet_frame; + + EthernetFrameParse(ðernet_frame, entry->frame, entry->length); + + switch (ethernet_frame.ethertype) + { + case ETHERTYPE_ARP: + ARPHandler(ðernet_frame); + break; + } +} + +U0 NetHandlerTask(I64) +{ + while (TRUE) + { + CNetQueueEntry *entry = NetQueuePull; + + if (entry) + { + HandleNetQueueEntry(entry); + } + else + { + LBts(&Fs->task_flags, TASKf_SUSPENDED); + Yield; + } + + } +} + +net_handler_task = Spawn(&NetHandlerTask, NULL, "NetQueueHandler",,); \ No newline at end of file diff --git a/src/Home/Net/NetQueue.CC b/src/Home/Net/NetQueue.CC new file mode 100644 index 00000000..cf088035 --- /dev/null +++ b/src/Home/Net/NetQueue.CC @@ -0,0 +1,85 @@ +//Shrine mentions possibly using two FIFOs (in our case, Queues) for pending and empty frames. +//If logical to implement, perhaps Zenith NetQueue code should do something similar to that idea. + +//Each Ethernet Frame will be represented as an entry in a CQueue. +class CNetQueueEntry:CQueue +{ + I64 length; //todo: change to packet_length? + U8 frame[ETHERNET_FRAME_SIZE]; +}; + + +/* global variable, holds pointer of Ethernet Queue. + This acts as the Head of the Queue, Entries act + as the Tail of the Queue. + Upon QueueInit, ->next and ->last are set to + itself, the Head. */ +CQueue *net_queue; // no QueueRemove the Head! only Entries! + +//Net Handler Task is set idle and active depending on if entries in Net Queue. See NetHandlerTask.CC +CTask *net_handler_task = NULL; + +U0 NetQueueInit() +{ + net_queue = CAlloc(sizeof(CQueue)); + QueueInit(net_queue); +} + +CNetQueueEntry *NetQueuePull() +{//Returns a pointer to a CNetQueueEntry, or NULL pointer if Net Queue is empty. + CNetQueueEntry *entry; + + if (net_queue->next != net_queue) + { + entry = net_queue->next; + QueueRemove(entry); + } + else // Queue is empty if head->next is head itself. + entry = NULL; + + return entry; +} + +U0 NetQueuePushCopy(U8 *data, I64 length) +{/* Pushes a copy of the packet data and length + into the Net Queue. The NetQueueEntry is inserted + after the last entry of net_queue to keep new + items in the back of the Queue, old in front. */ + CNetQueueEntry *entry = CAlloc(sizeof(CNetQueueEntry)); + + entry->length = length; + MemCopy(entry->frame, data, length); + + QueueInsert(entry, net_queue->last); + + //Set Net Handler Task active. + if (net_handler_task) + LBtr(&net_handler_task->task_flags, TASKf_SUSPENDED); + + +} + +NetQueueInit; + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Home/Net/NetQueueDiagram.DD b/src/Home/Net/NetQueueDiagram.DD new file mode 100644 index 0000000000000000000000000000000000000000..a1a2a09b9923eaea664ae8c9f3320c9d160e1030 GIT binary patch literal 295 zcmYMvy$ZrG5C`yc?c(BM+aVM|kUCU1Q4yU4@dGDC&_E9@+KNpS^&xx(M;AAr%m)zs zM+F1F%O%_$NuTv-&wCbOB$ug-<0x5LR$)B!y?W5}{C2ky6evUA^~7fK47nw20ut8q zotZ#R6~`=eJ`>5lBG1DaJaBFZreMV~B)f$yfHDlho+4CW4Lxupgb5^k)a05`GuTL_ z$-W~q-4_^ulS43_o&N7jwck6O7j758iB2O{LZ&QIj<*L6eapN>C@oJ)=oJekWBlZS J>f*nH=nW0jI$Hn$ literal 0 HcmV?d00001 diff --git a/src/Home/Net/NetworkingNotes.DD b/src/Home/Net/NetworkingNotes.DD new file mode 100644 index 00000000..d13aaf63 --- /dev/null +++ b/src/Home/Net/NetworkingNotes.DD @@ -0,0 +1,56 @@ +$BG,0$$FG,15$Zenith Networking Stack Notes$FG,0$$BG,15$ + +Departures from Shrine: + + ARP Cache is Hashtable. Keys are U32 ip addresses to "%d" string. + + NetFIFO is NetQueue. If problems arise, maybe set a #define max + for the length of the Queue. + + Not defining ntohl and friends. Using Endian functions. + + Many file global vars have been condensed into global classes. + +Stack progress: (# done, ~ WIP, . N/A) + + # PCNet-II Driver + + # NetQueue + - no NetHandler currently + + ~ Ethernet + - need frame parse method + + # ARP (Address Resolution Protocol) + - double check. + + . Sockets + - thinking I should nix Sockets and + work out a STREAMS protocol instead. + Need more docs on STREAMS. + + + . IPV4 (Internet Protocol version 4) + + . ICMP (Internet Control Message Protocol) + + . TCP (Transmission Control Protocol) + + . UDP (User Datagram Protocol) + + . DNS (Domain Name System) + + . NetHandlerTask + - thinking maybe for this, instead of using this whole + handler function pointer nonsense, it can be done + more seamlessly with a switch(ethertype). Shrine + version just looks and seems wrong. Must be better way. + + - I'm thinking this is the better way: + We include the NetQueue handler as late as + possible, allowing all of the other layers of the + stack to already have their handle functions + made so we can just do a switch (ethertype) and + then directly call the appropriate handler. + + . NetConfig \ No newline at end of file diff --git a/src/Home/Net/PCNet.CC b/src/Home/Net/PCNet.CC new file mode 100644 index 00000000..64fd1f8f --- /dev/null +++ b/src/Home/Net/PCNet.CC @@ -0,0 +1,508 @@ +/* AMD PCNetII Driver + Author: TomAwezome + + Driver is based on: + - minexew's ShrineOS PCNet.CC implementation + - OSDev AMD_PCNET documentation + - AMD PCnet(TM)-PCI datasheet + - any other useful sources. + + Guidelines: + - Magic numbers are bad. #defines are good. + - Understandability over LOC. + - Clear documentation. +*/ + +#include "Net/Net.HH" +#include "Net/NetQueue" + +#define PCNET_DEVICE_ID 0x2000 +#define PCNET_VENDOR_ID 0x1022 + +#define PCI_REG_COMMAND 0x04 + +#define PCNET_CMDf_IOEN 0 +#define PCNET_CMDf_BMEN 2 + +#define PCNET_CMDF_IOEN (1 << PCNET_CMDf_IOEN) +#define PCNET_CMDF_BMEN (1 << PCNET_CMDf_BMEN) + +#define PCNET_WD_RESET 0x14 // reset reg location when card is in 16-bit mode + +#define PCNET_DW_RDP 0x10 +#define PCNET_DW_RAP 0x14 +#define PCNET_DW_RESET 0x18 // reset reg location when card is in 32-bit mode + +#define PCNET_CSR_CTRLSTATUS 0 +#define PCNET_CSR_INTERRUPTS 3 +#define PCNET_CSR_FEATURECTRL 4 +#define PCNET_CSR_LADRF0 8 +#define PCNET_CSR_LADRF1 9 +#define PCNET_CSR_LADRF2 10 +#define PCNET_CSR_LADRF3 11 +#define PCNET_CSR_PADR0 12 +#define PCNET_CSR_PADR1 13 +#define PCNET_CSR_PADR2 14 +#define PCNET_CSR_MODE 15 +#define PCNET_CSR_BADRL 24 +#define PCNET_CSR_BADRU 25 +#define PCNET_CSR_BADTL 30 +#define PCNET_CSR_BADTU 31 +#define PCNET_CSR_POLLINT 47 +#define PCNET_CSR_SOFTWARESTYLE 58 +#define PCNET_CSR_RXRINGLEN 76 +#define PCNET_CSR_TXRINGLEN 78 + +#define PCNET_SWSTYLE_SELECTION 2 // AMD PCNet datasheet p. 1-968 + +// Refer to AMD PCNet datasheet p. 1-954, 1-956, 1-957 for Interrupt Mask details. +#define PCNET_INT_BSWP 2 // Byte Swap (Big-Endian / Little-Endian) +#define PCNET_INT_IDONM 8 // Initialization Done Mask +#define PCNET_INT_TINTM 9 // Transmit Interrupt Mask +#define PCNET_INT_RINTM 10 // Receive Interrupt Mask + +#define PCNET_FEATURE_APADXMT 11 + +#define PCNET_CTRL_INIT 0 +#define PCNET_CTRL_STRT 1 +#define PCNET_CTRL_STOP 2 +#define PCNET_CTRL_RINT 10 + +#define PCNET_RX_BUFF_COUNT 32 // Linux & Shrine Driver use 32 and 8 for these, we could allow more if wanted. +#define PCNET_TX_BUFF_COUNT 8 + +#define PCNET_DESCRIPTORf_ENP 24 +#define PCNET_DESCRIPTORf_STP 25 +#define PCNET_DESCRIPTORf_OWN 31 // AMD PCNet datasheet p.1-992, 1-994 +//#define PCNET_DESCRIPTORF_OWN (1 << PCNET_DESCRIPTORf_OWN) + +#define INT_DEST_CPU 0 + +class CPCNet +{ + CPCIDev *pci; + U64 mac_address; //MAC address is first 6 bytes of PCNet EEPROM (page # ?) + + I64 current_rx_de_index; // Current Receive DE being processed. Gets incremented, wrapped to 0 at max of PCNET_RX_BUFF_COUNT. + I64 current_tx_de_index; // Current Transmit DE being processed. Gets incremented, wrapped to 0 at max of PCNET_TX_BUFF_COUNT. + + U8 *rx_de_buffer; // Uncached-alias of pointer to the buffer of RX Descriptor Entries. + U8 *tx_de_buffer; // Uncached-alias of pointer to the buffer of TX Descriptor Entries. + U8 *rx_de_buffer_phys; // Pointer to the buffer of RX Descriptor Entries. (Code Heap, lower 2Gb) + U8 *tx_de_buffer_phys; // Pointer to the buffer of TX Descriptor Entries. (Code Heap, lower 2Gb) + + U32 rx_buffer_addr; // 'Physical address of actual receive buffers (< 4 Gb)' + U32 tx_buffer_addr; // 'Physical address of actual transmit buffers (< 4 Gb)' + +} pcnet; // pcnet is the global variable we store all of this into. + +class CPCNetDescriptorEntry +{/* AMD PCNet datasheet p.1-991 & p.1-994 NOTE: chart typo on 1-994, see ONES and BCNT on 1-995. + TX and RX DE's are the same size (16-Bytes) and structure, but have different registers and functions. + The RX and TX DE buffers of the CPCNet class are allocated to a certain amount of these DEs. */ + U32 buffer_addr; + U32 status1; + U32 status2; + U32 reserved; +}; + +CPCIDev *PCNetPCIDevFind() +{// Find and return PCNetII card as a CPCIDev pointer. + return PCIDevFind(,,PCNET_VENDOR_ID,PCNET_DEVICE_ID); +} + +U32 PCNetGetIOBase() +{/* Return memory IO base address of PCNet card. Bits 0-4 are not for the IO base, so an AND NOT 0x1F ignores those bits. */ + U32 io_base = pcnet.pci->base[0] & ~0x1F; + return io_base; +} + +U0 PCNetReset() +{/* Reads the 32- and 16-bit RESET registers, which, + regardless of which mode the card is in, will reset it back to 16-bit mode. */ + InU32(PCNetGetIOBase + PCNET_DW_RESET); + InU16(PCNetGetIOBase + PCNET_WD_RESET); + Busy(5); // OSDev says minimum 1 æS +} + +U0 PCNetEnter32BitMode() +{/* AMD PCNet datasheet p. 1-930 + Summary: A 32-bit write (while in 16-bit mode) to RDP will cause 16-bit mode exit and immediate entry into 32-bit mode. */ + OutU32(PCNetGetIOBase + PCNET_DW_RDP, 0); +} + +U0 PCNetWriteCSR(U32 csr, U32 value) +{/* AMD PCNet datasheet p. 1-952 + Summary: Control and Status Registers are accessed via the RDP (Register Data Port). + Which CSR is selected is based on the value in the RAP (Register Address Port). */ + OutU32(PCNetGetIOBase + PCNET_DW_RAP, csr); + OutU32(PCNetGetIOBase + PCNET_DW_RDP, value); +} + +U32 PCNetReadCSR(U32 csr) +{/* AMD PCNet datasheet p. 1-952 + Summary: Control and Status Registers are accessed via the RDP (Register Data Port). + Which CSR is selected is based on the value in the RAP. */ + OutU32(PCNetGetIOBase + PCNET_DW_RAP, csr); + return InU32(PCNetGetIOBase + PCNET_DW_RDP); +} + +U0 PCNetSetSWStyle() +{/* AMD PCNet datasheet p. 1-968 + In CSR58 (Software Style), the 8-bit SWSTYLE register dictates interpretation of certain bits in the CSR space, + and widths of descriptors and initialization block. + In PCNet-PCI mode, CSR4 bits function as defined in the datasheet, and TMD1[29] functions as ADD_FCS. */ + U32 csr = PCNetReadCSR(PCNET_CSR_SOFTWARESTYLE); + + csr &= ~0xFF; // clears first 8 bits: SWSTYLE 8-bit register. + csr |= PCNET_SWSTYLE_SELECTION; // set SWSTYLE to PCNet-PCI mode. + + PCNetWriteCSR(PCNET_CSR_SOFTWARESTYLE, csr); +} + +U0 PCNetGetMAC() +{/* AMD PCNet datasheet p. 1-887, 1-931, 1-937 + MAC address stored at first 6 bytes of PCNet EEPROM. + EEPROM addresses shadow-copied to APROM at hardware init. APROM accessible at first 16 bytes of PCI IO space. */ + I64 i; + for (i = 0; i < 6; i++) + pcnet.mac_address.u8[i] = InU8(PCNetGetIOBase + i); +} + +U0 PCNetInitDescriptorEntry(CPCNetDescriptorEntry *entry, U32 buffer_addr, I64 is_rx) +{ + entry->buffer_addr = buffer_addr; + /* AMD PCNet datasheet p.1-991. + BCNT is the usable buffer length, expressed as first 12 bits of 2s-complement of desired length. + Bits 0-11 of a DE are for the buffer byte count (BCNT),and bits 12-15 of a DE must be written all ones (ONES)*/ + entry->status1 |= -ETHERNET_MIN_FRAME_SIZE & 0xFFF; //Sets BCNT reg (first 12 bits) in DE TMD1/RMD1, as 2s complement of the desired length. + entry->status1 |= 0xF000; // Sets bits 12-15 (ONES) in DE TMD1/RMD1 as all ones. + //if this is a Receive DE, give ownership to the card so the PCNet can fill them. + if (is_rx) Bts(&entry->status1, PCNET_DESCRIPTORf_OWN); + ClassRep(entry); +} + +U0 PCNetAllocateBuffers() +{ + I64 de_index; // used in for loops for TX and RX DE access. + + /* AMD PCNet datasheet p.1-913, p.1-990 + When SSIZE32 = 1, Descriptor Ring Entry Base Address must be on 16-byte boundary. (TDRA[3:0] = 0, RDRA[3:0] = 0) */ + pcnet.rx_de_buffer_phys = CAllocAligned(sizeof(CPCNetDescriptorEntry) * PCNET_RX_BUFF_COUNT, 16, Fs->code_heap); + pcnet.tx_de_buffer_phys = CAllocAligned(sizeof(CPCNetDescriptorEntry) * PCNET_TX_BUFF_COUNT, 16, Fs->code_heap); + + //Shrine does a check and returns -1 here, if the end of either buffer exceeds 0x100000000 + + pcnet.rx_de_buffer = dev.uncached_alias + pcnet.rx_de_buffer_phys; // we want uncached + pcnet.tx_de_buffer = dev.uncached_alias + pcnet.tx_de_buffer_phys; // access to these. + + pcnet.rx_buffer_addr = CAlloc(ETHERNET_MIN_FRAME_SIZE * PCNET_RX_BUFF_COUNT, Fs->code_heap);//Shrine has a TODO to figure out + pcnet.tx_buffer_addr = CAlloc(ETHERNET_MIN_FRAME_SIZE * PCNET_TX_BUFF_COUNT, Fs->code_heap);//if these should be uncached too. + //note, p.1-991,1-994: RBADR is only 32 bits wide. + + //Shrine does a check and returns -1 here, if the end of either buffer exceeds 0x100000000 + + CPCNetDescriptorEntry *entry = pcnet.rx_de_buffer; + for (de_index = 0; de_index < PCNET_RX_BUFF_COUNT; de_index++) + PCNetInitDescriptorEntry(&entry[de_index], pcnet.rx_buffer_addr, TRUE); // TRUE for is_rx. + + entry = pcnet.tx_de_buffer; + for (de_index = 0; de_index < PCNET_TX_BUFF_COUNT; de_index++) + PCNetInitDescriptorEntry(&entry[de_index], pcnet.tx_buffer_addr, FALSE); // FALSE for is_rx. +} + +U0 PCNetDirectInit() +{/* AMD PCNet datasheet p. 1-1021 + Instead of setting up an initialization block, + direct writes to the necessary CSRs can be used to manually initialize the PCNet card. */ + + /* AMD PCNet datasheet p.1-991 + If Logical Address Filter is set as all 0, all incoming logical addresses are rejected. Disables multicast. */ + PCNetWriteCSR(PCNET_CSR_LADRF0, 0); + PCNetWriteCSR(PCNET_CSR_LADRF1, 0); + PCNetWriteCSR(PCNET_CSR_LADRF2, 0); + PCNetWriteCSR(PCNET_CSR_LADRF3, 0); + + /* AMD PCNet datasheet p.1-960, 1-961 + The Physical Address is the MAC. + The first 16 bits of CSRs 12-14 are for the Physical Address, the upper bits are reserved, written 0 read undefined.*/ + + PCNetWriteCSR(PCNET_CSR_PADR0, pcnet.mac_address.u16[0]); + PCNetWriteCSR(PCNET_CSR_PADR1, pcnet.mac_address.u16[1]); + PCNetWriteCSR(PCNET_CSR_PADR2, pcnet.mac_address.u16[2]); + + /* AMD PCNet datasheet p.1-961, 1-962, 1-963 + Refer to datasheet for specifics. Most relevant, when setting Mode to 0, promiscuous mode is is disabled, + TX and RX enabled, enable RX broadcast and unicast. */ + PCNetWriteCSR(PCNET_CSR_MODE, 0); + + /* AMD PCNet datasheet p.1-964 + CSR 24 and 25 need to be filled with the lower and upper 16 bits, respectively, of the address of the RX packet ring. Likewise for + CSR 30 and 31 for the TX packet ring.*/ + + PCNetWriteCSR(PCNET_CSR_BADRL, pcnet.rx_buffer_addr.u16[0]); + PCNetWriteCSR(PCNET_CSR_BADRU, pcnet.rx_buffer_addr.u16[1]); + + PCNetWriteCSR(PCNET_CSR_BADTL, pcnet.tx_buffer_addr.u16[0]); + PCNetWriteCSR(PCNET_CSR_BADTU, pcnet.tx_buffer_addr.u16[1]); + + /* AMD PCNet datasheet p. 1-967 + Default value at hardware init is all 0. + Standard init block process sets this, but if doing directly it is imperative to manually set it 0. */ + PCNetWriteCSR(PCNET_CSR_POLLINT, 0); + + /* AMD PCNet datasheet p. 1-970 + Receive and Transmit Ring Length CSRs bits 0-15 need to be set as the 2s complement of the ring length. + The AND with 0xFFFF clears the upper Reserved bits, which are to be written as zeroes read undefined. */ + PCNetWriteCSR(PCNET_CSR_RXRINGLEN, -PCNET_RX_BUFF_COUNT & 0xFFFF); + PCNetWriteCSR(PCNET_CSR_TXRINGLEN, -PCNET_TX_BUFF_COUNT & 0xFFFF); +} + +U0 PCNetSetInterruptCSR() +{/* AMD PCNet datasheet p.1-952, 1-953, 1-954, 1-955, 1-956, 1-957 + Refer to datasheet for specifics on the Interrupt Masks. + Most of these, when set 0, allow interrupts to be set in CSR0. + We set Big-Endian disabled, RX interrupts enabled, Init Done interrupt disabled, and TX interrupt disabled. */ + U32 csr = PCNetReadCSR(PCNET_CSR_INTERRUPTS); + + Btr(&csr, PCNET_INT_BSWP); + Btr(&csr, PCNET_INT_RINTM); + + Bts(&csr, PCNET_INT_IDONM); + Bts(&csr, PCNET_INT_TINTM); + + PCNetWriteCSR(PCNET_CSR_INTERRUPTS, csr); +} + +U0 PCNetEnableTXAutoPad() +{/* AMD PCNet datasheet p.1-958 + Setting bit 11 (Auto Pad Transmit) allows short transmit frames to be automatically extended to 64 bytes. */ + U32 csr = PCNetReadCSR(PCNET_CSR_FEATURECTRL); + + Bts(&csr, PCNET_FEATURE_APADXMT); + + PCNetWriteCSR(PCNET_CSR_FEATURECTRL, csr); + +} + +U0 PCNetExitConfigMode() +{/* AMD PCNet datasheet p.1-954 + PCNet controller can be started after configuring by ensuring INIT and STOP are cleared and START bit is set in CSR0. */ + U32 csr = PCNetReadCSR(PCNET_CSR_CTRLSTATUS); + + Btr(&csr, PCNET_CTRL_INIT); + Btr(&csr, PCNET_CTRL_STOP); + + Bts(&csr, PCNET_CTRL_STRT); + + PCNetWriteCSR(PCNET_CSR_CTRLSTATUS, csr); +} + +I64 PCNetDriverOwns(CPCNetDescriptorEntry* entry) +{/* Returns whether the value of the OWN bit of the Descriptor Entry is zero. + If 0, driver owns, if 1, PCNet card owns it. */ + return !Bt(&entry->status1, PCNET_DESCRIPTORf_OWN); +} + +I64 PCNetAllocateTransmitPacket(U8 **packet_buffer_out, I64 length) +{/* Transmits the packet at the current TX DE index. + The packet_buffer_out is a pointer, since we modify its value, ending with returning the index of the DE we just processed. + Length is validated to fit in BCNT. + The increment of the current TX DE index is done by assigning it the value of incrementing it AND the max DE index - 1. + This will increment it as well as wrap back to 0 if we hit the max DE index. */ + + I64 de_index = pcnet.current_tx_de_index; + + if (length > 0xFFF) + { // Max packet length must fit into BCNT 12-bit register. + ZenithErr("Invalid TX Packet Length"); + throw('PCNet'); + } + + CPCNetDescriptorEntry *entry = &pcnet.tx_de_buffer[de_index]; + + if (!PCNetDriverOwns(entry)) + { + ZenithErr("TX FIFO Full"); + return -1; // Positive value expected. Functions calling this must factor this in. + } + + Bts(&entry->status1, PCNET_DESCRIPTORf_STP); + Bts(&entry->status1, PCNET_DESCRIPTORf_ENP); + + /* AMD PCNet datasheet p.1-991. + BCNT is the usable buffer length, expressed as first 12 bits of 2s-complement of desired length. + Bits 0-11 of a DE are for the buffer byte count (BCNT), + and bits 12-15 of a DE must be written all ones (ONES) */ + entry->status1 |= -length & 0xFFF; // Sets BCNT reg (first 12 bits) in DE TMD1, as 2s complement of the desired length. + entry->status1 |= 0xF000; // Sets bits 12-15 (ONES) in DE TMD1 as all ones. + + pcnet.current_tx_de_index = (pcnet.current_tx_de_index + 1) & (PCNET_TX_BUFF_COUNT - 1); + + *packet_buffer_out = pcnet.tx_buffer_addr + (de_index * ETHERNET_MIN_FRAME_SIZE); + + return de_index; +} + +U0 PCNetFinishTransmitPacket(I64 de_index) +{/* Release ownership of the packet to the PCNet card + by setting the OWN bit to 1. */ + CPCNetDescriptorEntry *entry = &pcnet.tx_de_buffer[de_index]; + Bts(&entry->status1, PCNET_DESCRIPTORf_OWN); +} + +U0 EthernetFrameFinish(I64 de_index) +{//Alias for driver Finish TX function. + PCNetFinishTransmitPacket(de_index); +} + +I64 PCNetReceivePacket(U8 **packet_buffer_out, U16 *packet_length_out) +{/* Receives the packet at the current RX DE index. + Parameters are both pointers, since we modify the value at the packet_buffer_out, + and at the packet_length, ending with returning the index of the DE we just processed. + The MCNT is stored at the first two bytes of the RMD2. + We AND with 0xFFFF to only take in those first two bytes: that is the packet_length. + The increment of the current RX DE index is done by assigning it the value of incrementing it AND the max DE index - 1. + This will increment it as well as wrap back to 0 if we hit the max DE index. */ + ZenithLog("PCNet received packet. %X , %X",packet_buffer_out, packet_length_out); + I64 de_index = pcnet.current_rx_de_index; + + CPCNetDescriptorEntry *entry = &pcnet.rx_de_buffer[de_index]; + U16 packet_length = entry->status2 & 0xFFFF; + + pcnet.current_rx_de_index = (pcnet.current_rx_de_index + 1) & (PCNET_RX_BUFF_COUNT - 1); + + *packet_buffer_out = pcnet.rx_buffer_addr + (de_index * ETHERNET_MIN_FRAME_SIZE); + *packet_length_out = packet_length; + return de_index; +} + +U0 PCNetReleaseReceivePacket(I64 de_index) +{/* Release ownership of the packet to the PCNet card + by setting the OWN bit to 1. */ + CPCNetDescriptorEntry *entry = &pcnet.rx_de_buffer[de_index]; + Bts(&entry->status1, PCNET_DESCRIPTORf_OWN); +} + +interrupt U0 PCNetIRQ() +{// todo: comments explaining process...maybe reimplement interrupt handling altogether. + U8 *packet_buffer; + U16 packet_length; + I64 de_index; + U32 csr = PCNetReadCSR(PCNET_CSR_CTRLSTATUS); + //"Interrupt Reason: %X , %b\n",csr,csr; + + CPCNetDescriptorEntry *entry = pcnet.rx_de_buffer; + + while (PCNetDriverOwns(&entry[pcnet.current_rx_de_index])) + { + "%X", pcnet.current_rx_de_index; + de_index = PCNetReceivePacket(&packet_buffer, &packet_length); + + if (de_index >= 0) // necessary? check increment logic in PCNetReceivePacket. + { + ZenithLog("Pushing copy into Net Queue, Releasing Receive Packet"); + NetQueuePushCopy(packet_buffer, packet_length); + PCNetReleaseReceivePacket(de_index); + } + + Bts(&csr, PCNET_CTRL_RINT); + + PCNetWriteCSR(PCNET_CSR_CTRLSTATUS, csr); + } + + *(dev.uncached_alias + LAPIC_EOI)(U32*) = 0; +} + +U0 PCIRerouteInterrupts(I64 base) +{// todo: comments explaining process, maybe better var names + I64 i; + U8 *da = dev.uncached_alias + IOAPIC_REG; + U32 *_d = dev.uncached_alias + IOAPIC_DATA; + + for (i = 0; i < 4; i++) + { + *da = IOREDTAB + i * 2 + 1; + *_d = dev.mp_apic_ids[INT_DEST_CPU] << 24; + *da = IOREDTAB + i * 2; + *_d = 0x4000 + base + i; + } +} + +U0 PCNetSetupInterrupts() +{ // todo: comments explaining process + IntEntrySet(I_USER + 0, &PCNetIRQ, IDTET_IRQ); + IntEntrySet(I_USER + 1, &PCNetIRQ, IDTET_IRQ); + IntEntrySet(I_USER + 2, &PCNetIRQ, IDTET_IRQ); + IntEntrySet(I_USER + 3, &PCNetIRQ, IDTET_IRQ); + PCIRerouteInterrupts(I_USER); +} + +U0 PCNetInit() +{ + MemSet(&pcnet, 0, sizeof(CPCNet)); // pcnet global var will hold member data the driver uses often. + + pcnet.pci = PCNetPCIDevFind; + if (!pcnet.pci) + return; // if we don't find the card, quit. + + //Clear command register of PCNet PCI device, set IO Enable and Bus Master Enable bits of the register. + PCIWriteU16(pcnet.pci->bus, pcnet.pci->dev, pcnet.pci->fun, PCI_REG_COMMAND, PCNET_CMDF_IOEN | PCNET_CMDF_BMEN); + + PCNetReset; + PCNetEnter32BitMode; + PCNetSetSWStyle; + PCNetGetMAC; + // OSDev has code ensuring auto selected connection... + PCNetAllocateBuffers; + PCNetDirectInit; + PCNetSetInterruptCSR; + PCNetEnableTXAutoPad; + PCNetExitConfigMode; + PCNetSetupInterrupts; + + ClassRep(&pcnet); + + "pcnet->rx_de_buffer: %X\n",pcnet.rx_de_buffer; + "pcnet->tx_de_buffer: %X\n",pcnet.tx_de_buffer; + "pcnet->rx_de_buffer_phys: %X\n",pcnet.rx_de_buffer_phys; + "pcnet->rx_de_buffer_phys: %X\n",pcnet.tx_de_buffer_phys; +} + +I64 EthernetFrameAllocate(U8 **packet_buffer_out, U8 *source_address, U8 *destination_address, U16 ethertype, I64 packet_length) +{/* Allocate an Ethernet Frame for transmit. + The source and destination addresses are copied to the Frame, as well as the ethertype. + The packet_buffer_out parameter has the value at its pointer set to the payload of the Ethernet Frame. */ + +//todo: un magic number the rest of this + U8 *ethernet_frame; + I64 de_index; + + //need to see if 3 years later VirtualBox supports APAD_XMT! + if (packet_length < ETHERNET_MIN_FRAME_SIZE) + packet_length = ETHERNET_MIN_FRAME_SIZE; + + de_index = PCNetAllocateTransmitPacket(ðernet_frame, 14 + packet_length); + + if (de_index < 0) + { + ZenithErr("Ethernet Frame Allocate failure"); + return -1; // Positive value expected. Functions calling this must factor this in. + } + + MemCopy(ethernet_frame, destination_address, MAC_ADDRESS_LENGTH); + MemCopy(ethernet_frame + MAC_ADDRESS_LENGTH, source_address, MAC_ADDRESS_LENGTH); + + *ðernet_frame[ETHERNET_ETHERTYPE_OFFSET](U16 *) = ethertype; + + *packet_buffer_out = ethernet_frame + ETHERNET_MAC_HEADER_LENGTH; + + return de_index; +} + +U64 EthernetGetMAC() +{ + return pcnet.mac_address; +} + +PCNetInit; diff --git a/src/Home/Net/ZenithStackNotes.DD b/src/Home/Net/ZenithStackNotes.DD new file mode 100644 index 0000000000000000000000000000000000000000..20618498c7372fcdf8721bbadc90cc86bd04f639 GIT binary patch literal 199 zcmY!h4$x7uF|length; i++) + checksum += mem[i]; + + if (checksum == 0) //valid checksums sum to zero + break; + } + mem += 16; //anchor sits on 16-byte boundary + } + ClassRep(*entry,,,,TRUE); + return mem != 0x100000; +} + + +U8 *SMBIOSStringGet(CSMBIOSHeader *header, I64 str_num) +{ + if (!str_num) return NULL; + + I64 i; + U8* ptr = header(U8 *) + header->length; + + for (i = 1; i < str_num; i++) + { + while (*ptr++); + if (!ptr[0] && !ptr[1]) //structure ends in double NULL + { + return NULL; + } + } + return ptr; +} + +U0 SMBIOSInit() +{ + I64 i = 1; + CSMBIOSEntryPoint *entry; + U8 *header; + + if (!SMBIOSEntryScan(&entry)) + return; + + header = entry->table_address; + + while (header(CSMBIOSHeader *)->type != 127) + { + + switch (header(CSMBIOSHeader *)->type) + { + case SMBIOSt_BIOS: + ClassRep(header(CSMBIOSBIOSInfo *),,,,TRUE); + break; + case SMBIOSt_SYSTEM: + CSMBIOSSystemInfo *info = header; + ClassRep(info,,,,TRUE); + "%s\n", SMBIOSStringGet(info, info->manufacturer); + "%z\n", info->wake_up_type, " \0Other\0Unknown\0APM\0Modem\0LAN\0Power Switch\0PCI\0AC Power"; + break; + } + + header += header(CSMBIOSHeader *)->length; + for (i = 1; header[i - 1] || header[i]; i++); + header += i + 1; + } +} + +SMBIOSInit; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Kernel/KConfig.CC b/src/Kernel/KConfig.CC index 18d85b71..0db748c8 100755 --- a/src/Kernel/KConfig.CC +++ b/src/Kernel/KConfig.CC @@ -54,7 +54,7 @@ U0 KConfigOptions(CKConfig *c) else "$$PURPLE$$%13tz$$FG$$:%Z\n",i,kernel_config_options,c->opts[i],"ST_OFF_ON"; "\nType '$$PURPLE$$Help$$FG$$' for help.\n"; - st=GetStr("Option ($$PURPLE$$$$FG$$ when done):",""); + st=StrGet("Option ($$PURPLE$$$$FG$$ when done):",""); i=ListMatch(st,kernel_config_options,LMF_IGNORE_CASE); if (i==CONFIG_HELP) "\n" @@ -85,7 +85,7 @@ U0 KConfigOptions(CKConfig *c) c->var_init_val=GetI64("Val (0-255):",255,0,255); break; case CONFIG_HOME_DIR: - st2=GetStr("Home Dir(\"%s\"):",c->home_dir); + st2=StrGet("Home Dir(\"%s\"):",c->home_dir); if (!*st2) st2=StrNew("::/Home"); else if (st2[1]!=':') { @@ -131,7 +131,7 @@ U0 KConfigOptions(CKConfig *c) c->debug_distro_file=0; c->debug_distro_start=0; if (state) { - c->debug_distro_file=GetStr("Debug Distro File:"); + c->debug_distro_file=StrGet("Debug Distro File:"); c->debug_distro_start=GetI64("Debug Distro Start:"); } break; @@ -164,7 +164,7 @@ CKConfig *KConfigNew() } - c->disk_cache_size_exp = GetStr("\nDisk Cache Size in Bytes, gets rounded-up funny, " + c->disk_cache_size_exp = StrGet("\nDisk Cache Size in Bytes, gets rounded-up funny, " "($$PURPLE$$$$FG$$ will use default.):", "Scale2Mem(0x80000,0x8000000)"); KConfigOptions(c); diff --git a/src/Kernel/KernelA.HH b/src/Kernel/KernelA.HH index 3d02e1fc..7bb7860f 100755 --- a/src/Kernel/KernelA.HH +++ b/src/Kernel/KernelA.HH @@ -16,29 +16,29 @@ extern class CIntermediateCode; extern class CJobCtrl; extern class CTask; -#define NULL 0 -#define TRUE 1 +#define NULL 0 +#define TRUE 1 #define FALSE 0 -#define ON 1 -#define OFF 0 -#define NONE 0 //for use in default arguments -#define I8_MIN (-0x80) -#define I8_MAX 0x7F -#define U8_MIN 0 -#define U8_MAX 0xFF -#define I16_MIN (-0x8000) -#define I16_MAX 0x7FFF -#define U16_MIN 0 -#define U16_MAX 0xFFFF -#define I32_MIN (-0x80000000) -#define I32_MAX 0x7FFFFFFF -#define U32_MIN 0 -#define U32_MAX 0xFFFFFFFF -#define I64_MIN (-0x8000000000000000) -#define I64_MAX 0x7FFFFFFFFFFFFFFF +#define ON 1 +#define OFF 0 +#define NONE 0 //for use in default arguments +#define I8_MIN (-0x80) +#define I8_MAX 0x7F +#define U8_MIN 0 +#define U8_MAX 0xFF +#define I16_MIN (-0x8000) +#define I16_MAX 0x7FFF +#define U16_MIN 0 +#define U16_MAX 0xFFFF +#define I32_MIN (-0x80000000) +#define I32_MAX 0x7FFFFFFF +#define U32_MIN 0 +#define U32_MAX 0xFFFFFFFF +#define I64_MIN (-0x8000000000000000) +#define I64_MAX 0x7FFFFFFFFFFFFFFF #define U64_MIN 0 -#define U64_MAX 0xFFFFFFFFFFFFFFFF -#define INVALID_PTR I64_MAX +#define U64_MAX 0xFFFFFFFFFFFFFFFF +#define INVALID_PTR I64_MAX #define STR_LEN 144 //(Int to F64 conversion is signed) @@ -46,17 +46,17 @@ extern class CTask; #define U64_F64_MAX (0x43F0000000000000(F64)) #define F64_MAX (0x7FEFFFFFFFFFFFFF(F64)) #define F64_MIN (0xFFEFFFFFFFFFFFFF(F64)) -#define inf (0x7FF0000000000000(F64)) -#define ì (0x7FF0000000000000(F64)) -#define pi (0x400921FB54442D18(F64)) -#define ã (0x400921FB54442D18(F64)) +#define inf (0x7FF0000000000000(F64)) +#define ì (0x7FF0000000000000(F64)) +#define pi (0x400921FB54442D18(F64)) +#define ã (0x400921FB54442D18(F64)) #define exp_1 (0x4005BF0A8B145769(F64)) //The number "e" #define log2_10 (0x400A934F0979A371(F64)) #define log2_e (0x3FF71547652B82FE(F64)) #define log10_2 (0x3FD34413509F79FF(F64)) #define loge_2 (0x3FE62E42FEFA39EF(F64)) #define sqrt2 (0x3FF6A09E667F3BCD(F64)) -#define eps (0x3CB0000000000000(F64)) +#define eps (0x3CB0000000000000(F64)) #help_index "Data Types/Simple" /*CosmiC union structure is treated as a @@ -2375,69 +2375,69 @@ class CUAsmGlobals #help_index "Devices;PCI" //PCI Registers, used with $LK,"PCIRead",A="MN:PCIReadU16"$ functions. -#define PCIR_VENDOR_ID 0x00 -#define PCIR_DEVICE_ID 0x02 -#define PCIR_COMMAND 0x04 -#define PCIR_STATUS 0x06 -#define PCIR_REVISION_ID 0x08 -#define PCIR_PROG_IF 0x09 -#define PCIR_SUB_CODE 0x0A -#define PCIR_CLASS_CODE 0x0B -#define PCIR_CACHE_LINE_SIZE 0x0C -#define PCIR_LATENCY_TIMER 0x0D -#define PCIR_HEADER_TYPE 0x0E -#define PCIR_BIST 0x0F -#define PCIR_BASE0 0x10 -#define PCIR_BASE1 0x14 -#define PCIR_BASE2 0x18 -#define PCIR_BASE3 0x1C -#define PCIR_BASE4 0x20 -#define PCIR_BASE5 0x24 +#define PCIR_VENDOR_ID 0x00 +#define PCIR_DEVICE_ID 0x02 +#define PCIR_COMMAND 0x04 +#define PCIR_STATUS 0x06 +#define PCIR_REVISION_ID 0x08 +#define PCIR_PROG_IF 0x09 +#define PCIR_SUB_CODE 0x0A +#define PCIR_CLASS_CODE 0x0B +#define PCIR_CACHE_LINE_SIZE 0x0C +#define PCIR_LATENCY_TIMER 0x0D +#define PCIR_HEADER_TYPE 0x0E +#define PCIR_BIST 0x0F +#define PCIR_BASE0 0x10 +#define PCIR_BASE1 0x14 +#define PCIR_BASE2 0x18 +#define PCIR_BASE3 0x1C +#define PCIR_BASE4 0x20 +#define PCIR_BASE5 0x24 #define PCIR_SUBSYS_VENDOR_ID 0x2C -#define PCIR_SUBSYS_ID 0x2E -#define PCIR_EXPANSION_ROM 0x30 -#define PCIR_CAPABILITIES 0x34 -#define PCIR_INTERRUPT_LINE 0x3C -#define PCIR_INTERRUPT_PIN 0x3D -#define PCIR_MIN_GRANT 0x3E -#define PCIR_MAX_LATENCY 0x3F +#define PCIR_SUBSYS_ID 0x2E +#define PCIR_EXPANSION_ROM 0x30 +#define PCIR_CAPABILITIES 0x34 +#define PCIR_INTERRUPT_LINE 0x3C +#define PCIR_INTERRUPT_PIN 0x3D +#define PCIR_MIN_GRANT 0x3E +#define PCIR_MAX_LATENCY 0x3F //PCI class codes -#define PCIC_STORAGE 0x1 -#define PCIC_NETWORK 0x2 +#define PCIC_STORAGE 0x1 +#define PCIC_NETWORK 0x2 //PCI subclass codes #define PCISC_ETHERNET 0x0 -#define PCISC_AHCI 0x6 +#define PCISC_AHCI 0x6 class CPCIDev { CPCIDev *next, *last; - U8 bus,dev,fun, - *vendor_str, - *dev_id_str, - class_code, - sub_code, - prog_if, - revision_id, - bist, - header_type, - latency_timer, - cache_line_size, - capabilities, - interrupt_line, - interrupt_pin, - min_grant, - max_latency; + U8 bus,dev,fun, + *vendor_str, + *dev_id_str, + class_code, + sub_code, + prog_if, + revision_id, + bist, + header_type, + latency_timer, + cache_line_size, + capabilities, + interrupt_line, + interrupt_pin, + min_grant, + max_latency; - U16 vendor_id, - device_id, - subsys_id, - subsys_vendor_id; + U16 vendor_id, + device_id, + subsys_id, + subsys_vendor_id; - U32 base[6], - erom; + U32 base[6], + erom; }; #help_index "Devices;File/System;PCI" @@ -2447,51 +2447,102 @@ public class CATARep I64 num,type,base0,base1,unit,irq; }; +//AHCI definitions +#define AHCI_SIG_ATA 0x00000101 +#define AHCI_SIG_ATAPI 0xEB140101 +#define AHCI_SIG_SEMB 0xC33C0101 //Enclosure Management Bridge... rare to encounter in the wild +#define AHCI_SIG_PM 0x96690101 //Port multiplier... not relevant to PC-type systems. + +#define AHCI_MAX_PORTS 32 +#define AHCI_PRDT_MAX_LEN 32 +#define AHCI_PRDT_BYTES_BITS 22 +#define AHCI_PRDT_BYTES (1 << 22) + +#define AHCI_GHCf_HBA_RESET 0 +#define AHCI_GHCf_INTERRUPT_ENABLE 1 +#define AHCI_GHCf_AHCI_ENABLE 31 + +#define AHCI_CAPSEXTf_BOH 0 + +#define AHCI_BOHCf_BOS 0 +#define AHCI_BOHCf_OOS 1 +#define AHCI_BOHCf_BB 4 + +#define AHCI_CHDESCf_W 6 +#define AHCI_CHDESCf_W (1 << 6) + +#define AHCI_CFDESCf_C 7 +#define AHCI_CFDESCf_C (1 << 7) + +#define AHCI_PxCMDf_ST 0 +#define AHCI_PxCMDf_SUD 1 +#define AHCI_PxCMDf_POD 2 +#define AHCI_PxCMDf_FRE 4 +#define AHCI_PxCMDf_FR 14 +#define AHCI_PxCMDf_CR 15 +#define AHCI_PxCMDf_ATAPI 24 + +#define AHCI_PxCMDF_ST (1 << 0) +#define AHCI_PxCMDF_SUD (1 << 1) +#define AHCI_PxCMDF_POD (1 << 2) +#define AHCI_PxCMDF_FRE (1 << 4) +#define AHCI_PxCMDF_FR (1 << 14) +#define AHCI_PxCMDF_CR (1 << 15) +#define AHCI_PxCMDF_ATAPI (1 << 24) + +#define AHCI_PxIEf_DP 5 +#define AHCI_PxIEf_TFE 30 + +#define AHCI_PxIEF_DP (1 << 5) +#define AHCI_PxIEF_TFE (1 << 30) + +#define AHCI_PxSCTLf_DET_INIT + //See $LK,"::/Doc/Credits.DD"$. -#define ATA_NOP 0x00 -#define ATA_DEV_RST 0x08 -#define ATA_PACKET 0xA0 -#define ATA_READ_NATIVE_MAX 0xF8 +#define ATA_NOP 0x00 +#define ATA_DEV_RST 0x08 +#define ATA_PACKET 0xA0 +#define ATA_READ_NATIVE_MAX 0xF8 #define ATA_READ_NATIVE_MAX_EXT 0x27 -#define ATA_SET_MAX 0xF9 -#define ATA_SET_MAX_EXT 0x37 -#define ATA_READ_MULTI 0xC4 -#define ATA_READ_MULTI_EXT 0x29 -#define ATA_WRITE_MULTI 0xC5 -#define ATA_WRITE_MULTI_EXT 0x39 -#define ATA_ID_DEV 0xEC +#define ATA_SET_MAX 0xF9 +#define ATA_SET_MAX_EXT 0x37 +#define ATA_READ_MULTI 0xC4 +#define ATA_READ_MULTI_EXT 0x29 +#define ATA_WRITE_MULTI 0xC5 +#define ATA_WRITE_MULTI_EXT 0x39 +#define ATA_ID_DEV 0xEC -#define ATAS_ERR 0x01 -#define ATAS_DRQ 0x08 -#define ATAS_DF 0x20 -#define ATAS_DRDY 0x40 -#define ATAS_BSY 0x80 +#define ATAS_ERR 0x01 +#define ATAS_DRQ 0x08 +#define ATAS_DF 0x20 +#define ATAS_DRDY 0x40 +#define ATAS_BSY 0x80 -#define ATAR0_DATA 0 -#define ATAR0_FEAT 1 -#define ATAR0_NSECT 2 -#define ATAR0_SECT 3 -#define ATAR0_LCYL 4 -#define ATAR0_HCYL 5 -#define ATAR0_SEL 6 -#define ATAR0_STAT 7 -#define ATAR0_CMD 7 -#define ATAR1_CTRL 2 +#define ATAR0_DATA 0 +#define ATAR0_FEAT 1 +#define ATAR0_NSECT 2 +#define ATAR0_SECT 3 +#define ATAR0_LCYL 4 +#define ATAR0_HCYL 5 +#define ATAR0_SEL 6 +#define ATAR0_STAT 7 +#define ATAR0_CMD 7 +#define ATAR1_CTRL 2 #help_index "File/FileNames" -#define FILEMASK_JIT "*.CC*;*.HH*" -#define FILEMASK_AOT "*.CC*;*.HH*;*.PRJ*" -#define FILEMASK_SRC "*.CC*;*.HH*;*.IN*;*.PRJ*" -#define FILEMASK_DD FILEMASK_SRC ";*.DD*" -#define FILEMASK_TXT FILEMASK_DD ";*.TXT*" -#define FILEMASK_GR "*.GR*" +#define FILEMASK_JIT "*.CC*;*.HH*" +#define FILEMASK_AOT "*.CC*;*.HH*;*.PRJ*" +#define FILEMASK_SRC "*.CC*;*.HH*;*.IN*;*.PRJ*" +#define FILEMASK_DD FILEMASK_SRC ";*.DD*" +#define FILEMASK_TXT FILEMASK_DD ";*.TXT*" +#define FILEMASK_GR "*.GR*" #help_index "File/Low Level" #define BLK_SIZE_BITS 9 -#define BLK_SIZE (1< #define GSF_WITH_NEW_LINE 2 diff --git a/src/Kernel/KernelC.HH b/src/Kernel/KernelC.HH index 4d0620e3..203487eb 100755 --- a/src/Kernel/KernelC.HH +++ b/src/Kernel/KernelC.HH @@ -500,14 +500,14 @@ extern CJob sys_macro_head; extern CTask *sys_macro_task; #help_index "Keyboard Devices;Char/Input;StdIn" -extern U8 *(*fp_getstr2)(I64 flags=0); //GetStr $LK,"Flags",A="MN:GSF_SHIFT_ESC_EXIT"$ +extern U8 *(*fp_getstr2)(I64 flags=0); //StrGet $LK,"Flags",A="MN:GSF_SHIFT_ESC_EXIT"$ public extern Bool AreYouSure(); public extern I64 GetChar(I64 *_scan_code=NULL,Bool echo=TRUE, Bool raw_cursor=FALSE); public extern I64 GetKey(I64 *_scan_code=NULL,Bool echo=FALSE, Bool raw_cursor=FALSE); public extern I64 GetS(U8 *buf,I64 size,Bool allow_ext=TRUE); -public extern U8 *GetStr(U8 *message=NULL,U8 *default=NULL,I64 flags=0); +public extern U8 *StrGet(U8 *message=NULL,U8 *default=NULL,I64 flags=0); extern U0 KbdInit(); public extern I64 KbdMouseEventTime(); extern U0 KbdMouseHandler(Bool poll_kbd,Bool poll_mouse); diff --git a/src/Kernel/SerialDev/Message.CC b/src/Kernel/SerialDev/Message.CC index ef9e945f..d1d4a15f 100755 --- a/src/Kernel/SerialDev/Message.CC +++ b/src/Kernel/SerialDev/Message.CC @@ -190,7 +190,7 @@ I64 GetChar(I64 *_scan_code=NULL,Bool echo=TRUE,Bool raw_cursor=FALSE) return ch1; } -U8 *GetStr(U8 *message=NULL,U8 *default=NULL,I64 flags=0) +U8 *StrGet(U8 *message=NULL,U8 *default=NULL,I64 flags=0) {//Returns a $LK,"MAlloc",A="MN:MAlloc"$()ed prompted string. See $LK,"Flags",A="MN:GSF_SHIFT_ESC_EXIT"$. U8 *st; if (message) @@ -212,7 +212,7 @@ I64 GetS(U8 *buf,I64 size,Bool allow_ext=TRUE) I64 ch,i=0; if (!size || !buf) return 0; if (allow_ext) { - st=GetStr; + st=StrGet; if (StrLen(st)>size-1) { MemCopy(buf,st,size-1); buf[size-1]=0; diff --git a/src/Misc/OSInstall.CC b/src/Misc/OSInstall.CC index 4ca7640b..6afc7223 100755 --- a/src/Misc/OSInstall.CC +++ b/src/Misc/OSInstall.CC @@ -94,7 +94,7 @@ U0 RegularInstallWiz() num_hints=ATARep(FALSE,,&head); "\nInclude '$$PURPLE$$0x$$FG$$' for hexidecimal numbers.\n\n"; while (TRUE) { - base0=GetStr("Hard Drive I/O Port Base0 : "); + base0=StrGet("Hard Drive I/O Port Base0 : "); if (0global_name=GetStr("Global Struct Name (ENTER for No Global):"); + res->global_name=StrGet("Global Struct Name (ENTER for No Global):"); res->range=GetI64 ("Range (%4d):",30); res->spacing=GetI64("Spacing (%4d):",20); res->border=GetI64 ("Border (%4d):",2); @@ -28,7 +28,7 @@ CTemplateCS *CtrlSliderGet() res->next_slider=res->last_slider=&res->next_slider; while (TRUE) { StrPrint(prompt,"Slider #%d Name:",res->num_sliders+1); - st=GetStr(prompt); + st=StrGet(prompt); if (!*st) { Free(st); break; diff --git a/src/Zenith/DolDoc/DocGet.CC b/src/Zenith/DolDoc/DocGet.CC index 961e368a..9f1103ee 100755 --- a/src/Zenith/DolDoc/DocGet.CC +++ b/src/Zenith/DolDoc/DocGet.CC @@ -177,7 +177,7 @@ public I64 GetI64(U8 *message=NULL,I64 default=0,I64 lo=I64_MIN,I64 hi=I64_MAX) while (TRUE) { if (message) "" message,default; - st=GetStr; + st=StrGet; if (!*st) { Free(st); return default; @@ -203,7 +203,7 @@ public F64 GetF64(U8 *message=NULL,F64 default=0,F64 lo=F64_MIN,F64 hi=F64_MAX) while (TRUE) { if (message) "" message,default; - st=GetStr; + st=StrGet; if (!*st) { Free(st); return default; @@ -230,7 +230,7 @@ public CDate GetDate(U8 *message=NULL,CDate default=I64_MIN, while (TRUE) { if (message) "" message,default,default; - st=GetStr; + st=StrGet; if (!*st) { Free(st); return default; diff --git a/src/Zenith/DolDoc/DocPopUp.CC b/src/Zenith/DolDoc/DocPopUp.CC index f5dceac7..8799a390 100755 --- a/src/Zenith/DolDoc/DocPopUp.CC +++ b/src/Zenith/DolDoc/DocPopUp.CC @@ -164,7 +164,7 @@ U8 *PopUpGetStr2(U8 *header,CTask *mem_task) U8 *res,*st; if (header) "%s",header; - st=GetStr(,,GSF_WITH_NEW_LINE); + st=StrGet(,,GSF_WITH_NEW_LINE); res=StrNew(st,mem_task); Free(st); return res; diff --git a/src/Zenith/ZBlkDev/Mount.CC b/src/Zenith/ZBlkDev/Mount.CC index d417ebc6..af204aa8 100755 --- a/src/Zenith/ZBlkDev/Mount.CC +++ b/src/Zenith/ZBlkDev/Mount.CC @@ -43,7 +43,7 @@ U8 Mount2(U8 boot_drive_let,CDoc *_doc,Bool _caller_is_prtdisk) GetS(blks_buf,STR_LEN); break; case BDT_ISO_FILE_READ: - filename=GetStr("File Name:"); + filename=StrGet("File Name:"); break; case BDT_ATA: prt_num=GetI64("Partition Num (Default=All):",prt_num); diff --git a/src/Zenith/ZDebug.CC b/src/Zenith/ZDebug.CC index 4ef99fa1..6f614d2c 100755 --- a/src/Zenith/ZDebug.CC +++ b/src/Zenith/ZDebug.CC @@ -1,6 +1,5 @@ #help_index "Debugging/Dump" -Bool ClassRep2(CDoc *doc,U8 *_d,U8 *class_name=lastclass,Bool u8_chars, - I64 depth,I64 max_depth,Bool dynamic,I64 types=HTT_CLASS,I64 offset=0) +Bool ClassRep2(CDoc *doc,U8 *_d,U8 *class_name=lastclass,Bool u8_chars,Bool force,I64 depth,I64 max_depth,Bool dynamic,I64 types=HTT_CLASS,I64 offset=0) {//See $LK,"::/Demo/LastClass.CC"$. I64 i,j,stars,*ptr; CMemberList *ml; @@ -12,7 +11,7 @@ Bool ClassRep2(CDoc *doc,U8 *_d,U8 *class_name=lastclass,Bool u8_chars, DocPrint(doc,"Class Not Found.\n"); return FALSE; } - if (!CheckPtr(_d) || !CheckPtr(_d(U8 *)+tmpc->size)) { + if (!force && (!CheckPtr(_d) || !CheckPtr(_d(U8 *)+tmpc->size))) { DocPrint(doc,"Bad Ptr:%016X\n",_d); return FALSE; } @@ -143,9 +142,9 @@ Bool ClassRep2(CDoc *doc,U8 *_d,U8 *class_name=lastclass,Bool u8_chars, DocPrint(doc,"$$TR,\"%s\"$$\n",ml->str); DocPrint(doc,"$$ID,2$$"); if (!stars) - ClassRep2(doc,ptr,tmpc2->str,u8_chars,depth+1,max_depth,dynamic); + ClassRep2(doc,ptr,tmpc2->str,u8_chars,force,depth+1,max_depth,dynamic); else if (stars==1) - ClassRep2(doc,*ptr,tmpc2->str,u8_chars,depth+1,max_depth,dynamic); + ClassRep2(doc,*ptr,tmpc2->str,u8_chars,force,depth+1,max_depth,dynamic); DocPrint(doc,"$$ID,-2$$"); } } else @@ -158,8 +157,7 @@ Bool ClassRep2(CDoc *doc,U8 *_d,U8 *class_name=lastclass,Bool u8_chars, return TRUE; } -public U0 ClassRep(U8 *_d,U8 *class_name=lastclass, - I64 max_depth=2,Bool u8_chars=FALSE,Bool fun=FALSE,I64 offset=0) +public U0 ClassRep(U8 *_d, U8 *class_name=lastclass, I64 max_depth=2, Bool u8_chars=FALSE, Bool force=FALSE, Bool fun=FALSE, I64 offset=0) {//Displays members of a record by using the compiler's info. CDoc *doc; I64 type; @@ -176,7 +174,7 @@ public U0 ClassRep(U8 *_d,U8 *class_name=lastclass, else type=HTT_CLASS; - ClassRep2(doc,_d,class_name,u8_chars,0,max_depth,FALSE,type,offset); + ClassRep2(doc,_d,class_name,u8_chars,force,0,max_depth,FALSE,type,offset); DocPrint(doc,"\n"); DocRecalc(doc); @@ -189,7 +187,7 @@ public U0 ClassRep(U8 *_d,U8 *class_name=lastclass, } public U0 ClassRepD(U8 *_d,U8 *class_name=lastclass, - I64 max_depth=2,Bool u8_chars=FALSE,Bool fun=FALSE,I64 offset=0) + I64 max_depth=2,Bool u8_chars=FALSE,Bool force=FALSE,Bool fun=FALSE,I64 offset=0) {//Dynamic ClassRep. Uses hex_ed widget for live changes. CDoc *doc; if (IsRaw) @@ -199,9 +197,9 @@ public U0 ClassRepD(U8 *_d,U8 *class_name=lastclass, doc=DocPut; } if (fun) - ClassRep2(doc,_d,class_name,u8_chars,0,max_depth,TRUE,HTT_FUN,offset); + ClassRep2(doc,_d,class_name,u8_chars,force,0,max_depth,TRUE,HTT_FUN,offset); else - ClassRep2(doc,_d,class_name,u8_chars,0,max_depth,TRUE,HTT_CLASS,offset); + ClassRep2(doc,_d,class_name,u8_chars,force,0,max_depth,TRUE,HTT_CLASS,offset); DocPrint(doc,"\n"); DocRecalc(doc); if (IsRaw) { @@ -240,10 +238,10 @@ public U0 FunRep(U8 *st,U8 *rbp=NULL,I64 max_depth=2,CTask *task=NULL) img=MAlloc(size); MemCopy(img,rbp+tmpf->size,size); UpdateRegVarImg(tmpf,img-tmpf->size,task); - ClassRep(img-tmpf->size,st,max_depth,FALSE,TRUE,rbp-img+tmpf->size); + ClassRep(img-tmpf->size,st,max_depth,FALSE,FALSE,TRUE,rbp-img+tmpf->size); Free(img); } else - ClassRep(rbp,st,max_depth,FALSE,TRUE); + ClassRep(rbp,st,max_depth,FALSE,FALSE,TRUE); } else { tmpm=tmpf->member_list_and_root; while (tmpm) {