Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


27e1aadfed236aaa8506ad1c1693c1179364eb0e
[palacios.git] / palacios / src / geekos / rtl8139.c
1 #include <geekos/rtl8139.h>
2 #include <geekos/debug.h>
3 #include <geekos/io.h>
4 #include <geekos/irq.h>
5 #include <geekos/malloc.h>
6 #include <geekos/string.h>
7 #include <uip/uip.h>
8 #include <uip/uip_arp.h>
9
10
11 #define RX_BUF_LEN (32768 + 16 + 2048)
12 #define TX_BUF_SIZE 1536
13 #define TX_FIFO_THRESH 256
14 uchar_t *rx_buf;
15 uchar_t *tx_buf;
16 uint_t cur_tx;
17 uint_t cur_rx;
18 uint_t tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
19 uint_t pkt_cntr = 0;
20
21 /* The macros below were copied straight from the linux 8139too.c driver. */
22 enum ClearBitMasks {
23         MultiIntrClear = 0xF000,
24         ChipCmdClear = 0xE2,
25         Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1),
26 };
27
28 enum ChipCmdBits {
29         CmdReset = 0x10,
30         CmdRxEnb = 0x08,
31         CmdTxEnb = 0x04,
32         RxBufEmpty = 0x01,
33 };
34
35 /* Interrupt register bits */
36 enum IntrStatusBits {
37         PCIErr = 0x8000,
38         PCSTimeout = 0x4000,
39         RxFIFOOver = 0x40,
40         RxUnderrun = 0x20,
41         RxOverflow = 0x10,
42         TxErr = 0x08,
43         TxOK = 0x04,
44         RxErr = 0x02,
45         RxOK = 0x01,
46
47         RxAckBits = RxFIFOOver | RxOverflow | RxOK,
48 };
49
50 enum TxStatusBits {
51         TxHostOwns = 0x2000,
52         TxUnderrun = 0x4000,
53         TxStatOK = 0x8000,
54         TxOutOfWindow = 0x20000000,
55         TxAborted = 0x40000000,
56         TxCarrierLost = 0x80000000,
57 };
58 enum RxStatusBits {
59         RxMulticast = 0x8000,
60         RxPhysical = 0x4000,
61         RxBroadcast = 0x2000,
62         RxBadSymbol = 0x0020,
63         RxRunt = 0x0010,
64         RxTooLong = 0x0008,
65         RxCRCErr = 0x0004,
66         RxBadAlign = 0x0002,
67         RxStatusOK = 0x0001,
68 };
69
70 /* Bits in RxConfig. */
71 enum rx_mode_bits {
72         AcceptErr = 0x20,
73         AcceptRunt = 0x10,
74         AcceptBroadcast = 0x08,
75         AcceptMulticast = 0x04,
76         AcceptMyPhys = 0x02,
77         AcceptAllPhys = 0x01,
78 };
79
80 /* Bits in TxConfig. */
81 enum tx_config_bits {
82
83         /* Interframe Gap Time. Only TxIFG96 doesn't violate IEEE 802.3 */
84         TxIFGShift = 24,
85         TxIFG84 = (0 << TxIFGShift),    /* 8.4us / 840ns (10 / 100Mbps) */
86         TxIFG88 = (1 << TxIFGShift),    /* 8.8us / 880ns (10 / 100Mbps) */
87         TxIFG92 = (2 << TxIFGShift),    /* 9.2us / 920ns (10 / 100Mbps) */
88         TxIFG96 = (3 << TxIFGShift),    /* 9.6us / 960ns (10 / 100Mbps) */
89
90         TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
91         TxCRC = (1 << 16),      /* DISABLE appending CRC to end of Tx packets */
92         TxClearAbt = (1 << 0),  /* Clear abort (WO) */
93         TxDMAShift = 8,         /* DMA burst value (0-7) is shifted this many bits */
94         TxRetryShift = 4,       /* TXRR value (0-15) is shifted this many bits */
95
96         TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */
97 };
98
99 /* Bits in Config1 */
100 enum Config1Bits {
101         Cfg1_PM_Enable = 0x01,
102         Cfg1_VPD_Enable = 0x02,
103         Cfg1_PIO = 0x04,
104         Cfg1_MMIO = 0x08,
105         LWAKE = 0x10,           /* not on 8139, 8139A */
106         Cfg1_Driver_Load = 0x20,
107         Cfg1_LED0 = 0x40,
108         Cfg1_LED1 = 0x80,
109         SLEEP = (1 << 1),       /* only on 8139, 8139A */
110         PWRDN = (1 << 0),       /* only on 8139, 8139A */
111 };
112
113 /* Bits in Config3 */
114 enum Config3Bits {
115         Cfg3_FBtBEn    = (1 << 0), /* 1 = Fast Back to Back */
116         Cfg3_FuncRegEn = (1 << 1), /* 1 = enable CardBus Function registers */
117         Cfg3_CLKRUN_En = (1 << 2), /* 1 = enable CLKRUN */
118         Cfg3_CardB_En  = (1 << 3), /* 1 = enable CardBus registers */
119         Cfg3_LinkUp    = (1 << 4), /* 1 = wake up on link up */
120         Cfg3_Magic     = (1 << 5), /* 1 = wake up on Magic Packet (tm) */
121         Cfg3_PARM_En   = (1 << 6), /* 0 = software can set twister parameters */
122         Cfg3_GNTSel    = (1 << 7), /* 1 = delay 1 clock from PCI GNT signal */
123 };
124
125 /* Bits in Config4 */
126 enum Config4Bits {
127         LWPTN = (1 << 2),       /* not on 8139, 8139A */
128 };
129
130 /* Bits in Config5 */
131 enum Config5Bits {
132         Cfg5_PME_STS     = (1 << 0), /* 1 = PCI reset resets PME_Status */
133         Cfg5_LANWake     = (1 << 1), /* 1 = enable LANWake signal */
134         Cfg5_LDPS        = (1 << 2), /* 0 = save power when link is down */
135         Cfg5_FIFOAddrPtr = (1 << 3), /* Realtek internal SRAM testing */
136         Cfg5_UWF         = (1 << 4), /* 1 = accept unicast wakeup frame */
137         Cfg5_MWF         = (1 << 5), /* 1 = accept multicast wakeup frame */
138         Cfg5_BWF         = (1 << 6), /* 1 = accept broadcast wakeup frame */
139 };
140
141 enum RxConfigBits {
142         /* rx fifo threshold */
143         RxCfgFIFOShift = 13,
144         RxCfgFIFONone = (7 << RxCfgFIFOShift),
145
146         /* Max DMA burst */
147         RxCfgDMAShift = 8,
148         RxCfgDMAUnlimited = (7 << RxCfgDMAShift),
149
150         /* rx ring buffer length */
151         RxCfgRcv8K = 0,
152         RxCfgRcv16K = (1 << 11),
153         RxCfgRcv32K = (1 << 12),
154         RxCfgRcv64K = (1 << 11) | (1 << 12),
155
156         /* Disable packet wrap at end of Rx buffer. (not possible with 64k) */
157         RxNoWrap = (1 << 7),
158 };
159
160 /* Twister tuning parameters from RealTek.
161    Completely undocumented, but required to tune bad links on some boards. */
162 enum CSCRBits {
163         CSCR_LinkOKBit = 0x0400,
164         CSCR_LinkChangeBit = 0x0800,
165         CSCR_LinkStatusBits = 0x0f000,
166         CSCR_LinkDownOffCmd = 0x003c0,
167         CSCR_LinkDownCmd = 0x0f3c0,
168 };
169
170 enum Cfg9346Bits {
171         Cfg9346_Lock = 0x00,
172         Cfg9346_Unlock = 0xC0,
173 };
174
175 static const uint_t rtl8139_intr_mask =
176         PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver |
177         TxErr | TxOK | RxErr | RxOK;
178
179 //static void Init_8139(int (*rcvd_fn)(struct NE2K_Packet_Info *info, uchar_t *packet))
180
181
182 static void rtl8139_interrupt( struct Interrupt_State * state )
183 {
184         Begin_IRQ(state);
185
186         uint_t status = In_Word(RTL8139_ISR);
187
188         PrintBoth("Interrupt Received: %x\n", status);
189
190         if( status == PKT_RX )
191                 rtl8139_Receive();
192
193         rtl8139_Clear_IRQ(status);
194         End_IRQ(state);
195
196 }
197
198 void rtl8139_Clear_IRQ(uint_t interrupts)
199 {
200         Out_Word(RTL8139_ISR, interrupts);
201 }
202
203 void Init_8139()
204 {
205         cur_tx = 0;
206         cur_rx = 0;
207
208         /* Reset the chip */
209         Out_Byte(RTL8139_CR, CmdReset);
210
211         //while( In_Byte(RTL8139_CR) != 0 )
212                 /*udelay(10)*/;
213
214         /* Unlock Config[01234] and BMCR register writes */
215         Out_Byte(RTL8139_9346CR, Cfg9346_Unlock);
216
217         /* Enable Tx/Rx before setting transfer thresholds */
218         Out_Byte(RTL8139_CR, CmdRxEnb | CmdTxEnb);
219
220         /* Using 32K ring */
221         Out_DWord(RTL8139_RCR, RxCfgRcv32K | RxNoWrap | (7 << RxCfgFIFOShift) | (7 << RxCfgDMAShift)
222                                  | AcceptBroadcast | AcceptMyPhys);
223
224 //      Out_DWord(RTL8139_TCR, RxCfgRcv32K | RxNoWrap | (7 << RxCfgFIFOShift) | (7 << RxCfgDMAShift));
225
226         Out_DWord(RTL8139_TCR, TxIFG96 | (6 << TxDMAShift) | (8 << TxRetryShift));
227
228         /* Lock Config[01234] and BMCR register writes */
229         Out_Byte(RTL8139_9346CR, Cfg9346_Lock);
230
231         /* init Rx ring buffer DMA address */
232         rx_buf = Malloc(RX_BUF_LEN);
233         Out_DWord(RTL8139_RBSTART, (uint_t)rx_buf);
234
235         /* init Tx buffer DMA addresses (4 registers) */
236         tx_buf = Malloc(TX_BUF_SIZE * 4);
237         int i;
238         for(i = 0; i < 4; i++)
239                 Out_DWord(RTL8139_TSAD0 + (i * 4), ((uint_t)tx_buf) + (i * TX_BUF_SIZE));
240
241         /* missed packet counter */
242         Out_DWord(RTL8139_MPC, 0);
243
244         // rtl8139_set_rx_mode does some stuff here.
245         Out_DWord(RTL8139_RCR, In_DWord(RTL8139_RCR) | AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
246                                 AcceptAllPhys);
247
248         for(i = 0; i < 8; i++)
249                 Out_Byte(RTL8139_MAR0 + i, 0xff);
250
251         /* no early-rx interrupts */
252         Out_Word(RTL8139_MULINT, In_Word(RTL8139_MULINT) & MultiIntrClear);
253
254         /* make sure RxTx has started */
255         if(!(In_Byte(RTL8139_CR) & CmdRxEnb) || !(In_Byte(RTL8139_CR) & CmdTxEnb))
256                 Out_Byte(RTL8139_CR, CmdRxEnb | CmdTxEnb);
257
258         /* Enable all known interrupts by setting the interrupt mask. */
259         Out_Word(RTL8139_IMR, rtl8139_intr_mask);
260
261         Install_IRQ(RTL8139_IRQ, rtl8139_interrupt);
262         Enable_IRQ(RTL8139_IRQ);
263
264         PrintBoth("8139 initialized\n");
265 }
266
267 int rtl8139_Send(uchar_t *packet, uint_t size)
268 {
269         uint_t entry = cur_tx % 4;
270         memcpy(tx_buf + (entry * TX_BUF_SIZE), packet, size);
271         Out_DWord(RTL8139_TSD0 + (entry * 4), tx_flag | size);
272         cur_tx++;
273         PrintBoth("Packet transmitted.  cur_tx = %d\n", cur_tx);
274         return 0;
275 }
276
277 int rtl8139_Receive()
278 {
279         PrintBoth("Packet Received\n");
280         int i;
281
282         while( (In_Byte(RTL8139_CR) & RxBufEmpty) == 0){
283
284                 uint_t ring_offset = cur_rx % RX_BUF_LEN;
285
286                 uint_t rx_status = ((uint_t)rx_buf + ring_offset);
287
288                 PrintBoth("RX Status = %x\n", rx_status);
289
290                 uint_t rx_size = (uint_t)((*(uchar_t *)(rx_status + 3) << 8) | (*(uchar_t *)(rx_status + 2)));
291                 uint_t pkt_len = rx_size - 4;
292
293                 PrintBoth("Packet Size = %d\n", pkt_len);
294         
295                 for (i = 0; i < pkt_len; i++){
296                         PrintBoth(" %x ", *((uchar_t *)(rx_status + i)));
297                 }
298                 PrintBoth("\n");
299
300                 cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
301                 Out_Word(RTL8139_CAPR, (ushort_t)(cur_rx - 16));
302
303                 pkt_cntr++;
304
305                 PrintBoth("Packet counter at %d\n", pkt_cntr);
306         }
307
308
309
310         return 0;
311 }