1 /*
2 * Cisco router simulation platform.
3 * Copyright (C) 2007 Christophe Fillot. All rights reserved.
4 *
5 * Intel i8254x (Wiseman/Livengood) Ethernet chip emulation.
6 */
7
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <stdarg.h>
12 #include <unistd.h>
13 #include <time.h>
14 #include <errno.h>
15 #include <assert.h>
16
17 #include "utils.h"
18 #include "cpu.h"
19 #include "vm.h"
20 #include "dynamips.h"
21 #include "memory.h"
22 #include "device.h"
23 #include "net.h"
24 #include "net_io.h"
25 #include "ptask.h"
26 #include "dev_i8254x.h"
27
28 /* Debugging flags */
29 #define DEBUG_MII_REGS 0
30 #define DEBUG_ACCESS 0
31 #define DEBUG_TRANSMIT 0
32 #define DEBUG_RECEIVE 0
33 #define DEBUG_UNKNOWN 0
34
35 /* Intel i8254x PCI vendor/product codes */
36 #define I8254X_PCI_VENDOR_ID 0x8086
37 #define I8254X_PCI_PRODUCT_ID 0x1001
38
39 /* Maximum packet size */
40 #define I8254X_MAX_PKT_SIZE 16384
41
42 /* Send up to 16 packets in a TX ring scan pass */
43 #define I8254X_TXRING_PASS_COUNT 16
44
45 /* Register list */
46 #define I8254X_REG_CTRL 0x0000 /* Control Register */
47 #define I8254X_REG_STATUS 0x0008 /* Device Status Register */
48 #define I8254X_REG_CTRLEXT 0x0018 /* Extended Control Register */
49 #define I8254X_REG_MDIC 0x0020 /* MDI Control Register */
50 #define I8254X_REG_FCAL 0x0028 /* Flow Control Address Low */
51 #define I8254X_REG_FCAH 0x002c /* Flow Control Address High */
52 #define I8254X_REG_FCT 0x0030 /* Flow Control Type */
53 #define I8254X_REG_VET 0x0038 /* VLAN Ether Type */
54 #define I8254X_REG_ICR 0x00c0 /* Interrupt Cause Read */
55 #define I8254X_REG_ITR 0x00c4 /* Interrupt Throttling Register */
56 #define I8254X_REG_ICS 0x00c8 /* Interrupt Cause Set Register */
57 #define I8254X_REG_IMS 0x00d0 /* Interrupt Mask Set/Read Register */
58 #define I8254X_REG_IMC 0x00d8 /* Interrupt Mask Clear Register */
59 #define I8254X_REG_RCTL 0x0100 /* Receive Control Register */
60 #define I8254X_REG_FCTTV 0x0170 /* Flow Control Transmit Timer Value */
61 #define I8254X_REG_TXCW 0x0178 /* Transmit Configuration Word */
62 #define I8254X_REG_RXCW 0x0180 /* Receive Configuration Word */
63 #define I8254X_REG_TCTL 0x0400 /* Transmit Control Register */
64 #define I8254X_REG_TIPG 0x0410 /* Transmit Inter Packet Gap */
65
66 #define I8254X_REG_LEDCTL 0x0E00 /* LED Control */
67 #define I8254X_REG_PBA 0x1000 /* Packet Buffer Allocation */
68
69 #define I8254X_REG_RDBAL 0x2800 /* RX Descriptor Base Address Low */
70 #define I8254X_REG_RDBAH 0x2804 /* RX Descriptor Base Address High */
71 #define I8254X_REG_RDLEN 0x2808 /* RX Descriptor Length */
72 #define I8254X_REG_RDH 0x2810 /* RX Descriptor Head */
73 #define I8254X_REG_RDT 0x2818 /* RX Descriptor Tail */
74 #define I8254X_REG_RDTR 0x2820 /* RX Delay Timer Register */
75 #define I8254X_REG_RXDCTL 0x3828 /* RX Descriptor Control */
76 #define I8254X_REG_RADV 0x282c /* RX Int. Absolute Delay Timer */
77 #define I8254X_REG_RSRPD 0x2c00 /* RX Small Packet Detect Interrupt */
78
79 #define I8254X_REG_TXDMAC 0x3000 /* TX DMA Control */
80 #define I8254X_REG_TDBAL 0x3800 /* TX Descriptor Base Address Low */
81 #define I8254X_REG_TDBAH 0x3804 /* TX Descriptor Base Address Low */
82 #define I8254X_REG_TDLEN 0x3808 /* TX Descriptor Length */
83 #define I8254X_REG_TDH 0x3810 /* TX Descriptor Head */
84 #define I8254X_REG_TDT 0x3818 /* TX Descriptor Tail */
85 #define I8254X_REG_TIDV 0x3820 /* TX Interrupt Delay Value */
86 #define I8254X_REG_TXDCTL 0x3828 /* TX Descriptor Control */
87 #define I8254X_REG_TADV 0x382c /* TX Absolute Interrupt Delay Value */
88 #define I8254X_REG_TSPMT 0x3830 /* TCP Segmentation Pad & Min Threshold */
89
90 #define I8254X_REG_RXCSUM 0x5000 /* RX Checksum Control */
91
92 /* Register list for i8254x */
93 #define I82542_REG_RDTR 0x0108 /* RX Delay Timer Register */
94 #define I82542_REG_RDBAL 0x0110 /* RX Descriptor Base Address Low */
95 #define I82542_REG_RDBAH 0x0114 /* RX Descriptor Base Address High */
96 #define I82542_REG_RDLEN 0x0118 /* RX Descriptor Length */
97 #define I82542_REG_RDH 0x0120 /* RDH for i82542 */
98 #define I82542_REG_RDT 0x0128 /* RDT for i82542 */
99 #define I82542_REG_TDBAL 0x0420 /* TX Descriptor Base Address Low */
100 #define I82542_REG_TDBAH 0x0424 /* TX Descriptor Base Address Low */
101 #define I82542_REG_TDLEN 0x0428 /* TX Descriptor Length */
102 #define I82542_REG_TDH 0x0430 /* TDH for i82542 */
103 #define I82542_REG_TDT 0x0438 /* TDT for i82542 */
104
105 /* CTRL - Control Register (0x0000) */
106 #define I8254X_CTRL_FD 0x00000001 /* Full Duplex */
107 #define I8254X_CTRL_LRST 0x00000008 /* Link Reset */
108 #define I8254X_CTRL_ASDE 0x00000020 /* Auto-speed detection */
109 #define I8254X_CTRL_SLU 0x00000040 /* Set Link Up */
110 #define I8254X_CTRL_ILOS 0x00000080 /* Invert Loss of Signal */
111 #define I8254X_CTRL_SPEED_MASK 0x00000300 /* Speed selection */
112 #define I8254X_CTRL_SPEED_SHIFT 8
113 #define I8254X_CTRL_FRCSPD 0x00000800 /* Force Speed */
114 #define I8254X_CTRL_FRCDPLX 0x00001000 /* Force Duplex */
115 #define I8254X_CTRL_SDP0_DATA 0x00040000 /* SDP0 data */
116 #define I8254X_CTRL_SDP1_DATA 0x00080000 /* SDP1 data */
117 #define I8254X_CTRL_SDP0_IODIR 0x00400000 /* SDP0 direction */
118 #define I8254X_CTRL_SDP1_IODIR 0x00800000 /* SDP1 direction */
119 #define I8254X_CTRL_RST 0x04000000 /* Device Reset */
120 #define I8254X_CTRL_RFCE 0x08000000 /* RX Flow Ctrl Enable */
121 #define I8254X_CTRL_TFCE 0x10000000 /* TX Flow Ctrl Enable */
122 #define I8254X_CTRL_VME 0x40000000 /* VLAN Mode Enable */
123 #define I8254X_CTRL_PHY_RST 0x80000000 /* PHY reset */
124
125 /* STATUS - Device Status Register (0x0008) */
126 #define I8254X_STATUS_FD 0x00000001 /* Full Duplex */
127 #define I8254X_STATUS_LU 0x00000002 /* Link Up */
128 #define I8254X_STATUS_TXOFF 0x00000010 /* Transmit paused */
129 #define I8254X_STATUS_TBIMODE 0x00000020 /* TBI Mode */
130 #define I8254X_STATUS_SPEED_MASK 0x000000C0 /* Link Speed setting */
131 #define I8254X_STATUS_SPEED_SHIFT 6
132 #define I8254X_STATUS_ASDV_MASK 0x00000300 /* Auto Speed Detection */
133 #define I8254X_STATUS_ASDV_SHIFT 8
134 #define I8254X_STATUS_PCI66 0x00000800 /* PCI bus speed */
135 #define I8254X_STATUS_BUS64 0x00001000 /* PCI bus width */
136 #define I8254X_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */
137 #define I8254X_STATUS_PCIXSPD_MASK 0x0000C000 /* PCI-X speed */
138 #define I8254X_STATUS_PCIXSPD_SHIFT 14
139
140 /* CTRL_EXT - Extended Device Control Register (0x0018) */
141 #define I8254X_CTRLEXT_PHY_INT 0x00000020 /* PHY interrupt */
142 #define I8254X_CTRLEXT_SDP6_DATA 0x00000040 /* SDP6 data */
143 #define I8254X_CTRLEXT_SDP7_DATA 0x00000080 /* SDP7 data */
144 #define I8254X_CTRLEXT_SDP6_IODIR 0x00000400 /* SDP6 direction */
145 #define I8254X_CTRLEXT_SDP7_IODIR 0x00000800 /* SDP7 direction */
146 #define I8254X_CTRLEXT_ASDCHK 0x00001000 /* Auto-Speed Detect Chk */
147 #define I8254X_CTRLEXT_EE_RST 0x00002000 /* EEPROM reset */
148 #define I8254X_CTRLEXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */
149 #define I8254X_CTRLEXT_RO_DIS 0x00020000 /* Relaxed Ordering Dis. */
150 #define I8254X_CTRLEXT_LNKMOD_MASK 0x00C00000 /* Link Mode */
151 #define I8254X_CTRLEXT_LNKMOD_SHIFT 22
152
153 /* MDIC - MDI Control Register (0x0020) */
154 #define I8254X_MDIC_DATA_MASK 0x0000FFFF /* Data */
155 #define I8254X_MDIC_REG_MASK 0x001F0000 /* PHY Register */
156 #define I8254X_MDIC_REG_SHIFT 16
157 #define I8254X_MDIC_PHY_MASK 0x03E00000 /* PHY Address */
158 #define I8254X_MDIC_PHY_SHIFT 21
159 #define I8254X_MDIC_OP_MASK 0x0C000000 /* Opcode */
160 #define I8254X_MDIC_OP_SHIFT 26
161 #define I8254X_MDIC_R 0x10000000 /* Ready */
162 #define I8254X_MDIC_I 0x20000000 /* Interrupt Enable */
163 #define I8254X_MDIC_E 0x40000000 /* Error */
164
165 /* ICR - Interrupt Cause Read (0x00c0) */
166 #define I8254X_ICR_TXDW 0x00000001 /* TX Desc Written back */
167 #define I8254X_ICR_TXQE 0x00000002 /* TX Queue Empty */
168 #define I8254X_ICR_LSC 0x00000004 /* Link Status Change */
169 #define I8254X_ICR_RXSEQ 0x00000008 /* RX Sequence Error */
170 #define I8254X_ICR_RXDMT0 0x00000010 /* RX Desc min threshold reached */
171 #define I8254X_ICR_RXO 0x00000040 /* RX Overrun */
172 #define I8254X_ICR_RXT0 0x00000080 /* RX Timer Interrupt */
173 #define I8254X_ICR_MDAC 0x00000200 /* MDIO Access Complete */
174 #define I8254X_ICR_RXCFG 0x00000400
175 #define I8254X_ICR_PHY_INT 0x00001000 /* PHY Interrupt */
176 #define I8254X_ICR_GPI_SDP6 0x00002000 /* GPI on SDP6 */
177 #define I8254X_ICR_GPI_SDP7 0x00004000 /* GPI on SDP7 */
178 #define I8254X_ICR_TXD_LOW 0x00008000 /* TX Desc low threshold hit */
179 #define I8254X_ICR_SRPD 0x00010000 /* Small RX packet detected */
180
181 /* RCTL - Receive Control Register (0x0100) */
182 #define I8254X_RCTL_EN 0x00000002 /* Receiver Enable */
183 #define I8254X_RCTL_SBP 0x00000004 /* Store Bad Packets */
184 #define I8254X_RCTL_UPE 0x00000008 /* Unicast Promiscuous Enabled */
185 #define I8254X_RCTL_MPE 0x00000010 /* Xcast Promiscuous Enabled */
186 #define I8254X_RCTL_LPE 0x00000020 /* Long Packet Reception Enable */
187 #define I8254X_RCTL_LBM_MASK 0x000000C0 /* Loopback Mode */
188 #define I8254X_RCTL_LBM_SHIFT 6
189 #define I8254X_RCTL_RDMTS_MASK 0x00000300 /* RX Desc Min Threshold Size */
190 #define I8254X_RCTL_RDMTS_SHIFT 8
191 #define I8254X_RCTL_MO_MASK 0x00003000 /* Multicast Offset */
192 #define I8254X_RCTL_MO_SHIFT 12
193 #define I8254X_RCTL_BAM 0x00008000 /* Broadcast Accept Mode */
194 #define I8254X_RCTL_BSIZE_MASK 0x00030000 /* RX Buffer Size */
195 #define I8254X_RCTL_BSIZE_SHIFT 16
196 #define I8254X_RCTL_VFE 0x00040000 /* VLAN Filter Enable */
197 #define I8254X_RCTL_CFIEN 0x00080000 /* CFI Enable */
198 #define I8254X_RCTL_CFI 0x00100000 /* Canonical Form Indicator Bit */
199 #define I8254X_RCTL_DPF 0x00400000 /* Discard Pause Frames */
200 #define I8254X_RCTL_PMCF 0x00800000 /* Pass MAC Control Frames */
201 #define I8254X_RCTL_BSEX 0x02000000 /* Buffer Size Extension */
202 #define I8254X_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */
203
204 /* TCTL - Transmit Control Register (0x0400) */
205 #define I8254X_TCTL_EN 0x00000002 /* Transmit Enable */
206 #define I8254X_TCTL_PSP 0x00000008 /* Pad short packets */
207 #define I8254X_TCTL_SWXOFF 0x00400000 /* Software XOFF Transmission */
208
209 /* PBA - Packet Buffer Allocation (0x1000) */
210 #define I8254X_PBA_RXA_MASK 0x0000FFFF /* RX Packet Buffer */
211 #define I8254X_PBA_RXA_SHIFT 0
212 #define I8254X_PBA_TXA_MASK 0xFFFF0000 /* TX Packet Buffer */
213 #define I8254X_PBA_TXA_SHIFT 16
214
215 /* Flow Control Type */
216 #define I8254X_FCT_TYPE_DEFAULT 0x8808
217
218 /* === TX Descriptor fields === */
219
220 /* TX Packet Length (word 2) */
221 #define I8254X_TXDESC_LEN_MASK 0x0000ffff
222
223 /* TX Descriptor CMD field (word 2) */
224 #define I8254X_TXDESC_IDE 0x80000000 /* Interrupt Delay Enable */
225 #define I8254X_TXDESC_VLE 0x40000000 /* VLAN Packet Enable */
226 #define I8254X_TXDESC_DEXT 0x20000000 /* Extension */
227 #define I8254X_TXDESC_RPS 0x10000000 /* Report Packet Sent */
228 #define I8254X_TXDESC_RS 0x08000000 /* Report Status */
229 #define I8254X_TXDESC_IC 0x04000000 /* Insert Checksum */
230 #define I8254X_TXDESC_IFCS 0x02000000 /* Insert FCS */
231 #define I8254X_TXDESC_EOP 0x01000000 /* End Of Packet */
232
233 /* TX Descriptor STA field (word 3) */
234 #define I8254X_TXDESC_TU 0x00000008 /* Transmit Underrun */
235 #define I8254X_TXDESC_LC 0x00000004 /* Late Collision */
236 #define I8254X_TXDESC_EC 0x00000002 /* Excess Collisions */
237 #define I8254X_TXDESC_DD 0x00000001 /* Descriptor Done */
238
239 /* === RX Descriptor fields === */
240
241 /* RX Packet Length (word 2) */
242 #define I8254X_RXDESC_LEN_MASK 0x0000ffff
243
244 /* RX Descriptor STA field (word 3) */
245 #define I8254X_RXDESC_PIF 0x00000080 /* Passed In-exact Filter */
246 #define I8254X_RXDESC_IPCS 0x00000040 /* IP cksum calculated */
247 #define I8254X_RXDESC_TCPCS 0x00000020 /* TCP cksum calculated */
248 #define I8254X_RXDESC_VP 0x00000008 /* Packet is 802.1Q */
249 #define I8254X_RXDESC_IXSM 0x00000004 /* Ignore cksum indication */
250 #define I8254X_RXDESC_EOP 0x00000002 /* End Of Packet */
251 #define I8254X_RXDESC_DD 0x00000001 /* Descriptor Done */
252
253 /* Intel i8254x private data */
254 struct i8254x_data {
255 char *name;
256
257 /* Lock test */
258 pthread_mutex_t lock;
259
260 /* Physical (MAC) address */
261 n_eth_addr_t mac_addr;
262
263 /* Device information */
264 struct vdevice *dev;
265
266 /* PCI device information */
267 struct pci_device *pci_dev;
268
269 /* Virtual machine */
270 vm_instance_t *vm;
271
272 /* NetIO descriptor */
273 netio_desc_t *nio;
274
275 /* TX ring scanner task id */
276 ptask_id_t tx_tid;
277
278 /* Interrupt registers */
279 m_uint32_t icr,imr;
280
281 /* Device Control Register */
282 m_uint32_t ctrl;
283
284 /* Extended Control Register */
285 m_uint32_t ctrl_ext;
286
287 /* Flow Control registers */
288 m_uint32_t fcal,fcah,fct;
289
290 /* RX Delay Timer */
291 m_uint32_t rdtr;
292
293 /* RX/TX Control Registers */
294 m_uint32_t rctl,tctl;
295
296 /* RX buffer size (computed from RX control register */
297 m_uint32_t rx_buf_size;
298
299 /* RX/TX ring base addresses */
300 m_uint64_t rx_addr,tx_addr;
301
302 /* RX/TX descriptor length */
303 m_uint32_t rdlen,tdlen;
304
305 /* RX/TX descriptor head and tail */
306 m_uint32_t rdh,rdt,tdh,tdt;
307
308 /* TX packet buffer */
309 m_uint8_t tx_buffer[I8254X_MAX_PKT_SIZE];
310
311 /* RX IRQ count */
312 m_uint32_t rx_irq_cnt;
313
314 /* MII/PHY handling */
315 u_int mii_state;
316 u_int mii_bit;
317 u_int mii_opcode;
318 u_int mii_phy;
319 u_int mii_reg;
320 u_int mii_data_pos;
321 u_int mii_data;
322 u_int mii_regs[32][32];
323 };
324
325 /* TX descriptor */
326 struct tx_desc {
327 m_uint32_t tdes[4];
328 };
329
330 /* RX descriptor */
331 struct rx_desc {
332 m_uint32_t rdes[4];
333 };
334
335 #define LVG_LOCK(d) pthread_mutex_lock(&(d)->lock)
336 #define LVG_UNLOCK(d) pthread_mutex_unlock(&(d)->lock)
337
338 /* Log an message */
339 #define LVG_LOG(d,msg...) vm_log((d)->vm,(d)->name,msg)
340
341 /* Read a MII register */
mii_reg_read(struct i8254x_data * d)342 static m_uint16_t mii_reg_read(struct i8254x_data *d)
343 {
344 #if DEBUG_MII_REGS
345 LVG_LOG(d,"MII PHY read %d reg %d\n",d->mii_phy,d->mii_reg);
346 #endif
347
348 switch(d->mii_reg) {
349 case 0x00:
350 return((d->mii_regs[d->mii_phy][d->mii_reg] & ~0x8200) | 0x2000);
351 case 0x01:
352 return(0x782c);
353 case 0x02:
354 return(0x0013);
355 case 0x03:
356 return(0x61d4);
357 case 0x05:
358 return(0x41e1);
359 case 0x06:
360 return(0x0001);
361 case 0x11:
362 return(0x4700);
363 default:
364 return(d->mii_regs[d->mii_phy][d->mii_reg]);
365 }
366 }
367
368 /* Write a MII register */
mii_reg_write(struct i8254x_data * d)369 static void mii_reg_write(struct i8254x_data *d)
370 {
371 #if DEBUG_MII_REGS
372 LVG_LOG(d,"MII PHY write %d reg %d value %04x\n",
373 d->mii_phy,d->mii_reg,d->mii_data);
374 #endif
375 assert(d->mii_phy < 32);
376 assert(d->mii_reg < 32);
377 d->mii_regs[d->mii_phy][d->mii_reg] = d->mii_data;
378 }
379
380 enum {
381 MII_OPCODE_READ = 1,
382 MII_OPCODE_WRITE,
383 };
384
385 /* MII Finite State Machine */
mii_access(struct i8254x_data * d)386 static void mii_access(struct i8254x_data *d)
387 {
388 switch(d->mii_state) {
389 case 0: /* reset */
390 d->mii_phy = 0;
391 d->mii_reg = 0;
392 d->mii_data_pos = 15;
393 d->mii_data = 0;
394
395 case 1: /* idle */
396 if (!d->mii_bit)
397 d->mii_state = 2;
398 else
399 d->mii_state = 1;
400 break;
401
402 case 2: /* start */
403 d->mii_state = d->mii_bit ? 3 : 0;
404 break;
405
406 case 3: /* opcode */
407 d->mii_state = d->mii_bit ? 4 : 5;
408 break;
409
410 case 4: /* read: opcode "10" */
411 if (!d->mii_bit) {
412 d->mii_opcode = MII_OPCODE_READ;
413 d->mii_state = 6;
414 } else {
415 d->mii_state = 0;
416 }
417 break;
418
419 case 5: /* write: opcode "01" */
420 if (d->mii_bit) {
421 d->mii_opcode = MII_OPCODE_WRITE;
422 d->mii_state = 6;
423 } else {
424 d->mii_state = 0;
425 }
426 break;
427
428 case 6 ... 10: /* phy */
429 d->mii_phy <<= 1;
430 d->mii_phy |= d->mii_bit;
431 d->mii_state++;
432 break;
433
434 case 11 ... 15: /* reg */
435 d->mii_reg <<= 1;
436 d->mii_reg |= d->mii_bit;
437 d->mii_state++;
438 break;
439
440 case 16 ... 17: /* ta */
441 if (d->mii_opcode == MII_OPCODE_READ)
442 d->mii_state = 18;
443 else
444 d->mii_state++;
445 break;
446
447 case 18:
448 if (d->mii_opcode == MII_OPCODE_READ) {
449 d->mii_data = mii_reg_read(d);
450 d->mii_state++;
451 }
452
453 case 19 ... 35:
454 if (d->mii_opcode == MII_OPCODE_READ) {
455 d->mii_bit = (d->mii_data >> d->mii_data_pos) & 0x1;
456 } else {
457 d->mii_data |= d->mii_bit << d->mii_data_pos;
458 }
459
460 if (!d->mii_data_pos) {
461 if (d->mii_opcode == MII_OPCODE_WRITE)
462 mii_reg_write(d);
463 d->mii_state = 0;
464 } else {
465 d->mii_state++;
466 }
467
468 d->mii_data_pos--;
469 break;
470
471 default:
472 printf("MII: impossible state %u!\n",d->mii_state);
473 }
474 }
475
476 /* Update the interrupt status */
dev_i8254x_update_irq_status(struct i8254x_data * d)477 static inline void dev_i8254x_update_irq_status(struct i8254x_data *d)
478 {
479 if (d->icr & d->imr)
480 pci_dev_trigger_irq(d->vm,d->pci_dev);
481 else
482 pci_dev_clear_irq(d->vm,d->pci_dev);
483 }
484
485 /* Compute RX buffer size */
dev_i8254x_set_rx_buf_size(struct i8254x_data * d)486 static inline void dev_i8254x_set_rx_buf_size(struct i8254x_data *d)
487 {
488 m_uint32_t bsize;
489
490 bsize = (d->rctl & I8254X_RCTL_BSIZE_MASK) >> I8254X_RCTL_BSIZE_SHIFT;
491
492 if (!(d->rctl & I8254X_RCTL_BSEX)) {
493 /* Standard buffer sizes */
494 switch(bsize) {
495 case 0:
496 d->rx_buf_size = 2048;
497 break;
498 case 1:
499 d->rx_buf_size = 1024;
500 break;
501 case 2:
502 d->rx_buf_size = 512;
503 break;
504 case 3:
505 d->rx_buf_size = 256;
506 break;
507 }
508 } else {
509 /* Extended buffer sizes */
510 switch(bsize) {
511 case 0:
512 d->rx_buf_size = 0; /* invalid */
513 break;
514 case 1:
515 d->rx_buf_size = 16384;
516 break;
517 case 2:
518 d->rx_buf_size = 8192;
519 break;
520 case 3:
521 d->rx_buf_size = 4096;
522 break;
523 }
524 }
525 }
526
527 /*
528 * dev_i8254x_access()
529 */
dev_i8254x_access(cpu_gen_t * cpu,struct vdevice * dev,m_uint32_t offset,u_int op_size,u_int op_type,m_uint64_t * data)530 void *dev_i8254x_access(cpu_gen_t *cpu,struct vdevice *dev,
531 m_uint32_t offset,u_int op_size,u_int op_type,
532 m_uint64_t *data)
533 {
534 struct i8254x_data *d = dev->priv_data;
535
536 if (op_type == MTS_READ)
537 *data = 0x0;
538
539 #if DEBUG_ACCESS
540 if (op_type == MTS_READ) {
541 cpu_log(cpu,d->name,"read access to offset=0x%x, pc=0x%llx, size=%u\n",
542 offset,cpu_get_pc(cpu),op_size);
543 } else {
544 cpu_log(cpu,d->name,"write access to offset=0x%x, pc=0x%llx, "
545 "val=0x%llx, size=%u\n",offset,cpu_get_pc(cpu),*data,op_size);
546 }
547 #endif
548
549 LVG_LOCK(d);
550
551 switch(offset) {
552 #if 0 /* TODO */
553 case 0x180:
554 if (op_type == MTS_READ)
555 *data = 0xFFFFFFFF; //0xDC004020; //1 << 31;
556 break;
557 #endif
558
559 /* Link is Up and Full Duplex */
560 case I8254X_REG_STATUS:
561 if (op_type == MTS_READ)
562 *data = I8254X_STATUS_LU | I8254X_STATUS_FD;
563 break;
564
565 /* Device Control Register */
566 case I8254X_REG_CTRL:
567 if (op_type == MTS_WRITE)
568 d->ctrl = *data;
569 else
570 *data = d->ctrl;
571 break;
572
573 /* Extended Device Control Register */
574 case I8254X_REG_CTRLEXT:
575 if (op_type == MTS_WRITE) {
576 /* MDIO clock set ? */
577 if (!(d->ctrl_ext & I8254X_CTRLEXT_SDP6_DATA) &&
578 (*data & I8254X_CTRLEXT_SDP6_DATA))
579 {
580 if (*data & I8254X_CTRLEXT_SDP7_IODIR)
581 d->mii_bit = (*data & I8254X_CTRLEXT_SDP7_DATA) ? 1 : 0;
582
583 mii_access(d);
584 }
585
586 d->ctrl_ext = *data;
587 } else {
588 *data = d->ctrl_ext;
589
590 if (!(d->ctrl_ext & I8254X_CTRLEXT_SDP7_IODIR)) {
591 if (d->mii_bit)
592 *data |= I8254X_CTRLEXT_SDP7_DATA;
593 else
594 *data &= ~I8254X_CTRLEXT_SDP7_DATA;
595 }
596 }
597 break;
598
599 /* XXX */
600 case I8254X_REG_MDIC:
601 if (op_type == MTS_READ)
602 *data = 1 << 28;
603 break;
604
605 /*
606 * Interrupt Cause Read Register.
607 *
608 * Notice: a read clears all interrupt bits.
609 */
610 case I8254X_REG_ICR:
611 if (op_type == MTS_READ) {
612 *data = d->icr;
613 d->icr = 0;
614
615 if (d->rx_irq_cnt > 0) {
616 d->icr |= I8254X_ICR_RXT0;
617 d->rx_irq_cnt--;
618 }
619
620 dev_i8254x_update_irq_status(d);
621 }
622 break;
623
624 /* Interrupt Cause Set Register */
625 case I8254X_REG_ICS:
626 if (op_type == MTS_WRITE) {
627 d->icr |= *data;
628 dev_i8254x_update_irq_status(d);
629 }
630 break;
631
632 /* Interrupt Mask Set/Read Register */
633 case I8254X_REG_IMS:
634 if (op_type == MTS_WRITE) {
635 d->imr |= *data;
636 dev_i8254x_update_irq_status(d);
637 } else {
638 *data = d->imr;
639 }
640 break;
641
642 /* Interrupt Mask Clear Register */
643 case I8254X_REG_IMC:
644 if (op_type == MTS_WRITE) {
645 d->imr &= ~(*data);
646 dev_i8254x_update_irq_status(d);
647 }
648 break;
649
650 /* Receive Control Register */
651 case I8254X_REG_RCTL:
652 if (op_type == MTS_READ) {
653 *data = d->rctl;
654 } else {
655 d->rctl = *data;
656 dev_i8254x_set_rx_buf_size(d);
657 }
658 break;
659
660 /* Transmit Control Register */
661 case I8254X_REG_TCTL:
662 if (op_type == MTS_READ)
663 *data = d->tctl;
664 else
665 d->tctl = *data;
666 break;
667
668 /* RX Descriptor Base Address Low */
669 case I8254X_REG_RDBAL:
670 case I82542_REG_RDBAL:
671 if (op_type == MTS_WRITE) {
672 d->rx_addr &= 0xFFFFFFFF00000000ULL;
673 d->rx_addr |= (m_uint32_t)(*data);
674 } else {
675 *data = (m_uint32_t)d->rx_addr;
676 }
677 break;
678
679 /* RX Descriptor Base Address High */
680 case I8254X_REG_RDBAH:
681 case I82542_REG_RDBAH:
682 if (op_type == MTS_WRITE) {
683 d->rx_addr &= 0x00000000FFFFFFFFULL;
684 d->rx_addr |= *data << 32;
685 } else {
686 *data = d->rx_addr >> 32;
687 }
688 break;
689
690 /* TX Descriptor Base Address Low */
691 case I8254X_REG_TDBAL:
692 case I82542_REG_TDBAL:
693 if (op_type == MTS_WRITE) {
694 d->tx_addr &= 0xFFFFFFFF00000000ULL;
695 d->tx_addr |= (m_uint32_t)(*data);
696 } else {
697 *data = (m_uint32_t)d->tx_addr;
698 }
699 break;
700
701 /* TX Descriptor Base Address High */
702 case I8254X_REG_TDBAH:
703 case I82542_REG_TDBAH:
704 if (op_type == MTS_WRITE) {
705 d->tx_addr &= 0x00000000FFFFFFFFULL;
706 d->tx_addr |= *data << 32;
707 } else {
708 *data = d->tx_addr >> 32;
709 }
710 break;
711
712 /* RX Descriptor Length */
713 case I8254X_REG_RDLEN:
714 case I82542_REG_RDLEN:
715 if (op_type == MTS_WRITE)
716 d->rdlen = *data & 0xFFF80;
717 else
718 *data = d->rdlen;
719 break;
720
721 /* TX Descriptor Length */
722 case I8254X_REG_TDLEN:
723 case I82542_REG_TDLEN:
724 if (op_type == MTS_WRITE)
725 d->tdlen = *data & 0xFFF80;
726 else
727 *data = d->tdlen;
728 break;
729
730 /* RX Descriptor Head */
731 case I82542_REG_RDH:
732 case I8254X_REG_RDH:
733 if (op_type == MTS_WRITE)
734 d->rdh = *data & 0xFFFF;
735 else
736 *data = d->rdh;
737 break;
738
739 /* RX Descriptor Tail */
740 case I8254X_REG_RDT:
741 case I82542_REG_RDT:
742 if (op_type == MTS_WRITE)
743 d->rdt = *data & 0xFFFF;
744 else
745 *data = d->rdt;
746 break;
747
748 /* TX Descriptor Head */
749 case I82542_REG_TDH:
750 case I8254X_REG_TDH:
751 if (op_type == MTS_WRITE)
752 d->tdh = *data & 0xFFFF;
753 else
754 *data = d->tdh;
755 break;
756
757 /* TX Descriptor Tail */
758 case I82542_REG_TDT:
759 case I8254X_REG_TDT:
760 if (op_type == MTS_WRITE)
761 d->tdt = *data & 0xFFFF;
762 else
763 *data = d->tdt;
764 break;
765
766 /* Flow Control Address Low */
767 case I8254X_REG_FCAL:
768 if (op_type == MTS_WRITE)
769 d->fcal = *data;
770 else
771 *data = d->fcal;
772 break;
773
774 /* Flow Control Address High */
775 case I8254X_REG_FCAH:
776 if (op_type == MTS_WRITE)
777 d->fcah = *data & 0xFFFF;
778 else
779 *data = d->fcah;
780 break;
781
782 /* Flow Control Type */
783 case I8254X_REG_FCT:
784 if (op_type == MTS_WRITE)
785 d->fct = *data & 0xFFFF;
786 else
787 *data = d->fct;
788 break;
789
790 /* RX Delay Timer */
791 case I8254X_REG_RDTR:
792 case I82542_REG_RDTR:
793 if (op_type == MTS_WRITE)
794 d->rdtr = *data & 0xFFFF;
795 else
796 *data = d->rdtr;
797 break;
798
799 #if DEBUG_UNKNOWN
800 default:
801 if (op_type == MTS_READ) {
802 cpu_log(cpu,d->name,
803 "read access to unknown offset=0x%x, "
804 "pc=0x%llx (size=%u)\n",
805 offset,cpu_get_pc(cpu),op_size);
806 } else {
807 cpu_log(cpu,d->name,
808 "write access to unknown offset=0x%x, pc=0x%llx, "
809 "val=0x%llx (size=%u)\n",
810 offset,cpu_get_pc(cpu),*data,op_size);
811 }
812 #endif
813 }
814
815 LVG_UNLOCK(d);
816 return NULL;
817 }
818
819 /* Read a TX descriptor */
txdesc_read(struct i8254x_data * d,m_uint64_t txd_addr,struct tx_desc * txd)820 static void txdesc_read(struct i8254x_data *d,m_uint64_t txd_addr,
821 struct tx_desc *txd)
822 {
823 /* Get the descriptor from VM physical RAM */
824 physmem_copy_from_vm(d->vm,txd,txd_addr,sizeof(struct tx_desc));
825
826 /* byte-swapping */
827 txd->tdes[0] = vmtoh32(txd->tdes[0]);
828 txd->tdes[1] = vmtoh32(txd->tdes[1]);
829 txd->tdes[2] = vmtoh32(txd->tdes[2]);
830 txd->tdes[3] = vmtoh32(txd->tdes[3]);
831 }
832
833 /* Handle the TX ring (single packet) */
dev_i8254x_handle_txring_single(struct i8254x_data * d)834 static int dev_i8254x_handle_txring_single(struct i8254x_data *d)
835 {
836 m_uint64_t txd_addr,buf_addr;
837 m_uint32_t buf_len,tot_len;
838 m_uint32_t norm_len,icr;
839 struct tx_desc txd;
840 m_uint8_t *pkt_ptr;
841
842 /* If Head is at same position than Tail, the ring is empty */
843 if (d->tdh == d->tdt)
844 return(FALSE);
845
846 /* Check if the NIO can transmit */
847 if (!netio_can_transmit(d->nio))
848 return(FALSE);
849
850 /* Empty packet for now */
851 pkt_ptr = d->tx_buffer;
852 tot_len = 0;
853 icr = 0;
854
855 while(d->tdh != d->tdt) {
856 txd_addr = d->tx_addr + (d->tdh * sizeof(struct tx_desc));
857 txdesc_read(d,txd_addr,&txd);
858
859 /* Copy the packet buffer */
860 buf_addr = ((m_uint64_t)txd.tdes[1] << 32) | txd.tdes[0];
861 buf_len = txd.tdes[2] & I8254X_TXDESC_LEN_MASK;
862
863 #if DEBUG_TRANSMIT
864 LVG_LOG(d,"copying data from 0x%8.8llx (buf_len=%u)\n",buf_addr,buf_len);
865 #endif
866 norm_len = normalize_size(buf_len,4,0);
867 physmem_copy_from_vm(d->vm,pkt_ptr,buf_addr,norm_len);
868 mem_bswap32(pkt_ptr,norm_len);
869
870 pkt_ptr += buf_len;
871 tot_len += buf_len;
872
873 /* Write the descriptor done bit if required */
874 if (txd.tdes[2] & I8254X_TXDESC_RS) {
875 txd.tdes[3] |= I8254X_TXDESC_DD;
876 icr |= I8254X_ICR_TXDW;
877 physmem_copy_u32_to_vm(d->vm,txd_addr+0x0c,txd.tdes[3]);
878 }
879
880 /* Go to the next descriptor. Wrap ring if we are at end */
881 if (++d->tdh == (d->tdlen / sizeof(struct tx_desc)))
882 d->tdh = 0;
883
884 /* End of packet ? */
885 if (txd.tdes[2] & I8254X_TXDESC_EOP) {
886 #if DEBUG_TRANSMIT
887 LVG_LOG(d,"sending packet of %u bytes\n",tot_len);
888 mem_dump(log_file,d->tx_buffer,tot_len);
889 #endif
890 netio_send(d->nio,d->tx_buffer,tot_len);
891 break;
892 }
893 }
894
895 if (d->tdh == d->tdt)
896 icr |= I8254X_ICR_TXQE;
897
898 /* Update the interrupt cause register and trigger IRQ if needed */
899 d->icr |= icr;
900 dev_i8254x_update_irq_status(d);
901 return(TRUE);
902 }
903
904 /* Handle the TX ring */
dev_i8254x_handle_txring(struct i8254x_data * d)905 static int dev_i8254x_handle_txring(struct i8254x_data *d)
906 {
907 int res,i;
908
909 /* Transmit Enabled ? */
910 if (!(d->tctl & I8254X_TCTL_EN))
911 return(FALSE);
912
913 for(i=0;i<I8254X_TXRING_PASS_COUNT;i++) {
914 LVG_LOCK(d);
915 res = dev_i8254x_handle_txring_single(d);
916 LVG_UNLOCK(d);
917
918 if (!res)
919 break;
920 }
921
922 netio_clear_bw_stat(d->nio);
923 return(TRUE);
924 }
925
926 /* Read a RX descriptor */
rxdesc_read(struct i8254x_data * d,m_uint64_t rxd_addr,struct rx_desc * rxd)927 static void rxdesc_read(struct i8254x_data *d,m_uint64_t rxd_addr,
928 struct rx_desc *rxd)
929 {
930 /* Get the descriptor from VM physical RAM */
931 physmem_copy_from_vm(d->vm,rxd,rxd_addr,sizeof(struct rx_desc));
932
933 /* byte-swapping */
934 rxd->rdes[0] = vmtoh32(rxd->rdes[0]);
935 rxd->rdes[1] = vmtoh32(rxd->rdes[1]);
936 rxd->rdes[2] = vmtoh32(rxd->rdes[2]);
937 rxd->rdes[3] = vmtoh32(rxd->rdes[3]);
938 }
939
940 /*
941 * Put a packet in the RX ring.
942 */
dev_i8254x_receive_pkt(struct i8254x_data * d,u_char * pkt,ssize_t pkt_len)943 static int dev_i8254x_receive_pkt(struct i8254x_data *d,
944 u_char *pkt,ssize_t pkt_len)
945 {
946 m_uint64_t rxd_addr,buf_addr;
947 m_uint32_t cur_len,norm_len,tot_len;
948 struct rx_desc rxd;
949 m_uint32_t icr;
950 u_char *pkt_ptr;
951
952 if (!d->rx_buf_size)
953 return(FALSE);
954
955 LVG_LOCK(d);
956 pkt_ptr = pkt;
957 tot_len = pkt_len;
958 icr = 0;
959
960 while(tot_len > 0) {
961 /* No descriptor available: RX overrun condition */
962 if (d->rdh == d->rdt) {
963 icr |= I8254X_ICR_RXO;
964 break;
965 }
966
967 rxd_addr = d->rx_addr + (d->rdh * sizeof(struct rx_desc));
968 rxdesc_read(d,rxd_addr,&rxd);
969
970 cur_len = (tot_len > d->rx_buf_size) ? d->rx_buf_size : tot_len;
971
972 /* Copy the packet data into the RX buffer */
973 buf_addr = ((m_uint64_t)rxd.rdes[1] << 32) | rxd.rdes[0];
974
975 norm_len = normalize_size(cur_len,4,0);
976 mem_bswap32(pkt_ptr,norm_len);
977 physmem_copy_to_vm(d->vm,pkt_ptr,buf_addr,norm_len);
978 tot_len -= cur_len;
979 pkt_ptr += cur_len;
980
981 /* Set length field */
982 rxd.rdes[2] = cur_len;
983
984 /* Set the status */
985 rxd.rdes[3] = I8254X_RXDESC_IXSM|I8254X_RXDESC_DD;
986
987 if (!tot_len) {
988 rxd.rdes[3] |= I8254X_RXDESC_EOP;
989 icr |= I8254X_ICR_RXT0;
990 d->rx_irq_cnt++;
991 rxd.rdes[2] += 4; /* FCS */
992 }
993
994 /* Write back updated descriptor */
995 physmem_copy_u32_to_vm(d->vm,rxd_addr+0x08,rxd.rdes[2]);
996 physmem_copy_u32_to_vm(d->vm,rxd_addr+0x0c,rxd.rdes[3]);
997
998 /* Goto to the next descriptor, and wrap if necessary */
999 if (++d->rdh == (d->rdlen / sizeof(struct rx_desc)))
1000 d->rdh = 0;
1001 }
1002
1003 /* Update the interrupt cause register and trigger IRQ if needed */
1004 d->icr |= icr;
1005 dev_i8254x_update_irq_status(d);
1006 LVG_UNLOCK(d);
1007 return(TRUE);
1008 }
1009
1010 /* Handle the RX ring */
dev_i8254x_handle_rxring(netio_desc_t * nio,u_char * pkt,ssize_t pkt_len,struct i8254x_data * d)1011 static int dev_i8254x_handle_rxring(netio_desc_t *nio,
1012 u_char *pkt,ssize_t pkt_len,
1013 struct i8254x_data *d)
1014 {
1015 /*
1016 * Don't start receive if RX has not been enabled in RCTL register.
1017 */
1018 if (!(d->rctl & I8254X_RCTL_EN))
1019 return(FALSE);
1020
1021 #if DEBUG_RECEIVE
1022 LVG_LOG(d,"receiving a packet of %d bytes\n",pkt_len);
1023 mem_dump(log_file,pkt,pkt_len);
1024 #endif
1025
1026 /*
1027 * Receive only multicast/broadcast trafic + unicast traffic
1028 * for this virtual machine.
1029 */
1030 //if (dec21140_handle_mac_addr(d,pkt))
1031 return(dev_i8254x_receive_pkt(d,pkt,pkt_len));
1032
1033 return(FALSE);
1034 }
1035
1036 /*
1037 * pci_i8254x_read()
1038 *
1039 * Read a PCI register.
1040 */
pci_i8254x_read(cpu_gen_t * cpu,struct pci_device * dev,int reg)1041 static m_uint32_t pci_i8254x_read(cpu_gen_t *cpu,struct pci_device *dev,
1042 int reg)
1043 {
1044 struct i8254x_data *d = dev->priv_data;
1045
1046 #if DEBUG_PCI_REGS
1047 I8254X_LOG(d,"read PCI register 0x%x\n",reg);
1048 #endif
1049
1050 switch (reg) {
1051 case 0x00:
1052 return((I8254X_PCI_PRODUCT_ID << 16) | I8254X_PCI_VENDOR_ID);
1053 case 0x08:
1054 return(0x02000003);
1055 case PCI_REG_BAR0:
1056 return(d->dev->phys_addr);
1057 default:
1058 return(0);
1059 }
1060 }
1061
1062 /*
1063 * pci_i8254x_write()
1064 *
1065 * Write a PCI register.
1066 */
pci_i8254x_write(cpu_gen_t * cpu,struct pci_device * dev,int reg,m_uint32_t value)1067 static void pci_i8254x_write(cpu_gen_t *cpu,struct pci_device *dev,
1068 int reg,m_uint32_t value)
1069 {
1070 struct i8254x_data *d = dev->priv_data;
1071
1072 #if DEBUG_PCI_REGS
1073 LVG_LOG(d,"write PCI register 0x%x, value 0x%x\n",reg,value);
1074 #endif
1075
1076 switch(reg) {
1077 case PCI_REG_BAR0:
1078 vm_map_device(cpu->vm,d->dev,(m_uint64_t)value);
1079 LVG_LOG(d,"registers are mapped at 0x%x\n",value);
1080 break;
1081 }
1082 }
1083
1084 /*
1085 * dev_i8254x_init()
1086 */
1087 struct i8254x_data *
dev_i8254x_init(vm_instance_t * vm,char * name,int interface_type,struct pci_bus * pci_bus,int pci_device,int irq)1088 dev_i8254x_init(vm_instance_t *vm,char *name,int interface_type,
1089 struct pci_bus *pci_bus,int pci_device,int irq)
1090 {
1091 struct i8254x_data *d;
1092 struct pci_device *pci_dev;
1093 struct vdevice *dev;
1094
1095 /* Allocate the private data structure for I8254X */
1096 if (!(d = malloc(sizeof(*d)))) {
1097 fprintf(stderr,"%s (i8254x): out of memory\n",name);
1098 return NULL;
1099 }
1100
1101 memset(d,0,sizeof(*d));
1102 pthread_mutex_init(&d->lock,NULL);
1103
1104 /* Add as PCI device */
1105 pci_dev = pci_dev_add(pci_bus,name,
1106 I8254X_PCI_VENDOR_ID,I8254X_PCI_PRODUCT_ID,
1107 pci_device,0,irq,
1108 d,NULL,pci_i8254x_read,pci_i8254x_write);
1109
1110 if (!pci_dev) {
1111 fprintf(stderr,"%s (i8254x): unable to create PCI device.\n",name);
1112 goto err_pci_dev;
1113 }
1114
1115 /* Create the device itself */
1116 if (!(dev = dev_create(name))) {
1117 fprintf(stderr,"%s (i8254x): unable to create device.\n",name);
1118 goto err_dev;
1119 }
1120
1121 d->name = name;
1122 d->vm = vm;
1123 d->pci_dev = pci_dev;
1124 d->dev = dev;
1125
1126 dev->phys_addr = 0;
1127 dev->phys_len = 0x10000;
1128 dev->handler = dev_i8254x_access;
1129 dev->priv_data = d;
1130 return(d);
1131
1132 err_dev:
1133 pci_dev_remove(pci_dev);
1134 err_pci_dev:
1135 free(d);
1136 return NULL;
1137 }
1138
1139 /* Remove an Intel i8254x device */
dev_i8254x_remove(struct i8254x_data * d)1140 void dev_i8254x_remove(struct i8254x_data *d)
1141 {
1142 if (d != NULL) {
1143 pci_dev_remove(d->pci_dev);
1144 vm_unbind_device(d->vm,d->dev);
1145 cpu_group_rebuild_mts(d->vm->cpu_group);
1146 free(d->dev);
1147 free(d);
1148 }
1149 }
1150
1151 /* Bind a NIO to an Intel i8254x device */
dev_i8254x_set_nio(struct i8254x_data * d,netio_desc_t * nio)1152 int dev_i8254x_set_nio(struct i8254x_data *d,netio_desc_t *nio)
1153 {
1154 /* check that a NIO is not already bound */
1155 if (d->nio != NULL)
1156 return(-1);
1157
1158 d->nio = nio;
1159 d->tx_tid = ptask_add((ptask_callback)dev_i8254x_handle_txring,d,NULL);
1160 netio_rxl_add(nio,(netio_rx_handler_t)dev_i8254x_handle_rxring,d,NULL);
1161 return(0);
1162 }
1163
1164 /* Unbind a NIO from an Intel i8254x device */
dev_i8254x_unset_nio(struct i8254x_data * d)1165 void dev_i8254x_unset_nio(struct i8254x_data *d)
1166 {
1167 if (d->nio != NULL) {
1168 ptask_remove(d->tx_tid);
1169 netio_rxl_remove(d->nio);
1170 d->nio = NULL;
1171 }
1172 }
1173