mirror of
https://github.com/Zeal-Operating-System/ZealOS.git
synced 2024-12-29 00:36:32 +00:00
802 lines
76 KiB
HTML
Executable file
802 lines
76 KiB
HTML
Executable file
<!DOCTYPE HTML>
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html;charset=US-ASCII">
|
|
<meta name="generator" content="ZealOS V1.00">
|
|
<style type="text/css">
|
|
body {background-color:#fef1f0;}
|
|
.cF0{color:#000000;background-color:#fef1f0;}
|
|
.cF1{color:#0148a4;background-color:#fef1f0;}
|
|
.cF2{color:#3b7901;background-color:#fef1f0;}
|
|
.cF3{color:#057c7e;background-color:#fef1f0;}
|
|
.cF4{color:#bb2020;background-color:#fef1f0;}
|
|
.cF5{color:#9e42ae;background-color:#fef1f0;}
|
|
.cF6{color:#b57901;background-color:#fef1f0;}
|
|
.cF7{color:#b2b6af;background-color:#fef1f0;}
|
|
.cF8{color:#555753;background-color:#fef1f0;}
|
|
.cF9{color:#678fbb;background-color:#fef1f0;}
|
|
.cFA{color:#82bc49;background-color:#fef1f0;}
|
|
.cFB{color:#0097a2;background-color:#fef1f0;}
|
|
.cFC{color:#e26a6a;background-color:#fef1f0;}
|
|
.cFD{color:#c671bc;background-color:#fef1f0;}
|
|
.cFE{color:#c7ab00;background-color:#fef1f0;}
|
|
.cFF{color:#fef1f0;background-color:#fef1f0;}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<pre style="font-family:monospace;font-size:12pt">
|
|
<a name="l1"></a><span class=cF2>/*</span><span class=cF0> </span><span class=cF2>AMD PCNetII Driver</span><span class=cF0>
|
|
<a name="l2"></a> </span><span class=cF2>Author: TomAwezome</span><span class=cF0>
|
|
<a name="l3"></a>
|
|
<a name="l4"></a> </span><span class=cF2>Driver is based on:</span><span class=cF0>
|
|
<a name="l5"></a> </span><span class=cF2>-</span><span class=cF0> </span><span class=cF2>minexew's ShrineOS PCNet.CC implementation</span><span class=cF0>
|
|
<a name="l6"></a> </span><span class=cF2>-</span><span class=cF0> </span><span class=cF2>OSDev AMD_PCNET documentation</span><span class=cF0>
|
|
<a name="l7"></a> </span><span class=cF2>-</span><span class=cF0> </span><span class=cF2>AMD PCnet(TM)-PCI datasheet</span><span class=cF0>
|
|
<a name="l8"></a> </span><span class=cF2>-</span><span class=cF0> </span><span class=cF2>any other useful sources.</span><span class=cF0>
|
|
<a name="l9"></a>
|
|
<a name="l10"></a> </span><span class=cF2>Guidelines:</span><span class=cF0>
|
|
<a name="l11"></a> </span><span class=cF2>-</span><span class=cF0> </span><span class=cF2>Magic numbers are bad. #defines are good.</span><span class=cF0>
|
|
<a name="l12"></a> </span><span class=cF2>-</span><span class=cF0> </span><span class=cF2>Understandability over LOC.</span><span class=cF0>
|
|
<a name="l13"></a> </span><span class=cF2>-</span><span class=cF0> </span><span class=cF2>Clear documentation.</span><span class=cF0>
|
|
<a name="l14"></a></span><span class=cF2>*/</span><span class=cF0>
|
|
<a name="l15"></a>
|
|
<a name="l16"></a></span><span class=cF2>//#define</span><span class=cF0> </span><span class=cF2>PCNET_DEVICE_ID</span><span class=cF0> </span><span class=cF2>0x2000</span><span class=cF0>
|
|
<a name="l17"></a></span><span class=cF2>//#define</span><span class=cF0> </span><span class=cF2>PCNET_VENDOR_ID</span><span class=cF0> </span><span class=cF2>0x1022</span><span class=cF0>
|
|
<a name="l18"></a>
|
|
<a name="l19"></a></span><span class=cF2>//#define</span><span class=cF0> </span><span class=cF2>PCI_REG_COMMAND</span><span class=cF0> </span><span class=cF2>0x04</span><span class=cF0>
|
|
<a name="l20"></a>
|
|
<a name="l21"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CMDf_IOEN </span><span class=cFE>0</span><span class=cF0>
|
|
<a name="l22"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CMDf_BMEN </span><span class=cFE>2</span><span class=cF0>
|
|
<a name="l23"></a>
|
|
<a name="l24"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CMDF_IOEN (</span><span class=cFE>1</span><span class=cF0> << PCNET_CMDf_IOEN)
|
|
<a name="l25"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CMDF_BMEN (</span><span class=cFE>1</span><span class=cF0> << PCNET_CMDf_BMEN)
|
|
<a name="l26"></a>
|
|
<a name="l27"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_WD_RESET </span><span class=cFE>0x14</span><span class=cF0> </span><span class=cF2>// reset reg location when card is in 16-bit mode</span><span class=cF0>
|
|
<a name="l28"></a>
|
|
<a name="l29"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_DW_RDP </span><span class=cFE>0x10</span><span class=cF0>
|
|
<a name="l30"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_DW_RAP </span><span class=cFE>0x14</span><span class=cF0>
|
|
<a name="l31"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_DW_RESET </span><span class=cFE>0x18</span><span class=cF0> </span><span class=cF2>// reset reg location when card is in 32-bit mode</span><span class=cF0>
|
|
<a name="l32"></a>
|
|
<a name="l33"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_CTRLSTATUS </span><span class=cFE>0</span><span class=cF0>
|
|
<a name="l34"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_INTERRUPTS </span><span class=cFE>3</span><span class=cF0>
|
|
<a name="l35"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_FEATURECTRL </span><span class=cFE>4</span><span class=cF0>
|
|
<a name="l36"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_LADRF0 </span><span class=cFE>8</span><span class=cF0>
|
|
<a name="l37"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_LADRF1 </span><span class=cFE>9</span><span class=cF0>
|
|
<a name="l38"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_LADRF2 </span><span class=cFE>10</span><span class=cF0>
|
|
<a name="l39"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_LADRF3 </span><span class=cFE>11</span><span class=cF0>
|
|
<a name="l40"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_PADR0 </span><span class=cFE>12</span><span class=cF0>
|
|
<a name="l41"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_PADR1 </span><span class=cFE>13</span><span class=cF0>
|
|
<a name="l42"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_PADR2 </span><span class=cFE>14</span><span class=cF0>
|
|
<a name="l43"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_MODE </span><span class=cFE>15</span><span class=cF0>
|
|
<a name="l44"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_BADRL </span><span class=cFE>24</span><span class=cF0>
|
|
<a name="l45"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_BADRU </span><span class=cFE>25</span><span class=cF0>
|
|
<a name="l46"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_BADTL </span><span class=cFE>30</span><span class=cF0>
|
|
<a name="l47"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_BADTU </span><span class=cFE>31</span><span class=cF0>
|
|
<a name="l48"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_POLLINT </span><span class=cFE>47</span><span class=cF0>
|
|
<a name="l49"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_SOFTWARESTYLE </span><span class=cFE>58</span><span class=cF0>
|
|
<a name="l50"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_RXRINGLEN </span><span class=cFE>76</span><span class=cF0>
|
|
<a name="l51"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CSR_TXRINGLEN </span><span class=cFE>78</span><span class=cF0>
|
|
<a name="l52"></a>
|
|
<a name="l53"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_SWSTYLE_SELECTION </span><span class=cFE>2</span><span class=cF0> </span><span class=cF2>// (value, not bit) AMD PCNet datasheet p. 1-968</span><span class=cF0>
|
|
<a name="l54"></a>
|
|
<a name="l55"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_SWSTYLE_SSIZE32 </span><span class=cFE>8</span><span class=cF0> </span><span class=cF2>// Bit 8 of SWSTYLE</span><span class=cF0>
|
|
<a name="l56"></a>
|
|
<a name="l57"></a></span><span class=cF2>// Refer to AMD PCNet datasheet p. 1-954, 1-956, 1-957 for Interrupt Mask details.</span><span class=cF0>
|
|
<a name="l58"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_INT_BSWP </span><span class=cFE>2</span><span class=cF0> </span><span class=cF2>// Byte Swap (Big-Endian / Little-Endian)</span><span class=cF0>
|
|
<a name="l59"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_INT_IDONM </span><span class=cFE>8</span><span class=cF0> </span><span class=cF2>// Initialization Done Mask</span><span class=cF0>
|
|
<a name="l60"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_INT_TINTM </span><span class=cFE>9</span><span class=cF0> </span><span class=cF2>// Transmit Interrupt Mask</span><span class=cF0>
|
|
<a name="l61"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_INT_RINTM </span><span class=cFE>10</span><span class=cF0> </span><span class=cF2>// Receive Interrupt Mask</span><span class=cF0>
|
|
<a name="l62"></a>
|
|
<a name="l63"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_FEATURE_APADXMT </span><span class=cFE>11</span><span class=cF0>
|
|
<a name="l64"></a>
|
|
<a name="l65"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CTRL_INIT </span><span class=cFE>0</span><span class=cF0>
|
|
<a name="l66"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CTRL_STRT </span><span class=cFE>1</span><span class=cF0>
|
|
<a name="l67"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CTRL_STOP </span><span class=cFE>2</span><span class=cF0>
|
|
<a name="l68"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_CTRL_RINT </span><span class=cFE>10</span><span class=cF0>
|
|
<a name="l69"></a>
|
|
<a name="l70"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_RX_BUFF_COUNT </span><span class=cFE>32</span><span class=cF0> </span><span class=cF2>// Linux & Shrine Driver use 32 and 8 for</span><span class=cF0>
|
|
<a name="l71"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_TX_BUFF_COUNT </span><span class=cFE>8</span><span class=cF0> </span><span class=cF2>// these, we could allow more if wanted.</span><span class=cF0>
|
|
<a name="l72"></a>
|
|
<a name="l73"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_DESCRIPTORf_ENP </span><span class=cFE>24</span><span class=cF0>
|
|
<a name="l74"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_DESCRIPTORf_STP </span><span class=cFE>25</span><span class=cF0>
|
|
<a name="l75"></a>#</span><span class=cF1>define</span><span class=cF0> PCNET_DESCRIPTORf_OWN </span><span class=cFE>31</span><span class=cF0> </span><span class=cF2>// AMD PCNet datasheet p.1-992, 1-994</span><span class=cF0>
|
|
<a name="l76"></a>
|
|
<a name="l77"></a></span><span class=cF1>class</span><span class=cF0> CPCNet
|
|
<a name="l78"></a>{
|
|
<a name="l79"></a> </span><span class=cF9>CPCIDev</span><span class=cF0> *pci;
|
|
<a name="l80"></a>
|
|
<a name="l81"></a> </span><span class=cF1>U8</span><span class=cF0> mac_address[</span><span class=cFE>6</span><span class=cF0>]; </span><span class=cF2>// MAC address is first 6 bytes of PCNet EEPROM</span><span class=cF0> </span><span class=cF2>(page # ? )</span><span class=cF0>
|
|
<a name="l82"></a>
|
|
<a name="l83"></a> </span><span class=cF9>I64</span><span class=cF0> current_rx_de_index; </span><span class=cF2>// Current Receive DE being processed. Gets incremented, wrapped to 0 at max of PCNET_RX_BUFF_COUNT.</span><span class=cF0>
|
|
<a name="l84"></a> </span><span class=cF9>I64</span><span class=cF0> current_tx_de_index; </span><span class=cF2>// Current Transmit DE being processed. Gets incremented, wrapped to 0 at max of PCNET_TX_BUFF_COUNT.</span><span class=cF0>
|
|
<a name="l85"></a>
|
|
<a name="l86"></a> </span><span class=cF1>U8</span><span class=cF0> *rx_de_buffer; </span><span class=cF2>// Uncached-alias of pointer to the buffer of RX Descriptor Entries.</span><span class=cF0>
|
|
<a name="l87"></a> </span><span class=cF1>U8</span><span class=cF0> *tx_de_buffer; </span><span class=cF2>// Uncached-alias of pointer to the buffer of TX Descriptor Entries.</span><span class=cF0>
|
|
<a name="l88"></a> </span><span class=cF1>U8</span><span class=cF0> *rx_de_buffer_phys; </span><span class=cF2>// Pointer to the buffer of RX Descriptor Entries. (Code Heap, lower 2Gb)</span><span class=cF0>
|
|
<a name="l89"></a> </span><span class=cF1>U8</span><span class=cF0> *tx_de_buffer_phys; </span><span class=cF2>// Pointer to the buffer of TX Descriptor Entries. (Code Heap, lower 2Gb)</span><span class=cF0>
|
|
<a name="l90"></a>
|
|
<a name="l91"></a> </span><span class=cF9>U32</span><span class=cF0> rx_buffer_addr; </span><span class=cF2>// Uncached-alias of address of receive buffers.</span><span class=cF0>
|
|
<a name="l92"></a> </span><span class=cF9>U32</span><span class=cF0> tx_buffer_addr; </span><span class=cF2>// Uncached-alias of address of transmit buffers.</span><span class=cF0>
|
|
<a name="l93"></a> </span><span class=cF9>U32</span><span class=cF0> rx_buffer_addr_phys; </span><span class=cF2>// Physical address of actual receive buffers (< 4 Gb)</span><span class=cF0>
|
|
<a name="l94"></a> </span><span class=cF9>U32</span><span class=cF0> tx_buffer_addr_phys; </span><span class=cF2>// Physical address of actual transmit buffers (< 4 Gb)</span><span class=cF0>
|
|
<a name="l95"></a>
|
|
<a name="l96"></a>} pcnet; </span><span class=cF2>// pcnet is the global variable we store all of this into.</span><span class=cF0>
|
|
<a name="l97"></a>
|
|
<a name="l98"></a></span><span class=cF1>class</span><span class=cF0> CPCNetDescriptorEntry
|
|
<a name="l99"></a>{</span><span class=cF2>/* AMD PCNet datasheet p.1-991 & p.1-994 NOTE: chart typo on 1-994, see ONES and BCNT on 1-995.</span><span class=cF0>
|
|
<a name="l100"></a> </span><span class=cF2>TX and RX DE's are the same size (16-Bytes) and structure,</span><span class=cF0>
|
|
<a name="l101"></a> </span><span class=cF2>but have different registers and functions.</span><span class=cF0>
|
|
<a name="l102"></a> </span><span class=cF2>The RX and TX DE buffers of the CPCNet class</span><span class=cF0>
|
|
<a name="l103"></a> </span><span class=cF2>are allocated to a certain amount of these DEs. */</span><span class=cF0>
|
|
<a name="l104"></a>
|
|
<a name="l105"></a> </span><span class=cF9>U32</span><span class=cF0> buffer_addr;
|
|
<a name="l106"></a> </span><span class=cF9>U32</span><span class=cF0> status1;
|
|
<a name="l107"></a> </span><span class=cF9>U32</span><span class=cF0> status2;
|
|
<a name="l108"></a> </span><span class=cF9>U32</span><span class=cF0> reserved;
|
|
<a name="l109"></a>};
|
|
<a name="l110"></a>
|
|
<a name="l111"></a></span><span class=cF1>class</span><span class=cF0> CPCNetBufferSetup
|
|
<a name="l112"></a>{
|
|
<a name="l113"></a> </span><span class=cF9>U16</span><span class=cF0> mode;
|
|
<a name="l114"></a> </span><span class=cF1>U8</span><span class=cF0> rlen;
|
|
<a name="l115"></a> </span><span class=cF1>U8</span><span class=cF0> tlen;
|
|
<a name="l116"></a> </span><span class=cF1>U8</span><span class=cF0> mac[</span><span class=cFE>6</span><span class=cF0>];
|
|
<a name="l117"></a> </span><span class=cF9>U16</span><span class=cF0> reserved;
|
|
<a name="l118"></a> </span><span class=cF1>U8</span><span class=cF0> ladr[</span><span class=cFE>8</span><span class=cF0>];
|
|
<a name="l119"></a> </span><span class=cF9>U32</span><span class=cF0> rxbuf;
|
|
<a name="l120"></a> </span><span class=cF9>U32</span><span class=cF0> txbuf;
|
|
<a name="l121"></a>};
|
|
<a name="l122"></a>
|
|
<a name="l123"></a></span><span class=cF9>CPCIDev</span><span class=cF0> *PCNetPCIDevFind()
|
|
<a name="l124"></a>{</span><span class=cF2>// Find and return PCNetII card as a CPCIDev pointer.</span><span class=cF0>
|
|
<a name="l125"></a>
|
|
<a name="l126"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF5>PCIDevFind</span><span class=cF0>(,, PCIV_PCNET, PCID_PCNET);
|
|
<a name="l127"></a>}
|
|
<a name="l128"></a>
|
|
<a name="l129"></a></span><span class=cF9>U32</span><span class=cF0> PCNetIOBaseGet()
|
|
<a name="l130"></a>{</span><span class=cF2>/* Return memory IO base address</span><span class=cF0>
|
|
<a name="l131"></a> </span><span class=cF2>of PCNet card. Bits 0-4 are not</span><span class=cF0>
|
|
<a name="l132"></a> </span><span class=cF2>for the IO base, so an AND with</span><span class=cF0>
|
|
<a name="l133"></a> </span><span class=cF2>~0x1F ignores those bits. */</span><span class=cF0>
|
|
<a name="l134"></a>
|
|
<a name="l135"></a> </span><span class=cF9>U32</span><span class=cF0> io_base = pcnet.pci->base[</span><span class=cFE>0</span><span class=cF0>] & ~</span><span class=cFE>0x1F</span><span class=cF0>;
|
|
<a name="l136"></a> </span><span class=cF1>return</span><span class=cF0> io_base;
|
|
<a name="l137"></a>}
|
|
<a name="l138"></a>
|
|
<a name="l139"></a></span><span class=cF1>U0</span><span class=cF0> PCNetReset()
|
|
<a name="l140"></a>{</span><span class=cF2>/* Reads the 32- and 16-bit RESET registers,</span><span class=cF0>
|
|
<a name="l141"></a> </span><span class=cF2>which, regardless of which mode the card is in,</span><span class=cF0>
|
|
<a name="l142"></a> </span><span class=cF2>will reset it back to 16-bit mode. */</span><span class=cF0>
|
|
<a name="l143"></a>
|
|
<a name="l144"></a> </span><span class=cF5>InU32</span><span class=cF0>(PCNetIOBaseGet + PCNET_DW_RESET);
|
|
<a name="l145"></a> </span><span class=cF5>InU16</span><span class=cF0>(PCNetIOBaseGet + PCNET_WD_RESET);
|
|
<a name="l146"></a> </span><span class=cF5>Busy</span><span class=cF0>(</span><span class=cFE>5</span><span class=cF0>); </span><span class=cF2>// OSDev says minimum 1 uS</span><span class=cF0>
|
|
<a name="l147"></a>}
|
|
<a name="l148"></a>
|
|
<a name="l149"></a></span><span class=cF1>U0</span><span class=cF0> PCNet32BitModeEnable()
|
|
<a name="l150"></a>{</span><span class=cF2>/* AMD PCNet datasheet p. 1-930</span><span class=cF0>
|
|
<a name="l151"></a> </span><span class=cF2>Summary: A 32-bit write (while in 16-bit mode)</span><span class=cF0>
|
|
<a name="l152"></a> </span><span class=cF2>to RDP will cause 16-bit mode exit</span><span class=cF0>
|
|
<a name="l153"></a> </span><span class=cF2>and immediate enter into 32-bit mode. */</span><span class=cF0>
|
|
<a name="l154"></a>
|
|
<a name="l155"></a> </span><span class=cF5>OutU32</span><span class=cF0>(PCNetIOBaseGet + PCNET_DW_RDP, </span><span class=cFE>0</span><span class=cF0>);
|
|
<a name="l156"></a>}
|
|
<a name="l157"></a>
|
|
<a name="l158"></a></span><span class=cF1>U0</span><span class=cF0> PCNetRAPWrite(</span><span class=cF9>U32</span><span class=cF0> value)
|
|
<a name="l159"></a>{</span><span class=cF2>/* AMD PCNet datasheet p. 1-952</span><span class=cF0>
|
|
<a name="l160"></a> </span><span class=cF2>Summary: Register Address Pointer register</span><span class=cF0>
|
|
<a name="l161"></a> </span><span class=cF2>value will indicate which CSR / BCR register</span><span class=cF0>
|
|
<a name="l162"></a> </span><span class=cF2>we want to access in RDP / BDP. */</span><span class=cF0>
|
|
<a name="l163"></a>
|
|
<a name="l164"></a> </span><span class=cF5>OutU32</span><span class=cF0>(PCNetIOBaseGet + PCNET_DW_RAP, value);
|
|
<a name="l165"></a>}
|
|
<a name="l166"></a>
|
|
<a name="l167"></a></span><span class=cF1>U0</span><span class=cF0> PCNetCSRWrite(</span><span class=cF9>U32</span><span class=cF0> csr, </span><span class=cF9>U32</span><span class=cF0> value)
|
|
<a name="l168"></a>{</span><span class=cF2>/* AMD PCNet datasheet p. 1-952</span><span class=cF0>
|
|
<a name="l169"></a> </span><span class=cF2>Summary: Control and Status Registers are</span><span class=cF0>
|
|
<a name="l170"></a> </span><span class=cF2>accessed via the RDP (Register Data Port).</span><span class=cF0>
|
|
<a name="l171"></a> </span><span class=cF2>Which CSR is selected is based on the value</span><span class=cF0>
|
|
<a name="l172"></a> </span><span class=cF2>in the RAP. */</span><span class=cF0>
|
|
<a name="l173"></a>
|
|
<a name="l174"></a> PCNetRAPWrite(csr);
|
|
<a name="l175"></a> </span><span class=cF5>OutU32</span><span class=cF0>(PCNetIOBaseGet + PCNET_DW_RDP, value);
|
|
<a name="l176"></a>}
|
|
<a name="l177"></a>
|
|
<a name="l178"></a></span><span class=cF9>U32</span><span class=cF0> PCNetCSRRead(</span><span class=cF9>U32</span><span class=cF0> csr)
|
|
<a name="l179"></a>{</span><span class=cF2>/* AMD PCNet datasheet p. 1-952</span><span class=cF0>
|
|
<a name="l180"></a> </span><span class=cF2>Summary: Control and Status Registers are</span><span class=cF0>
|
|
<a name="l181"></a> </span><span class=cF2>accessed via the RDP (Register Data Port).</span><span class=cF0>
|
|
<a name="l182"></a> </span><span class=cF2>Which CSR is selected is based on the value</span><span class=cF0>
|
|
<a name="l183"></a> </span><span class=cF2>in the RAP. */</span><span class=cF0>
|
|
<a name="l184"></a>
|
|
<a name="l185"></a> PCNetRAPWrite(csr);
|
|
<a name="l186"></a> </span><span class=cF1>return</span><span class=cF0> </span><span class=cF5>InU32</span><span class=cF0>(PCNetIOBaseGet + PCNET_DW_RDP);
|
|
<a name="l187"></a>}
|
|
<a name="l188"></a>
|
|
<a name="l189"></a></span><span class=cF1>U0</span><span class=cF0> PCNetSWStyleSet()
|
|
<a name="l190"></a>{</span><span class=cF2>/* AMD PCNet datasheet p. 1-968</span><span class=cF0>
|
|
<a name="l191"></a> </span><span class=cF2>In CSR58 (Software Style), the 8-bit</span><span class=cF0>
|
|
<a name="l192"></a> </span><span class=cF2>SWSTYLE register dictates interpretation of certain</span><span class=cF0>
|
|
<a name="l193"></a> </span><span class=cF2>bits in the CSR space, and widths of descriptors and</span><span class=cF0>
|
|
<a name="l194"></a> </span><span class=cF2>initialization block. In PCINet-PCI mode, CSR4 bits</span><span class=cF0>
|
|
<a name="l195"></a> </span><span class=cF2>function as defined in the datasheet , and TMD1[29]</span><span class=cF0>
|
|
<a name="l196"></a> </span><span class=cF2>functions as ADD_FCS. */</span><span class=cF0>
|
|
<a name="l197"></a>
|
|
<a name="l198"></a> </span><span class=cF9>U32</span><span class=cF0> csr = PCNetCSRRead(PCNET_CSR_SOFTWARESTYLE);
|
|
<a name="l199"></a>
|
|
<a name="l200"></a> csr &= ~</span><span class=cFE>0xFF</span><span class=cF0>; </span><span class=cF2>// clears first 8 bits: SWSTYLE 8-bit register.</span><span class=cF0>
|
|
<a name="l201"></a> csr |= PCNET_SWSTYLE_SELECTION; </span><span class=cF2>// set SWSTYLE to PCNet-PCI mode.</span><span class=cF0>
|
|
<a name="l202"></a> </span><span class=cF5>Bts</span><span class=cF0>(&csr, PCNET_SWSTYLE_SSIZE32); </span><span class=cF2>// set SSIZE32 bit 1</span><span class=cF0>
|
|
<a name="l203"></a>
|
|
<a name="l204"></a> PCNetCSRWrite(PCNET_CSR_SOFTWARESTYLE, csr);
|
|
<a name="l205"></a>}
|
|
<a name="l206"></a>
|
|
<a name="l207"></a></span><span class=cF1>U0</span><span class=cF0> PCNetMACGet()
|
|
<a name="l208"></a>{</span><span class=cF2>/* AMD PCNet datasheet p. 1-887, 1-931, 1-937</span><span class=cF0>
|
|
<a name="l209"></a> </span><span class=cF2>MAC address stored at first 6 bytes of PCNet EEPROM.</span><span class=cF0>
|
|
<a name="l210"></a> </span><span class=cF2>EEPROM addresses shadow-copied to APROM at hardware init.</span><span class=cF0>
|
|
<a name="l211"></a> </span><span class=cF2>APROM accessible at first 16 bytes of PCI IO space. */</span><span class=cF0>
|
|
<a name="l212"></a>
|
|
<a name="l213"></a> </span><span class=cF9>I64</span><span class=cF0> i;
|
|
<a name="l214"></a> NetLog(</span><span class=cF6>"PCNET GET MAC: Getting VM MAC."</span><span class=cF0>);
|
|
<a name="l215"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i < </span><span class=cFE>6</span><span class=cF0>; i++)
|
|
<a name="l216"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l217"></a> pcnet.mac_address[i] = </span><span class=cF5>InU8</span><span class=cF0>(PCNetIOBaseGet + i);
|
|
<a name="l218"></a> NetLog(</span><span class=cF6>" %02X"</span><span class=cF0>, pcnet.mac_address[i]);
|
|
<a name="l219"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l220"></a>}
|
|
<a name="l221"></a>
|
|
<a name="l222"></a></span><span class=cF1>U0</span><span class=cF0> PCNetDescriptorEntryInit(CPCNetDescriptorEntry *entry, </span><span class=cF9>U32</span><span class=cF0> buffer_address, </span><span class=cF9>I64</span><span class=cF0> is_rx)
|
|
<a name="l223"></a>{
|
|
<a name="l224"></a> </span><span class=cF9>U16</span><span class=cF0> buffer_byte_count;
|
|
<a name="l225"></a>
|
|
<a name="l226"></a> entry->buffer_addr = buffer_address;
|
|
<a name="l227"></a>
|
|
<a name="l228"></a> </span><span class=cF2>/*</span><span class=cF0> </span><span class=cF2>AMD PCNet datasheet p.1-991.</span><span class=cF0>
|
|
<a name="l229"></a> </span><span class=cF2>BCNT is the usable buffer length, expressed as first</span><span class=cF0>
|
|
<a name="l230"></a> </span><span class=cF2>12 bits of 2s-complement of desired length.</span><span class=cF0>
|
|
<a name="l231"></a> </span><span class=cF2>Bits 0-11 of a DE are for the buffer byte count (BCNT),</span><span class=cF0>
|
|
<a name="l232"></a> </span><span class=cF2>and bits 12-15 of a DE must be written all ones (ONES) */</span><span class=cF0>
|
|
<a name="l233"></a>
|
|
<a name="l234"></a> buffer_byte_count = -ETHERNET_FRAME_SIZE; </span><span class=cF2>// Sets up as 2s complement of the desired length.</span><span class=cF0>
|
|
<a name="l235"></a> buffer_byte_count &= </span><span class=cFE>0x0FFF</span><span class=cF0>; </span><span class=cF2>// Masks 0 over everything except bits 0-11.</span><span class=cF0>
|
|
<a name="l236"></a>
|
|
<a name="l237"></a> entry->status1 |= buffer_byte_count; </span><span class=cF2>// Sets BCNT reg (first 12 bits) in DE TMD1/RMD1.</span><span class=cF0>
|
|
<a name="l238"></a> entry->status1 |= </span><span class=cFE>0xF000</span><span class=cF0>; </span><span class=cF2>// Sets bits 12-15 (ONES) in DE TMD1/RMD1 as all ones.</span><span class=cF0>
|
|
<a name="l239"></a>
|
|
<a name="l240"></a> </span><span class=cF2>//if this is a Receive DE, give ownership to the card so the PCNet can fill them.</span><span class=cF0>
|
|
<a name="l241"></a> </span><span class=cF1>if</span><span class=cF0> (is_rx)
|
|
<a name="l242"></a> </span><span class=cF5>Bts</span><span class=cF0>(&entry->status1, PCNET_DESCRIPTORf_OWN);
|
|
<a name="l243"></a>}
|
|
<a name="l244"></a>
|
|
<a name="l245"></a></span><span class=cF1>U0</span><span class=cF0> PCNetBuffersAllocate()
|
|
<a name="l246"></a>{
|
|
<a name="l247"></a> </span><span class=cF9>I64</span><span class=cF0> de_index; </span><span class=cF2>// used in for loops for TX and RX DE access.</span><span class=cF0>
|
|
<a name="l248"></a>
|
|
<a name="l249"></a> </span><span class=cF2>/*</span><span class=cF0> </span><span class=cF2>AMD PCNet datasheet p.1-913, p.1-990</span><span class=cF0>
|
|
<a name="l250"></a> </span><span class=cF2>When SSIZE32=1, Descriptor Ring Entry Base Address</span><span class=cF0>
|
|
<a name="l251"></a> </span><span class=cF2>must be on 16-byte boundary. (TDRA[3:0]=0, RDRA[3:0]=0) */</span><span class=cF0>
|
|
<a name="l252"></a>
|
|
<a name="l253"></a> pcnet.rx_de_buffer_phys = </span><span class=cF5>CAllocAligned</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CPCNetDescriptorEntry</span><span class=cF7>)</span><span class=cF0> * PCNET_RX_BUFF_COUNT,
|
|
<a name="l254"></a> </span><span class=cFE>16</span><span class=cF0>,
|
|
<a name="l255"></a> </span><span class=cF5>Fs</span><span class=cF0>->code_heap);
|
|
<a name="l256"></a>
|
|
<a name="l257"></a> pcnet.tx_de_buffer_phys = </span><span class=cF5>CAllocAligned</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CPCNetDescriptorEntry</span><span class=cF7>)</span><span class=cF0> * PCNET_TX_BUFF_COUNT,
|
|
<a name="l258"></a> </span><span class=cFE>16</span><span class=cF0>,
|
|
<a name="l259"></a> </span><span class=cF5>Fs</span><span class=cF0>->code_heap);
|
|
<a name="l260"></a>
|
|
<a name="l261"></a> </span><span class=cF2>//Shrine does a check and returns -1 here, if the end of either buffer exceeds 0x100000000</span><span class=cF0>
|
|
<a name="l262"></a>
|
|
<a name="l263"></a> pcnet.rx_de_buffer = </span><span class=cFB>dev</span><span class=cF0>.uncached_alias + pcnet.rx_de_buffer_phys; </span><span class=cF2>// we want uncached</span><span class=cF0>
|
|
<a name="l264"></a> pcnet.tx_de_buffer = </span><span class=cFB>dev</span><span class=cF0>.uncached_alias + pcnet.tx_de_buffer_phys; </span><span class=cF2>// access to these.</span><span class=cF0>
|
|
<a name="l265"></a>
|
|
<a name="l266"></a> pcnet.rx_buffer_addr_phys = </span><span class=cF5>CAlloc</span><span class=cF0>(ETHERNET_FRAME_SIZE * PCNET_RX_BUFF_COUNT, </span><span class=cF5>Fs</span><span class=cF0>->code_heap);
|
|
<a name="l267"></a>
|
|
<a name="l268"></a> pcnet.tx_buffer_addr_phys = </span><span class=cF5>CAlloc</span><span class=cF0>(ETHERNET_FRAME_SIZE * PCNET_TX_BUFF_COUNT, </span><span class=cF5>Fs</span><span class=cF0>->code_heap);
|
|
<a name="l269"></a>
|
|
<a name="l270"></a> </span><span class=cF2>//Shrine does a check and returns -1 here, if the end of either buffer exceeds 0x100000000</span><span class=cF0>
|
|
<a name="l271"></a>
|
|
<a name="l272"></a> pcnet.rx_buffer_addr = </span><span class=cFB>dev</span><span class=cF0>.uncached_alias + pcnet.rx_buffer_addr_phys;
|
|
<a name="l273"></a> pcnet.tx_buffer_addr = </span><span class=cFB>dev</span><span class=cF0>.uncached_alias + pcnet.tx_buffer_addr_phys;
|
|
<a name="l274"></a>
|
|
<a name="l275"></a> CPCNetDescriptorEntry *entry = pcnet.rx_de_buffer;
|
|
<a name="l276"></a> </span><span class=cF1>for</span><span class=cF0> (de_index = </span><span class=cFE>0</span><span class=cF0>; de_index < PCNET_RX_BUFF_COUNT; de_index++)
|
|
<a name="l277"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l278"></a> PCNetDescriptorEntryInit(&entry[de_index],
|
|
<a name="l279"></a> pcnet.rx_buffer_addr + de_index * ETHERNET_FRAME_SIZE,
|
|
<a name="l280"></a> </span><span class=cF3>TRUE</span><span class=cF0>); </span><span class=cF2>// TRUE for is_rx.</span><span class=cF0>
|
|
<a name="l281"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l282"></a>
|
|
<a name="l283"></a> entry = pcnet.tx_de_buffer;
|
|
<a name="l284"></a> </span><span class=cF1>for</span><span class=cF0> (de_index = </span><span class=cFE>0</span><span class=cF0>; de_index < PCNET_TX_BUFF_COUNT; de_index++)
|
|
<a name="l285"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l286"></a> PCNetDescriptorEntryInit(&entry[de_index],
|
|
<a name="l287"></a> pcnet.tx_buffer_addr + de_index * ETHERNET_FRAME_SIZE,
|
|
<a name="l288"></a> </span><span class=cF3>FALSE</span><span class=cF0>); </span><span class=cF2>// FALSE for is_rx.</span><span class=cF0>
|
|
<a name="l289"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l290"></a>}
|
|
<a name="l291"></a>
|
|
<a name="l292"></a></span><span class=cF2>/*</span><span class=cF0>
|
|
<a name="l293"></a></span><span class=cF2>U0 PCNetDirectInit()</span><span class=cF0>
|
|
<a name="l294"></a></span><span class=cF2>{/* AMD PCNet datasheet p. 1-1021</span><span class=cF0>
|
|
<a name="l295"></a> </span><span class=cF2>Instead of setting up initialization block,</span><span class=cF0>
|
|
<a name="l296"></a> </span><span class=cF2>direct writes to the necessary CSRs can be</span><span class=cF0>
|
|
<a name="l297"></a> </span><span class=cF2>used to manually initialize the PCNet card. */</span><span class=cF0>
|
|
<a name="l298"></a>
|
|
<a name="l299"></a> </span><span class=cF2>/*</span><span class=cF0> </span><span class=cF2>AMD PCNet datasheet p.1-991</span><span class=cF0>
|
|
<a name="l300"></a> </span><span class=cF2>If Logical Address Filter is set as</span><span class=cF0>
|
|
<a name="l301"></a> </span><span class=cF2>all 0, all incoming logical addresses</span><span class=cF0>
|
|
<a name="l302"></a> </span><span class=cF2>are rejected. Disables multicast. */</span><span class=cF0>
|
|
<a name="l303"></a> </span><span class=cF2>PCNetCSRWrite(PCNET_CSR_LADRF0, 0);</span><span class=cF0>
|
|
<a name="l304"></a> </span><span class=cF2>PCNetCSRWrite(PCNET_CSR_LADRF1, 0);</span><span class=cF0>
|
|
<a name="l305"></a> </span><span class=cF2>PCNetCSRWrite(PCNET_CSR_LADRF2, 0);</span><span class=cF0>
|
|
<a name="l306"></a> </span><span class=cF2>PCNetCSRWrite(PCNET_CSR_LADRF3, 0);</span><span class=cF0>
|
|
<a name="l307"></a>
|
|
<a name="l308"></a> </span><span class=cF2>/*</span><span class=cF0> </span><span class=cF2>The Physical Address is the MAC.</span><span class=cF0>
|
|
<a name="l309"></a> </span><span class=cF2>AMD PCNet datasheet p.1-960, 1-961</span><span class=cF0>
|
|
<a name="l310"></a> </span><span class=cF2>The first 16 bits of CSRs 12-14 are</span><span class=cF0>
|
|
<a name="l311"></a> </span><span class=cF2>for the Physical Address, the upper bits</span><span class=cF0>
|
|
<a name="l312"></a> </span><span class=cF2>are reserved, written 0 read undefined. </span><span class=cF0>
|
|
<a name="l313"></a>
|
|
<a name="l314"></a> </span><span class=cF2>The OR and bit-shift of 8 allows writing</span><span class=cF0>
|
|
<a name="l315"></a> </span><span class=cF2>separate U8 values in the correct locations</span><span class=cF0>
|
|
<a name="l316"></a> </span><span class=cF2>of the CSR. */</span><span class=cF0>
|
|
<a name="l317"></a> </span><span class=cF2>NetLog("PCNetDirectInit: Write MAC to CSR: 0x%X ", pcnet.mac_address[0] | (pcnet.mac_address[1] << 8));</span><span class=cF0>
|
|
<a name="l318"></a> </span><span class=cF2>PCNetCSRWrite(PCNET_CSR_PADR0, pcnet.mac_address[0] | (pcnet.mac_address[1] << 8));</span><span class=cF0>
|
|
<a name="l319"></a> </span><span class=cF2>NetLog("PCNetDirectInit: Write MAC to CSR: 0x%X ", pcnet.mac_address[2] | (pcnet.mac_address[3] << 8));</span><span class=cF0>
|
|
<a name="l320"></a> </span><span class=cF2>PCNetCSRWrite(PCNET_CSR_PADR1, pcnet.mac_address[2] | (pcnet.mac_address[3] << 8));</span><span class=cF0>
|
|
<a name="l321"></a> </span><span class=cF2>NetLog("PCNetDirectInit: Write MAC to CSR: 0x%X ", pcnet.mac_address[4] | (pcnet.mac_address[5] << 8));</span><span class=cF0>
|
|
<a name="l322"></a> </span><span class=cF2>PCNetCSRWrite(PCNET_CSR_PADR2, pcnet.mac_address[4] | (pcnet.mac_address[5] << 8));</span><span class=cF0>
|
|
<a name="l323"></a>
|
|
<a name="l324"></a> </span><span class=cF2>/*</span><span class=cF0> </span><span class=cF2>AMD PCNet datasheet p.1-961, 1-962, 1-963</span><span class=cF0>
|
|
<a name="l325"></a> </span><span class=cF2>Refer to datasheet for specifics.</span><span class=cF0>
|
|
<a name="l326"></a> </span><span class=cF2>Most relevant, when setting Mode to 0,</span><span class=cF0>
|
|
<a name="l327"></a> </span><span class=cF2>promiscuous mode is is disabled, TX and</span><span class=cF0>
|
|
<a name="l328"></a> </span><span class=cF2>RX enabled, enable RX broadcast and unicast. */</span><span class=cF0>
|
|
<a name="l329"></a> </span><span class=cF2>PCNetCSRWrite(PCNET_CSR_MODE, 0);</span><span class=cF0>
|
|
<a name="l330"></a>
|
|
<a name="l331"></a> </span><span class=cF2>/* </span><span class=cF0> </span><span class=cF2>AMD PCNet datasheet p.1-964</span><span class=cF0>
|
|
<a name="l332"></a> </span><span class=cF2>CSR 24 and 25 need to be filled</span><span class=cF0>
|
|
<a name="l333"></a> </span><span class=cF2>with the lower and upper 16 bits,</span><span class=cF0>
|
|
<a name="l334"></a> </span><span class=cF2>respectively, of the address of </span><span class=cF0>
|
|
<a name="l335"></a> </span><span class=cF2>the RX packet ring. Likewise for</span><span class=cF0>
|
|
<a name="l336"></a> </span><span class=cF2>CSR 30 and 31 for the TX packet ring.</span><span class=cF0>
|
|
<a name="l337"></a>
|
|
<a name="l338"></a> </span><span class=cF2>0xFFFF AND on address will leave</span><span class=cF0>
|
|
<a name="l339"></a> </span><span class=cF2>only lower 16 bits remaining.</span><span class=cF0>
|
|
<a name="l340"></a>
|
|
<a name="l341"></a> </span><span class=cF2>Bitshift right of 16 will replace</span><span class=cF0>
|
|
<a name="l342"></a> </span><span class=cF2>first 16 bits with upper 16 bits,</span><span class=cF0>
|
|
<a name="l343"></a> </span><span class=cF2>remaining bits cleared.*/</span><span class=cF0>
|
|
<a name="l344"></a> </span><span class=cF2>PCNetCSRWrite(PCNET_CSR_BADRL, pcnet.rx_buffer_addr & 0xFFFF);</span><span class=cF0>
|
|
<a name="l345"></a> </span><span class=cF2>PCNetCSRWrite(PCNET_CSR_BADRU, pcnet.rx_buffer_addr >> 16);</span><span class=cF0>
|
|
<a name="l346"></a>
|
|
<a name="l347"></a> </span><span class=cF2>PCNetCSRWrite(PCNET_CSR_BADTL, pcnet.tx_buffer_addr & 0xFFFF);</span><span class=cF0>
|
|
<a name="l348"></a> </span><span class=cF2>PCNetCSRWrite(PCNET_CSR_BADTU, pcnet.tx_buffer_addr >> 16);</span><span class=cF0>
|
|
<a name="l349"></a>
|
|
<a name="l350"></a> </span><span class=cF2>/*</span><span class=cF0> </span><span class=cF2>AMD PCNet datasheet p. 1-967</span><span class=cF0>
|
|
<a name="l351"></a> </span><span class=cF2>Default value at hardware init is</span><span class=cF0>
|
|
<a name="l352"></a> </span><span class=cF2>all 0. Standard init block process</span><span class=cF0>
|
|
<a name="l353"></a> </span><span class=cF2>sets this, but if doing directly</span><span class=cF0>
|
|
<a name="l354"></a> </span><span class=cF2>it is imperative to manually set it 0. */</span><span class=cF0>
|
|
<a name="l355"></a> </span><span class=cF2>PCNetCSRWrite(PCNET_CSR_POLLINT, 0);</span><span class=cF0>
|
|
<a name="l356"></a>
|
|
<a name="l357"></a> </span><span class=cF2>/*</span><span class=cF0> </span><span class=cF2>AMD PCNet datasheet p. 1-970</span><span class=cF0>
|
|
<a name="l358"></a> </span><span class=cF2>Receive and Transmit Ring Length CSRs</span><span class=cF0>
|
|
<a name="l359"></a> </span><span class=cF2>bits 0-15 need to be set as the 2s complement</span><span class=cF0>
|
|
<a name="l360"></a> </span><span class=cF2>of the ring length. The AND with 0xFFFF clears</span><span class=cF0>
|
|
<a name="l361"></a> </span><span class=cF2>the upper Reserved bits, which are to be written</span><span class=cF0>
|
|
<a name="l362"></a> </span><span class=cF2>as zeroes read undefined. */</span><span class=cF0>
|
|
<a name="l363"></a> </span><span class=cF2>PCNetCSRWrite(PCNET_CSR_RXRINGLEN, -PCNET_RX_BUFF_COUNT & 0xFFFF);</span><span class=cF0>
|
|
<a name="l364"></a> </span><span class=cF2>PCNetCSRWrite(PCNET_CSR_TXRINGLEN, -PCNET_TX_BUFF_COUNT & 0xFFFF);</span><span class=cF0>
|
|
<a name="l365"></a></span><span class=cF2>}</span><span class=cF0>
|
|
<a name="l366"></a></span><span class=cF2>*/</span><span class=cF0>
|
|
<a name="l367"></a>
|
|
<a name="l368"></a></span><span class=cF1>U8</span><span class=cF0> *PCNetInitBlockSetup()
|
|
<a name="l369"></a>{
|
|
<a name="l370"></a> </span><span class=cF1>U8</span><span class=cF0> *setup = </span><span class=cF5>CAlloc</span><span class=cF0>(</span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CPCNetBufferSetup</span><span class=cF7>)</span><span class=cF0>, </span><span class=cF5>Fs</span><span class=cF0>->code_heap);
|
|
<a name="l371"></a> CPCNetBufferSetup *u_setup = setup + </span><span class=cFB>dev</span><span class=cF0>.uncached_alias;
|
|
<a name="l372"></a> </span><span class=cF9>U32</span><span class=cF0> p_setup;
|
|
<a name="l373"></a>
|
|
<a name="l374"></a> u_setup->mode = </span><span class=cFE>0</span><span class=cF0>;
|
|
<a name="l375"></a> u_setup->rlen = </span><span class=cFE>5</span><span class=cF0> << </span><span class=cFE>4</span><span class=cF0>;
|
|
<a name="l376"></a> u_setup->tlen = </span><span class=cFE>3</span><span class=cF0> << </span><span class=cFE>4</span><span class=cF0>;
|
|
<a name="l377"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(u_setup->mac, pcnet.mac_address, </span><span class=cFE>6</span><span class=cF0>);
|
|
<a name="l378"></a> u_setup->reserved = </span><span class=cFE>0</span><span class=cF0>;
|
|
<a name="l379"></a> </span><span class=cF5>MemSet</span><span class=cF0>(u_setup->ladr, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cFE>8</span><span class=cF0>);
|
|
<a name="l380"></a> u_setup->rxbuf = pcnet.rx_de_buffer_phys;
|
|
<a name="l381"></a> u_setup->txbuf = pcnet.tx_de_buffer_phys;
|
|
<a name="l382"></a>
|
|
<a name="l383"></a> p_setup = setup;
|
|
<a name="l384"></a> PCNetCSRWrite(</span><span class=cFE>1</span><span class=cF0>, p_setup & </span><span class=cFE>0xFFFF</span><span class=cF0>);
|
|
<a name="l385"></a> PCNetCSRWrite(</span><span class=cFE>2</span><span class=cF0>, p_setup >> </span><span class=cFE>16</span><span class=cF0>);
|
|
<a name="l386"></a>
|
|
<a name="l387"></a> </span><span class=cF1>return</span><span class=cF0> setup;
|
|
<a name="l388"></a>}
|
|
<a name="l389"></a>
|
|
<a name="l390"></a></span><span class=cF1>U0</span><span class=cF0> PCNetInterruptCSRSet()
|
|
<a name="l391"></a>{</span><span class=cF2>/* AMD PCNet datasheet p.1-952, 1-953, 1-954, 1-955, 1-956, 1-957</span><span class=cF0>
|
|
<a name="l392"></a> </span><span class=cF2>Refer to datasheet for specifics on the Interrupt Masks.</span><span class=cF0>
|
|
<a name="l393"></a> </span><span class=cF2>Most of these, when set 0, allow interrupts to be set in CSR0.</span><span class=cF0>
|
|
<a name="l394"></a> </span><span class=cF2>We set Big-Endian disabled, RX interrupts</span><span class=cF0>
|
|
<a name="l395"></a> </span><span class=cF2>enabled, Init Done interrupt disabled, and TX interrupt</span><span class=cF0>
|
|
<a name="l396"></a> </span><span class=cF2>disabled. */</span><span class=cF0>
|
|
<a name="l397"></a>
|
|
<a name="l398"></a> </span><span class=cF9>U32</span><span class=cF0> csr = PCNetCSRRead(PCNET_CSR_INTERRUPTS);
|
|
<a name="l399"></a>
|
|
<a name="l400"></a> </span><span class=cF5>Btr</span><span class=cF0>(&csr, PCNET_INT_BSWP);
|
|
<a name="l401"></a> </span><span class=cF5>Btr</span><span class=cF0>(&csr, PCNET_INT_RINTM);
|
|
<a name="l402"></a>
|
|
<a name="l403"></a> </span><span class=cF5>Bts</span><span class=cF0>(&csr, PCNET_INT_IDONM);
|
|
<a name="l404"></a> </span><span class=cF5>Bts</span><span class=cF0>(&csr, PCNET_INT_TINTM);
|
|
<a name="l405"></a>
|
|
<a name="l406"></a> PCNetCSRWrite(PCNET_CSR_INTERRUPTS, csr);
|
|
<a name="l407"></a>}
|
|
<a name="l408"></a>
|
|
<a name="l409"></a></span><span class=cF1>U0</span><span class=cF0> PCNetTXAutoPadEnable()
|
|
<a name="l410"></a>{</span><span class=cF2>/* AMD PCNet datasheet p.1-958</span><span class=cF0>
|
|
<a name="l411"></a> </span><span class=cF2>Setting bit 11 (Auto Pad Transmit) allows</span><span class=cF0>
|
|
<a name="l412"></a> </span><span class=cF2>shoft transmit frames to be automatically</span><span class=cF0>
|
|
<a name="l413"></a> </span><span class=cF2>extended to 64 bytes. */</span><span class=cF0>
|
|
<a name="l414"></a>
|
|
<a name="l415"></a> </span><span class=cF9>U32</span><span class=cF0> csr = PCNetCSRRead(PCNET_CSR_FEATURECTRL);
|
|
<a name="l416"></a>
|
|
<a name="l417"></a> </span><span class=cF5>Bts</span><span class=cF0>(&csr, PCNET_FEATURE_APADXMT);
|
|
<a name="l418"></a>
|
|
<a name="l419"></a> PCNetCSRWrite(PCNET_CSR_FEATURECTRL, csr);
|
|
<a name="l420"></a>}
|
|
<a name="l421"></a>
|
|
<a name="l422"></a></span><span class=cF1>U0</span><span class=cF0> PCNetConfigModeExit()
|
|
<a name="l423"></a>{</span><span class=cF2>/* AMD PCNet datasheet p.1-954</span><span class=cF0>
|
|
<a name="l424"></a> </span><span class=cF2>PCNet controller can be started</span><span class=cF0>
|
|
<a name="l425"></a> </span><span class=cF2>after configuring by ensuring INIT</span><span class=cF0>
|
|
<a name="l426"></a> </span><span class=cF2>and STOP are cleared and START bit</span><span class=cF0>
|
|
<a name="l427"></a> </span><span class=cF2>is set, in Status and Control Register</span><span class=cF0>
|
|
<a name="l428"></a> </span><span class=cF2>(CSR0). */</span><span class=cF0>
|
|
<a name="l429"></a>
|
|
<a name="l430"></a> </span><span class=cF9>U32</span><span class=cF0> csr = PCNetCSRRead(PCNET_CSR_CTRLSTATUS);
|
|
<a name="l431"></a>
|
|
<a name="l432"></a> </span><span class=cF5>Btr</span><span class=cF0>(&csr, PCNET_CTRL_INIT);
|
|
<a name="l433"></a> </span><span class=cF5>Btr</span><span class=cF0>(&csr, PCNET_CTRL_STOP);
|
|
<a name="l434"></a>
|
|
<a name="l435"></a> </span><span class=cF5>Bts</span><span class=cF0>(&csr, PCNET_CTRL_STRT);
|
|
<a name="l436"></a>
|
|
<a name="l437"></a> PCNetCSRWrite(PCNET_CSR_CTRLSTATUS, csr);
|
|
<a name="l438"></a>}
|
|
<a name="l439"></a>
|
|
<a name="l440"></a></span><span class=cF9>I64</span><span class=cF0> PCNetDriverOwns(CPCNetDescriptorEntry* entry)
|
|
<a name="l441"></a>{</span><span class=cF2>/* Returns whether the value of the OWN bit of the</span><span class=cF0>
|
|
<a name="l442"></a> </span><span class=cF2>Descriptor Entry is zero. If 0, driver owns,</span><span class=cF0>
|
|
<a name="l443"></a> </span><span class=cF2>if 1, PCNet card owns it. */</span><span class=cF0>
|
|
<a name="l444"></a>
|
|
<a name="l445"></a> </span><span class=cF1>return</span><span class=cF0> !</span><span class=cF5>Bt</span><span class=cF0>(&entry->status1, PCNET_DESCRIPTORf_OWN);
|
|
<a name="l446"></a>}
|
|
<a name="l447"></a>
|
|
<a name="l448"></a></span><span class=cF9>I64</span><span class=cF0> PCNetTransmitPacketAllocate(</span><span class=cF1>U8</span><span class=cF0> **packet_buffer_out, </span><span class=cF9>I64</span><span class=cF0> length)
|
|
<a name="l449"></a>{</span><span class=cF2>/* Transmits the packet at the current TX DE index. The packet_buffer_out</span><span class=cF0>
|
|
<a name="l450"></a> </span><span class=cF2>is a pointer, since we modify its value, ending with returning the</span><span class=cF0>
|
|
<a name="l451"></a> </span><span class=cF2>index of the DE we just processed. Length is validated to fit in BCNT.</span><span class=cF0>
|
|
<a name="l452"></a> </span><span class=cF2>The increment of the current TX DE index is done by assigning it the</span><span class=cF0>
|
|
<a name="l453"></a> </span><span class=cF2>value of incrementing it AND the max DE index-1. This will increment it</span><span class=cF0>
|
|
<a name="l454"></a> </span><span class=cF2>as well as wrap back to 0 if we hit the max DE index. */</span><span class=cF0>
|
|
<a name="l455"></a>
|
|
<a name="l456"></a> </span><span class=cF9>U16</span><span class=cF0> buffer_byte_count;
|
|
<a name="l457"></a> </span><span class=cF9>I64</span><span class=cF0> de_index = pcnet.current_tx_de_index;
|
|
<a name="l458"></a>
|
|
<a name="l459"></a> </span><span class=cF1>if</span><span class=cF0> (length > </span><span class=cFE>0xFFF</span><span class=cF0>)
|
|
<a name="l460"></a> </span><span class=cF7>{</span><span class=cF0> </span><span class=cF2>// Max packet length must fit into BCNT 12-bit register.</span><span class=cF0>
|
|
<a name="l461"></a> NetErr(</span><span class=cF6>"PCNET ALLOCATE TX PACKET: Invalid TX Packet Length"</span><span class=cF0>);
|
|
<a name="l462"></a> </span><span class=cF5>throw</span><span class=cF0>(</span><span class=cF6>'PCNet'</span><span class=cF0>);
|
|
<a name="l463"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l464"></a>
|
|
<a name="l465"></a> CPCNetDescriptorEntry *entry = &pcnet.tx_de_buffer[de_index * </span><span class=cF1>sizeof</span><span class=cF0>(CPCNetDescriptorEntry)];
|
|
<a name="l466"></a>
|
|
<a name="l467"></a> </span><span class=cF1>if</span><span class=cF0> (!PCNetDriverOwns</span><span class=cF7>(</span><span class=cF0>entry</span><span class=cF7>)</span><span class=cF0>)
|
|
<a name="l468"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l469"></a> NetErr(</span><span class=cF6>"PCNET ALLOCATE TX PACKET: TX FIFO Full"</span><span class=cF0>);
|
|
<a name="l470"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>; </span><span class=cF2>// Positive value expected. Functions calling this must factor this in.</span><span class=cF0>
|
|
<a name="l471"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l472"></a> </span><span class=cF1>else</span><span class=cF0>
|
|
<a name="l473"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l474"></a> NetLog(</span><span class=cF6>"PCNET ALLOCATE TX PACKET: Driver owns TX DE at index %d."</span><span class=cF0>, de_index);
|
|
<a name="l475"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l476"></a>
|
|
<a name="l477"></a> </span><span class=cF5>Bts</span><span class=cF0>(&entry->status1, PCNET_DESCRIPTORf_STP);
|
|
<a name="l478"></a>
|
|
<a name="l479"></a> </span><span class=cF5>Bts</span><span class=cF0>(&entry->status1, PCNET_DESCRIPTORf_ENP);
|
|
<a name="l480"></a>
|
|
<a name="l481"></a> </span><span class=cF2>/*</span><span class=cF0> </span><span class=cF2>AMD PCNet datasheet p.1-991.</span><span class=cF0>
|
|
<a name="l482"></a> </span><span class=cF2>BCNT is the usable buffer length, expressed as first</span><span class=cF0>
|
|
<a name="l483"></a> </span><span class=cF2>12 bits of 2s-complement of desired length.</span><span class=cF0>
|
|
<a name="l484"></a> </span><span class=cF2>Bits 0-11 of a DE are for the buffer byte count (BCNT),</span><span class=cF0>
|
|
<a name="l485"></a> </span><span class=cF2>and bits 12-15 of a DE must be written all ones (ONES) */</span><span class=cF0>
|
|
<a name="l486"></a> buffer_byte_count = -length; </span><span class=cF2>// Sets up as 2s complement of the desired length.</span><span class=cF0>
|
|
<a name="l487"></a> buffer_byte_count &= </span><span class=cFE>0x0FFF</span><span class=cF0>; </span><span class=cF2>// Masks 0 over everything except bits 0-11.</span><span class=cF0>
|
|
<a name="l488"></a>
|
|
<a name="l489"></a> entry->status1 &= </span><span class=cFE>0xFFFFF000</span><span class=cF0>; </span><span class=cF2>// Clear first 12 bits and retain other bits in DE TMD1.</span><span class=cF0>
|
|
<a name="l490"></a>
|
|
<a name="l491"></a> entry->status1 |= buffer_byte_count; </span><span class=cF2>// Sets BCNT reg (first 12 bits) in DE TMD1.</span><span class=cF0>
|
|
<a name="l492"></a> entry->status1 |= </span><span class=cFE>0xF000</span><span class=cF0>; </span><span class=cF2>// Sets bits 12-15 (ONES) in DE TMD1 as all ones.</span><span class=cF0>
|
|
<a name="l493"></a>
|
|
<a name="l494"></a> pcnet.current_tx_de_index = (pcnet.current_tx_de_index + </span><span class=cFE>1</span><span class=cF0>) & (PCNET_TX_BUFF_COUNT - </span><span class=cFE>1</span><span class=cF0>);
|
|
<a name="l495"></a>
|
|
<a name="l496"></a> *packet_buffer_out = pcnet.tx_buffer_addr + de_index * ETHERNET_FRAME_SIZE;
|
|
<a name="l497"></a>
|
|
<a name="l498"></a> </span><span class=cF5>MemSet</span><span class=cF0>(*packet_buffer_out, </span><span class=cFE>0</span><span class=cF0>, ETHERNET_FRAME_SIZE); </span><span class=cF2>// Clear buffer contents in advance.</span><span class=cF0>
|
|
<a name="l499"></a>
|
|
<a name="l500"></a> NetLog(</span><span class=cF6>"PCNET ALLOCATE TX PACKET: de_index: %X."</span><span class=cF0>, de_index);
|
|
<a name="l501"></a> </span><span class=cF1>return</span><span class=cF0> de_index;
|
|
<a name="l502"></a>}
|
|
<a name="l503"></a>
|
|
<a name="l504"></a></span><span class=cF1>U0</span><span class=cF0> PCNetTransmitPacketFinish(</span><span class=cF9>I64</span><span class=cF0> de_index)
|
|
<a name="l505"></a>{</span><span class=cF2>/* Release ownership of the packet to the PCNet card</span><span class=cF0>
|
|
<a name="l506"></a> </span><span class=cF2>by setting the OWN bit to 1. */</span><span class=cF0>
|
|
<a name="l507"></a>
|
|
<a name="l508"></a> CPCNetDescriptorEntry *entry = &pcnet.tx_de_buffer[de_index * </span><span class=cF1>sizeof</span><span class=cF0>(CPCNetDescriptorEntry)];
|
|
<a name="l509"></a>
|
|
<a name="l510"></a> </span><span class=cF5>Bts</span><span class=cF0>(&entry->status1, PCNET_DESCRIPTORf_OWN);
|
|
<a name="l511"></a> NetLog(</span><span class=cF6>"PCNET FINISH TX PACKET: TX DE index: %X, OWN bit of entry at entry: %b."</span><span class=cF0>,
|
|
<a name="l512"></a> de_index, </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&entry->status1, PCNET_DESCRIPTORf_OWN</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l513"></a>}
|
|
<a name="l514"></a>
|
|
<a name="l515"></a></span><span class=cF1>U0</span><span class=cF0> EthernetFrameFinish(</span><span class=cF9>I64</span><span class=cF0> de_index)
|
|
<a name="l516"></a>{</span><span class=cF2>//Alias for driver Finish TX function.</span><span class=cF0>
|
|
<a name="l517"></a> PCNetTransmitPacketFinish(de_index);
|
|
<a name="l518"></a>}
|
|
<a name="l519"></a>
|
|
<a name="l520"></a></span><span class=cF9>I64</span><span class=cF0> PCNetPacketReceive(</span><span class=cF1>U8</span><span class=cF0> **packet_buffer_out, </span><span class=cF9>U16</span><span class=cF0> *packet_length_out)
|
|
<a name="l521"></a>{</span><span class=cF2>/* Receives the packet at the current RX DE index. Parameters</span><span class=cF0>
|
|
<a name="l522"></a> </span><span class=cF2>are both pointers, since we modify the value at the packet_buffer_out,</span><span class=cF0>
|
|
<a name="l523"></a> </span><span class=cF2>and at the packet_length, ending with returning the index of the DE</span><span class=cF0>
|
|
<a name="l524"></a> </span><span class=cF2>we just processed.</span><span class=cF0>
|
|
<a name="l525"></a> </span><span class=cF2>The MCNT is stored at the first two bytes of the RMD2. We AND with</span><span class=cF0>
|
|
<a name="l526"></a> </span><span class=cF2>0xFFFF to only take in those first two bytes: that is the packet_length.</span><span class=cF0>
|
|
<a name="l527"></a> </span><span class=cF2>The increment of the current RX DE index is done by assigning it the</span><span class=cF0>
|
|
<a name="l528"></a> </span><span class=cF2>value of incrementing it AND the max DE index-1. This will increment it</span><span class=cF0>
|
|
<a name="l529"></a> </span><span class=cF2>as well as wrap back to 0 if we hit the max DE index. */</span><span class=cF0>
|
|
<a name="l530"></a>
|
|
<a name="l531"></a> </span><span class=cF9>I64</span><span class=cF0> de_index = pcnet.current_rx_de_index;
|
|
<a name="l532"></a> </span><span class=cF9>U16</span><span class=cF0> packet_length;
|
|
<a name="l533"></a>
|
|
<a name="l534"></a> NetLog(</span><span class=cF6>"PCNET RECEIVE PACKET: Output buffer ptr, output length ptr: %X, %X "</span><span class=cF0>, packet_buffer_out, packet_length_out);
|
|
<a name="l535"></a>
|
|
<a name="l536"></a> CPCNetDescriptorEntry *entry = &pcnet.rx_de_buffer[de_index * </span><span class=cF1>sizeof</span><span class=cF0>(CPCNetDescriptorEntry)];
|
|
<a name="l537"></a>
|
|
<a name="l538"></a> packet_length = entry->status2 & </span><span class=cFE>0xFFFF</span><span class=cF0>;
|
|
<a name="l539"></a>
|
|
<a name="l540"></a> NetDebug(</span><span class=cF6>"PCNET RECEIVE PACKET: de_index = 0x%0X"</span><span class=cF0>, de_index);
|
|
<a name="l541"></a> pcnet.current_rx_de_index = (pcnet.current_rx_de_index + </span><span class=cFE>1</span><span class=cF0>) & (PCNET_RX_BUFF_COUNT - </span><span class=cFE>1</span><span class=cF0>);
|
|
<a name="l542"></a> NetDebug(</span><span class=cF6>"PCNET RECEIVE PACKET: de_index incremented = 0x%0X"</span><span class=cF0>, pcnet.current_rx_de_index);
|
|
<a name="l543"></a>
|
|
<a name="l544"></a> *packet_buffer_out = pcnet.rx_buffer_addr + de_index * ETHERNET_FRAME_SIZE;
|
|
<a name="l545"></a> *packet_length_out = packet_length;
|
|
<a name="l546"></a>
|
|
<a name="l547"></a> </span><span class=cF1>return</span><span class=cF0> de_index;
|
|
<a name="l548"></a>}
|
|
<a name="l549"></a>
|
|
<a name="l550"></a></span><span class=cF1>U0</span><span class=cF0> PCNetReceivePacketRelease(</span><span class=cF9>I64</span><span class=cF0> de_index)
|
|
<a name="l551"></a>{</span><span class=cF2>/* Release ownership of the packet to the PCNet card</span><span class=cF0>
|
|
<a name="l552"></a> </span><span class=cF2>by setting the OWN bit to 1. */</span><span class=cF0>
|
|
<a name="l553"></a>
|
|
<a name="l554"></a> CPCNetDescriptorEntry *entry = &pcnet.rx_de_buffer[de_index * </span><span class=cF1>sizeof</span><span class=cF0>(CPCNetDescriptorEntry)];
|
|
<a name="l555"></a>
|
|
<a name="l556"></a> </span><span class=cF5>Bts</span><span class=cF0>(&entry->status1, PCNET_DESCRIPTORf_OWN);
|
|
<a name="l557"></a>}
|
|
<a name="l558"></a>
|
|
<a name="l559"></a></span><span class=cF1>interrupt</span><span class=cF0> </span><span class=cF1>U0</span><span class=cF0> PCNetIRQ()
|
|
<a name="l560"></a>{</span><span class=cF2>// todo: comments explaining process...maybe reimplement interrupt handling altogether.</span><span class=cF0>
|
|
<a name="l561"></a>
|
|
<a name="l562"></a> </span><span class=cF1>U8</span><span class=cF0> *packet_buffer;
|
|
<a name="l563"></a> </span><span class=cF9>U16</span><span class=cF0> packet_length;
|
|
<a name="l564"></a> </span><span class=cF9>I64</span><span class=cF0> de_index;
|
|
<a name="l565"></a>
|
|
<a name="l566"></a> </span><span class=cF9>U32</span><span class=cF0> csr = PCNetCSRRead(PCNET_CSR_CTRLSTATUS);
|
|
<a name="l567"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>"Interrupt Reason: %X , %b\n",csr,csr;Debug;</span><span class=cF0>
|
|
<a name="l568"></a>
|
|
<a name="l569"></a> CPCNetDescriptorEntry *entry = pcnet.rx_de_buffer;
|
|
<a name="l570"></a>
|
|
<a name="l571"></a> </span><span class=cF1>while</span><span class=cF0> (PCNetDriverOwns</span><span class=cF7>(</span><span class=cF0>&entry[pcnet.current_rx_de_index]</span><span class=cF7>)</span><span class=cF0>)
|
|
<a name="l572"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l573"></a> NetLog(</span><span class=cF6>"$BG,LTCYAN$$FG,WHITE$"</span><span class=cF0>
|
|
<a name="l574"></a> </span><span class=cF6>"==== PCNET IRQ ===="</span><span class=cF0>
|
|
<a name="l575"></a> </span><span class=cF6>"$BG$$FG$"</span><span class=cF0>);
|
|
<a name="l576"></a>
|
|
<a name="l577"></a> NetLog(</span><span class=cF6>"$BD,CYAN$$FD,WHITE$"</span><span class=cF0>
|
|
<a name="l578"></a> </span><span class=cF6>"PCNET IRQ: Saw owned RX DE index %d."</span><span class=cF0>, pcnet.current_rx_de_index);
|
|
<a name="l579"></a>
|
|
<a name="l580"></a> de_index = PCNetPacketReceive(&packet_buffer, &packet_length);
|
|
<a name="l581"></a>
|
|
<a name="l582"></a> </span><span class=cF1>if</span><span class=cF0> (de_index >= </span><span class=cFE>0</span><span class=cF0>) </span><span class=cF2>// todo: necessary? check increment logic in PCNetPacketReceive.</span><span class=cF0>
|
|
<a name="l583"></a> {
|
|
<a name="l584"></a> NetLog(</span><span class=cF6>"PCNET IRQ: Pushing copy into Net Queue, releasing receive packet."</span><span class=cF0>);
|
|
<a name="l585"></a> NetQueuePush(packet_buffer, packet_length);
|
|
<a name="l586"></a> PCNetReceivePacketRelease(de_index);
|
|
<a name="l587"></a> }
|
|
<a name="l588"></a>
|
|
<a name="l589"></a> </span><span class=cF5>Bts</span><span class=cF0>(&csr, PCNET_CTRL_RINT);
|
|
<a name="l590"></a>
|
|
<a name="l591"></a> PCNetCSRWrite(PCNET_CSR_CTRLSTATUS, csr);
|
|
<a name="l592"></a>
|
|
<a name="l593"></a> NetLog(</span><span class=cF6>"PCNET IRQ: Exiting.\n"</span><span class=cF0>
|
|
<a name="l594"></a> </span><span class=cF6>"$BD,WHITE$$FD,LTGRAY$"</span><span class=cF0>
|
|
<a name="l595"></a> </span><span class=cF6>"$BG,LTCYAN$$FG,WHITE$"</span><span class=cF0>
|
|
<a name="l596"></a> </span><span class=cF6>"==================="</span><span class=cF0>
|
|
<a name="l597"></a> </span><span class=cF6>"$BG$$FG$"</span><span class=cF0>);
|
|
<a name="l598"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l599"></a>
|
|
<a name="l600"></a> *(</span><span class=cFB>dev</span><span class=cF0>.uncached_alias + </span><span class=cF3>LAPIC_EOI</span><span class=cF0>)(</span><span class=cF9>U32</span><span class=cF0>*) = </span><span class=cFE>0</span><span class=cF0>;
|
|
<a name="l601"></a>}
|
|
<a name="l602"></a>
|
|
<a name="l603"></a></span><span class=cF1>U0</span><span class=cF0> PCIInterruptsReroute(</span><span class=cF9>I64</span><span class=cF0> base)
|
|
<a name="l604"></a>{ </span><span class=cF2>// todo: comments explaining process, maybe better var names</span><span class=cF0>
|
|
<a name="l605"></a> </span><span class=cF9>I64</span><span class=cF0> i;
|
|
<a name="l606"></a> </span><span class=cF1>U8</span><span class=cF0> *da = </span><span class=cFB>dev</span><span class=cF0>.uncached_alias + </span><span class=cF3>IOAPIC_REG</span><span class=cF0>;
|
|
<a name="l607"></a> </span><span class=cF9>U32</span><span class=cF0> *_d = </span><span class=cFB>dev</span><span class=cF0>.uncached_alias + </span><span class=cF3>IOAPIC_DATA</span><span class=cF0>;
|
|
<a name="l608"></a>
|
|
<a name="l609"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i < </span><span class=cFE>4</span><span class=cF0>; i++)
|
|
<a name="l610"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l611"></a> *da = </span><span class=cF3>IOREDTAB</span><span class=cF0> + i * </span><span class=cFE>2</span><span class=cF0> + </span><span class=cFE>1</span><span class=cF0>;
|
|
<a name="l612"></a> *_d = </span><span class=cFB>dev</span><span class=cF0>.mp_apic_ids[INT_DEST_CPU] << </span><span class=cFE>24</span><span class=cF0>;
|
|
<a name="l613"></a> *da = </span><span class=cF3>IOREDTAB</span><span class=cF0> + i * </span><span class=cFE>2</span><span class=cF0>;
|
|
<a name="l614"></a> *_d = </span><span class=cFE>0x4000</span><span class=cF0> + base + i;
|
|
<a name="l615"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l616"></a>}
|
|
<a name="l617"></a>
|
|
<a name="l618"></a></span><span class=cF1>U0</span><span class=cF0> PCNetInterruptsSetup()
|
|
<a name="l619"></a>{ </span><span class=cF2>// todo: comments explaining process</span><span class=cF0>
|
|
<a name="l620"></a></span><span class=cF2>/*</span><span class=cF0> </span><span class=cF2>IntEntrySet(I_PCNET0, &PCNetIRQ);</span><span class=cF0>
|
|
<a name="l621"></a> </span><span class=cF2>IntEntrySet(I_PCNET1, &PCNetIRQ);</span><span class=cF0>
|
|
<a name="l622"></a> </span><span class=cF2>IntEntrySet(I_PCNET2, &PCNetIRQ);</span><span class=cF0>
|
|
<a name="l623"></a> </span><span class=cF2>IntEntrySet(I_PCNET3, &PCNetIRQ);</span><span class=cF0>
|
|
<a name="l624"></a> </span><span class=cF2>PCIInterruptsReroute(I_PCNET0);*/</span><span class=cF0>
|
|
<a name="l625"></a> </span><span class=cF9>I64</span><span class=cF0> irq, i;
|
|
<a name="l626"></a>
|
|
<a name="l627"></a> </span><span class=cF1>for</span><span class=cF0> (i = </span><span class=cFE>0</span><span class=cF0>; i < </span><span class=cFE>4</span><span class=cF0>; i++)
|
|
<a name="l628"></a> </span><span class=cF5>IntEntrySet</span><span class=cF0>(</span><span class=cF7>(</span><span class=cF0>irq = </span><span class=cF5>IntEntryAlloc</span><span class=cF7>)</span><span class=cF0>, &PCNetIRQ);
|
|
<a name="l629"></a>
|
|
<a name="l630"></a> PCIInterruptsReroute(irq);
|
|
<a name="l631"></a>}
|
|
<a name="l632"></a>
|
|
<a name="l633"></a></span><span class=cF1>U0</span><span class=cF0> PCNetInit()
|
|
<a name="l634"></a>{
|
|
<a name="l635"></a> </span><span class=cF1>U8</span><span class=cF0> *setup; </span><span class=cF2>// PCNetInitBlockSetup</span><span class=cF0>
|
|
<a name="l636"></a>
|
|
<a name="l637"></a> </span><span class=cF5>MemSet</span><span class=cF0>(&pcnet, </span><span class=cFE>0</span><span class=cF0>, </span><span class=cF1>sizeof</span><span class=cF7>(</span><span class=cF0>CPCNet</span><span class=cF7>)</span><span class=cF0>); </span><span class=cF2>// pcnet global var will hold member data the driver uses often.</span><span class=cF0>
|
|
<a name="l638"></a>
|
|
<a name="l639"></a> pcnet.pci = PCNetPCIDevFind;
|
|
<a name="l640"></a> </span><span class=cF1>if</span><span class=cF0> (!pcnet.pci)
|
|
<a name="l641"></a> </span><span class=cF1>return</span><span class=cF0>; </span><span class=cF2>// if we don't find the card, quit.</span><span class=cF0>
|
|
<a name="l642"></a>
|
|
<a name="l643"></a> </span><span class=cF2>/*</span><span class=cF0> </span><span class=cF2>Clear command register of PCNet</span><span class=cF0>
|
|
<a name="l644"></a> </span><span class=cF2>PCI device, set IO Enable and Bus</span><span class=cF0>
|
|
<a name="l645"></a> </span><span class=cF2>Master Enable bits of the register. */</span><span class=cF0>
|
|
<a name="l646"></a> </span><span class=cF5>PCIWriteU16</span><span class=cF0>(pcnet.pci->bus,
|
|
<a name="l647"></a> pcnet.pci-></span><span class=cFB>dev</span><span class=cF0>,
|
|
<a name="l648"></a> pcnet.pci->fun,
|
|
<a name="l649"></a> </span><span class=cF3>PCIR_COMMAND</span><span class=cF0>,
|
|
<a name="l650"></a> PCNET_CMDF_IOEN | PCNET_CMDF_BMEN);
|
|
<a name="l651"></a>
|
|
<a name="l652"></a> PCNetReset;
|
|
<a name="l653"></a>
|
|
<a name="l654"></a> PCNet32BitModeEnable;
|
|
<a name="l655"></a>
|
|
<a name="l656"></a> </span><span class=cF9>U32</span><span class=cF0> csr = PCNetCSRRead(PCNET_CSR_CTRLSTATUS);
|
|
<a name="l657"></a> NetLog(</span><span class=cF6>"PCNET INIT START: what is INIT ?: %d"</span><span class=cF0>, </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&csr, PCNET_CTRL_INIT</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l658"></a> NetLog(</span><span class=cF6>"PCNET INIT START: what is STRT ?: %d"</span><span class=cF0>, </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&csr, PCNET_CTRL_STRT</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l659"></a> NetLog(</span><span class=cF6>"PCNET INIT START: what is STOP ?: %d"</span><span class=cF0>, </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&csr, PCNET_CTRL_STOP</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l660"></a> NetLog(</span><span class=cF6>"PCNET INIT START: what is RINT ?: %d"</span><span class=cF0>, </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&csr, PCNET_CTRL_RINT</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l661"></a>
|
|
<a name="l662"></a>
|
|
<a name="l663"></a> PCNetSWStyleSet;
|
|
<a name="l664"></a>
|
|
<a name="l665"></a> PCNetMACGet;
|
|
<a name="l666"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>OSDev has code ensuring auto selected connection...</span><span class=cF0>
|
|
<a name="l667"></a>
|
|
<a name="l668"></a> PCNetBuffersAllocate;
|
|
<a name="l669"></a>
|
|
<a name="l670"></a></span><span class=cF2>//</span><span class=cF0> </span><span class=cF2>PCNetDirectInit;</span><span class=cF0>
|
|
<a name="l671"></a> setup = PCNetInitBlockSetup();
|
|
<a name="l672"></a>
|
|
<a name="l673"></a> PCNetInterruptCSRSet;
|
|
<a name="l674"></a>
|
|
<a name="l675"></a> PCNetTXAutoPadEnable;
|
|
<a name="l676"></a>
|
|
<a name="l677"></a> PCNetCSRWrite(</span><span class=cFE>0</span><span class=cF0>, PCNetCSRRead</span><span class=cF7>(</span><span class=cFE>0</span><span class=cF7>)</span><span class=cF0> | </span><span class=cFE>1</span><span class=cF0> | </span><span class=cFE>1</span><span class=cF0> << </span><span class=cFE>6</span><span class=cF0>); </span><span class=cF2>// ?</span><span class=cF0>
|
|
<a name="l678"></a>
|
|
<a name="l679"></a> csr = PCNetCSRRead(PCNET_CSR_CTRLSTATUS);
|
|
<a name="l680"></a> NetLog(</span><span class=cF6>"PCNET INIT UPLOAD: what is INIT ?: %d"</span><span class=cF0>, </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&csr, PCNET_CTRL_INIT</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l681"></a> NetLog(</span><span class=cF6>"PCNET INIT UPLOAD: what is STRT ?: %d"</span><span class=cF0>, </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&csr, PCNET_CTRL_STRT</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l682"></a> NetLog(</span><span class=cF6>"PCNET INIT UPLOAD: what is STOP ?: %d"</span><span class=cF0>, </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&csr, PCNET_CTRL_STOP</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l683"></a> NetLog(</span><span class=cF6>"PCNET INIT UPLOAD: what is RINT ?: %d"</span><span class=cF0>, </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&csr, PCNET_CTRL_RINT</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l684"></a>
|
|
<a name="l685"></a> </span><span class=cF1>while</span><span class=cF0> (!</span><span class=cF7>(</span><span class=cF0>PCNetCSRRead(</span><span class=cFE>0</span><span class=cF0>) & </span><span class=cFE>1</span><span class=cF0> << </span><span class=cFE>8</span><span class=cF7>)</span><span class=cF0>) </span><span class=cF2>// ?</span><span class=cF0>
|
|
<a name="l686"></a> </span><span class=cF5>Yield</span><span class=cF0>;
|
|
<a name="l687"></a>
|
|
<a name="l688"></a> PCNetConfigModeExit;
|
|
<a name="l689"></a>
|
|
<a name="l690"></a> </span><span class=cF5>Sleep</span><span class=cF0>(</span><span class=cFE>100</span><span class=cF0>); </span><span class=cF2>//? necessary?</span><span class=cF0>
|
|
<a name="l691"></a>
|
|
<a name="l692"></a> csr = PCNetCSRRead(PCNET_CSR_CTRLSTATUS);
|
|
<a name="l693"></a> NetLog(</span><span class=cF6>"PCNET INIT END: what is INIT ?: %d"</span><span class=cF0>, </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&csr, PCNET_CTRL_INIT</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l694"></a> NetLog(</span><span class=cF6>"PCNET INIT END: what is STRT ?: %d"</span><span class=cF0>, </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&csr, PCNET_CTRL_STRT</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l695"></a> NetLog(</span><span class=cF6>"PCNET INIT END: what is STOP ?: %d"</span><span class=cF0>, </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&csr, PCNET_CTRL_STOP</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l696"></a> NetLog(</span><span class=cF6>"PCNET INIT END: what is RINT ?: %d"</span><span class=cF0>, </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&csr, PCNET_CTRL_RINT</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l697"></a> NetLog(</span><span class=cF6>"PCNET INIT END: what is TXON ?: %d"</span><span class=cF0>, </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&csr, </span><span class=cFE>4</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l698"></a> NetLog(</span><span class=cF6>"PCNET INIT END: what is RXON ?: %d"</span><span class=cF0>, </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&csr, </span><span class=cFE>5</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l699"></a>
|
|
<a name="l700"></a> csr = PCNetCSRRead(PCNET_CSR_POLLINT);
|
|
<a name="l701"></a> NetLog(</span><span class=cF6>"PCNET INIT END: what is POLLINT ?: %d"</span><span class=cF0>, </span><span class=cF5>Bt</span><span class=cF7>(</span><span class=cF0>&csr, PCNET_CTRL_RINT</span><span class=cF7>)</span><span class=cF0>);
|
|
<a name="l702"></a>
|
|
<a name="l703"></a> NetLog(</span><span class=cF6>"PCNET INIT END: Redirecting interrupts."</span><span class=cF0>);
|
|
<a name="l704"></a> PCNetInterruptsSetup;
|
|
<a name="l705"></a>
|
|
<a name="l706"></a>
|
|
<a name="l707"></a> </span><span class=cF5>Free</span><span class=cF0>(setup);
|
|
<a name="l708"></a>}
|
|
<a name="l709"></a>
|
|
<a name="l710"></a></span><span class=cF9>I64</span><span class=cF0> EthernetFrameAllocate(</span><span class=cF1>U8</span><span class=cF0> **packet_buffer_out,
|
|
<a name="l711"></a> </span><span class=cF1>U8</span><span class=cF0> *source_address,
|
|
<a name="l712"></a> </span><span class=cF1>U8</span><span class=cF0> *destination_address,
|
|
<a name="l713"></a> </span><span class=cF9>U16</span><span class=cF0> ethertype,
|
|
<a name="l714"></a> </span><span class=cF9>I64</span><span class=cF0> packet_length)
|
|
<a name="l715"></a>{</span><span class=cF2>/* Allocate an Ethernet Frame for transmit. The source</span><span class=cF0>
|
|
<a name="l716"></a> </span><span class=cF2>and destination addresses are copied to the Frame,</span><span class=cF0>
|
|
<a name="l717"></a> </span><span class=cF2>as well as the ethertype. The packet_buffer_out</span><span class=cF0>
|
|
<a name="l718"></a> </span><span class=cF2>parameter has the value at its pointer set to the</span><span class=cF0>
|
|
<a name="l719"></a> </span><span class=cF2>payload of the Ethernet Frame. */</span><span class=cF0>
|
|
<a name="l720"></a>
|
|
<a name="l721"></a> </span><span class=cF1>U8</span><span class=cF0> *ethernet_frame;
|
|
<a name="l722"></a> </span><span class=cF9>I64</span><span class=cF0> de_index;
|
|
<a name="l723"></a>
|
|
<a name="l724"></a> </span><span class=cF2>//need to see if 3 years later VirtualBox supports APAD_XMT!</span><span class=cF0>
|
|
<a name="l725"></a> </span><span class=cF1>if</span><span class=cF0> (packet_length < ETHERNET_MIN_FRAME_SIZE)
|
|
<a name="l726"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l727"></a> NetWarn(</span><span class=cF6>"ETHERNET FRAME ALLOCATE: PCNET APAD XMT TRUNCATE ? ..."</span><span class=cF0>);
|
|
<a name="l728"></a> packet_length = ETHERNET_MIN_FRAME_SIZE;
|
|
<a name="l729"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l730"></a>
|
|
<a name="l731"></a> de_index = PCNetTransmitPacketAllocate(&ethernet_frame, ETHERNET_MAC_HEADER_LENGTH + packet_length);
|
|
<a name="l732"></a>
|
|
<a name="l733"></a> </span><span class=cF1>if</span><span class=cF0> (de_index < </span><span class=cFE>0</span><span class=cF0>)
|
|
<a name="l734"></a> </span><span class=cF7>{</span><span class=cF0>
|
|
<a name="l735"></a> NetErr(</span><span class=cF6>"ETHERNET FRAME ALLOCATE: Failure"</span><span class=cF0>);
|
|
<a name="l736"></a> </span><span class=cF1>return</span><span class=cF0> -</span><span class=cFE>1</span><span class=cF0>; </span><span class=cF2>// Positive value expected. Functions calling this must factor this in.</span><span class=cF0>
|
|
<a name="l737"></a> </span><span class=cF7>}</span><span class=cF0>
|
|
<a name="l738"></a>
|
|
<a name="l739"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(ethernet_frame, destination_address, MAC_ADDRESS_LENGTH);
|
|
<a name="l740"></a> </span><span class=cF5>MemCopy</span><span class=cF0>(ethernet_frame + MAC_ADDRESS_LENGTH, source_address, MAC_ADDRESS_LENGTH);
|
|
<a name="l741"></a>
|
|
<a name="l742"></a> ethernet_frame[ETHERNET_ETHERTYPE_OFFSET] = ethertype >> </span><span class=cFE>8</span><span class=cF0>;
|
|
<a name="l743"></a> ethernet_frame[ETHERNET_ETHERTYPE_OFFSET + </span><span class=cFE>1</span><span class=cF0>] = ethertype & </span><span class=cFE>0xFF</span><span class=cF0>;
|
|
<a name="l744"></a>
|
|
<a name="l745"></a> *packet_buffer_out = ethernet_frame + ETHERNET_MAC_HEADER_LENGTH;
|
|
<a name="l746"></a>
|
|
<a name="l747"></a> </span><span class=cF1>return</span><span class=cF0> de_index;
|
|
<a name="l748"></a>}
|
|
<a name="l749"></a>
|
|
<a name="l750"></a></span><span class=cF1>U8</span><span class=cF0> *EthernetMACGet()
|
|
<a name="l751"></a>{
|
|
<a name="l752"></a> </span><span class=cF1>return</span><span class=cF0> pcnet.mac_address;
|
|
<a name="l753"></a>}
|
|
<a name="l754"></a>
|
|
<a name="l755"></a></span><span class=cF1>U0</span><span class=cF0> NetStop()
|
|
<a name="l756"></a>{ </span><span class=cF2>// Halt network activity by setting STOP bit on Status CSR.</span><span class=cF0>
|
|
<a name="l757"></a> </span><span class=cF9>U32</span><span class=cF0> csr = PCNetCSRRead(PCNET_CSR_CTRLSTATUS);
|
|
<a name="l758"></a>
|
|
<a name="l759"></a> </span><span class=cF5>Bts</span><span class=cF0>(&csr, PCNET_CTRL_STOP);
|
|
<a name="l760"></a>
|
|
<a name="l761"></a> PCNetCSRWrite(PCNET_CSR_CTRLSTATUS, csr);
|
|
<a name="l762"></a>
|
|
<a name="l763"></a>}
|
|
<a name="l764"></a>
|
|
<a name="l765"></a></span><span class=cF1>U0</span><span class=cF0> NetStart()
|
|
<a name="l766"></a>{ </span><span class=cF2>// Continue network activity. Setting START bit clears STOP/INIT.</span><span class=cF0>
|
|
<a name="l767"></a> </span><span class=cF9>U32</span><span class=cF0> csr = PCNetCSRRead(PCNET_CSR_CTRLSTATUS);
|
|
<a name="l768"></a>
|
|
<a name="l769"></a> </span><span class=cF5>Bts</span><span class=cF0>(&csr, PCNET_CTRL_STRT);
|
|
<a name="l770"></a>
|
|
<a name="l771"></a> PCNetCSRWrite(PCNET_CSR_CTRLSTATUS, csr);
|
|
<a name="l772"></a>}
|
|
<a name="l773"></a>
|
|
<a name="l774"></a>PCNetInit;</span></pre></body>
|
|
</html>
|