ia64/xen-unstable

view tools/ioemu/hw/lance.c @ 6946:e703abaf6e3d

Add behaviour to the remove methods to remove the transaction's path itself. This allows us to write Remove(path) to remove the specified path rather than having to slice the path ourselves.
author emellor@ewan
date Sun Sep 18 14:42:13 2005 +0100 (2005-09-18)
parents 8e5fc5fe636c
children f7b43e5c42b9
line source
1 /*
2 * QEMU Lance emulation
3 *
4 * Copyright (c) 2003-2004 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 #include "vl.h"
26 /* debug LANCE card */
27 //#define DEBUG_LANCE
29 #ifndef LANCE_LOG_TX_BUFFERS
30 #define LANCE_LOG_TX_BUFFERS 4
31 #define LANCE_LOG_RX_BUFFERS 4
32 #endif
34 #define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */
35 #define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */
38 #define LE_CSR0 0
39 #define LE_CSR1 1
40 #define LE_CSR2 2
41 #define LE_CSR3 3
42 #define LE_MAXREG (LE_CSR3 + 1)
44 #define LE_RDP 0
45 #define LE_RAP 1
47 #define LE_MO_PROM 0x8000 /* Enable promiscuous mode */
49 #define LE_C0_ERR 0x8000 /* Error: set if BAB, SQE, MISS or ME is set */
50 #define LE_C0_BABL 0x4000 /* BAB: Babble: tx timeout. */
51 #define LE_C0_CERR 0x2000 /* SQE: Signal quality error */
52 #define LE_C0_MISS 0x1000 /* MISS: Missed a packet */
53 #define LE_C0_MERR 0x0800 /* ME: Memory error */
54 #define LE_C0_RINT 0x0400 /* Received interrupt */
55 #define LE_C0_TINT 0x0200 /* Transmitter Interrupt */
56 #define LE_C0_IDON 0x0100 /* IFIN: Init finished. */
57 #define LE_C0_INTR 0x0080 /* Interrupt or error */
58 #define LE_C0_INEA 0x0040 /* Interrupt enable */
59 #define LE_C0_RXON 0x0020 /* Receiver on */
60 #define LE_C0_TXON 0x0010 /* Transmitter on */
61 #define LE_C0_TDMD 0x0008 /* Transmitter demand */
62 #define LE_C0_STOP 0x0004 /* Stop the card */
63 #define LE_C0_STRT 0x0002 /* Start the card */
64 #define LE_C0_INIT 0x0001 /* Init the card */
66 #define LE_C3_BSWP 0x4 /* SWAP */
67 #define LE_C3_ACON 0x2 /* ALE Control */
68 #define LE_C3_BCON 0x1 /* Byte control */
70 /* Receive message descriptor 1 */
71 #define LE_R1_OWN 0x80 /* Who owns the entry */
72 #define LE_R1_ERR 0x40 /* Error: if FRA, OFL, CRC or BUF is set */
73 #define LE_R1_FRA 0x20 /* FRA: Frame error */
74 #define LE_R1_OFL 0x10 /* OFL: Frame overflow */
75 #define LE_R1_CRC 0x08 /* CRC error */
76 #define LE_R1_BUF 0x04 /* BUF: Buffer error */
77 #define LE_R1_SOP 0x02 /* Start of packet */
78 #define LE_R1_EOP 0x01 /* End of packet */
79 #define LE_R1_POK 0x03 /* Packet is complete: SOP + EOP */
81 #define LE_T1_OWN 0x80 /* Lance owns the packet */
82 #define LE_T1_ERR 0x40 /* Error summary */
83 #define LE_T1_EMORE 0x10 /* Error: more than one retry needed */
84 #define LE_T1_EONE 0x08 /* Error: one retry needed */
85 #define LE_T1_EDEF 0x04 /* Error: deferred */
86 #define LE_T1_SOP 0x02 /* Start of packet */
87 #define LE_T1_EOP 0x01 /* End of packet */
88 #define LE_T1_POK 0x03 /* Packet is complete: SOP + EOP */
90 #define LE_T3_BUF 0x8000 /* Buffer error */
91 #define LE_T3_UFL 0x4000 /* Error underflow */
92 #define LE_T3_LCOL 0x1000 /* Error late collision */
93 #define LE_T3_CLOS 0x0800 /* Error carrier loss */
94 #define LE_T3_RTY 0x0400 /* Error retry */
95 #define LE_T3_TDR 0x03ff /* Time Domain Reflectometry counter */
97 #define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS))
98 #define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
99 #define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29)
101 #define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS))
102 #define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
103 #define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)
105 #define PKT_BUF_SZ 1544
106 #define RX_BUFF_SIZE PKT_BUF_SZ
107 #define TX_BUFF_SIZE PKT_BUF_SZ
109 struct lance_rx_desc {
110 unsigned short rmd0; /* low address of packet */
111 unsigned char rmd1_bits; /* descriptor bits */
112 unsigned char rmd1_hadr; /* high address of packet */
113 short length; /* This length is 2s complement (negative)!
114 * Buffer length
115 */
116 unsigned short mblength; /* This is the actual number of bytes received */
117 };
119 struct lance_tx_desc {
120 unsigned short tmd0; /* low address of packet */
121 unsigned char tmd1_bits; /* descriptor bits */
122 unsigned char tmd1_hadr; /* high address of packet */
123 short length; /* Length is 2s complement (negative)! */
124 unsigned short misc;
125 };
127 /* The LANCE initialization block, described in databook. */
128 /* On the Sparc, this block should be on a DMA region */
129 struct lance_init_block {
130 unsigned short mode; /* Pre-set mode (reg. 15) */
131 unsigned char phys_addr[6]; /* Physical ethernet address */
132 unsigned filter[2]; /* Multicast filter. */
134 /* Receive and transmit ring base, along with extra bits. */
135 unsigned short rx_ptr; /* receive descriptor addr */
136 unsigned short rx_len; /* receive len and high addr */
137 unsigned short tx_ptr; /* transmit descriptor addr */
138 unsigned short tx_len; /* transmit len and high addr */
140 /* The Tx and Rx ring entries must aligned on 8-byte boundaries. */
141 struct lance_rx_desc brx_ring[RX_RING_SIZE];
142 struct lance_tx_desc btx_ring[TX_RING_SIZE];
144 char tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
145 char pad[2]; /* align rx_buf for copy_and_sum(). */
146 char rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
147 };
149 #define LEDMA_REGS 4
150 #if 0
151 /* Structure to describe the current status of DMA registers on the Sparc */
152 struct sparc_dma_registers {
153 uint32_t cond_reg; /* DMA condition register */
154 uint32_t st_addr; /* Start address of this transfer */
155 uint32_t cnt; /* How many bytes to transfer */
156 uint32_t dma_test; /* DMA test register */
157 };
158 #endif
160 typedef struct LEDMAState {
161 uint32_t addr;
162 uint32_t regs[LEDMA_REGS];
163 } LEDMAState;
165 typedef struct LANCEState {
166 uint32_t paddr;
167 NetDriverState *nd;
168 uint32_t leptr;
169 uint16_t addr;
170 uint16_t regs[LE_MAXREG];
171 uint8_t phys[6]; /* mac address */
172 int irq;
173 LEDMAState *ledma;
174 } LANCEState;
176 static unsigned int rxptr, txptr;
178 static void lance_send(void *opaque);
180 static void lance_reset(LANCEState *s)
181 {
182 memcpy(s->phys, s->nd->macaddr, 6);
183 rxptr = 0;
184 txptr = 0;
185 s->regs[LE_CSR0] = LE_C0_STOP;
186 }
188 static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
189 {
190 LANCEState *s = opaque;
191 uint32_t saddr;
193 saddr = addr - s->paddr;
194 switch (saddr >> 1) {
195 case LE_RDP:
196 return s->regs[s->addr];
197 case LE_RAP:
198 return s->addr;
199 default:
200 break;
201 }
202 return 0;
203 }
205 static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
206 {
207 LANCEState *s = opaque;
208 uint32_t saddr;
209 uint16_t reg;
211 saddr = addr - s->paddr;
212 switch (saddr >> 1) {
213 case LE_RDP:
214 switch(s->addr) {
215 case LE_CSR0:
216 if (val & LE_C0_STOP) {
217 s->regs[LE_CSR0] = LE_C0_STOP;
218 break;
219 }
221 reg = s->regs[LE_CSR0];
223 // 1 = clear for some bits
224 reg &= ~(val & 0x7f00);
226 // generated bits
227 reg &= ~(LE_C0_ERR | LE_C0_INTR);
228 if (reg & 0x7100)
229 reg |= LE_C0_ERR;
230 if (reg & 0x7f00)
231 reg |= LE_C0_INTR;
233 // direct bit
234 reg &= ~LE_C0_INEA;
235 reg |= val & LE_C0_INEA;
237 // exclusive bits
238 if (val & LE_C0_INIT) {
239 reg |= LE_C0_IDON | LE_C0_INIT;
240 reg &= ~LE_C0_STOP;
241 }
242 else if (val & LE_C0_STRT) {
243 reg |= LE_C0_STRT | LE_C0_RXON | LE_C0_TXON;
244 reg &= ~LE_C0_STOP;
245 }
247 s->regs[LE_CSR0] = reg;
249 // trigger bits
250 //if (val & LE_C0_TDMD)
252 if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
253 pic_set_irq(s->irq, 1);
254 break;
255 case LE_CSR1:
256 s->leptr = (s->leptr & 0xffff0000) | (val & 0xffff);
257 s->regs[s->addr] = val;
258 break;
259 case LE_CSR2:
260 s->leptr = (s->leptr & 0xffff) | ((val & 0xffff) << 16);
261 s->regs[s->addr] = val;
262 break;
263 case LE_CSR3:
264 s->regs[s->addr] = val;
265 break;
266 }
267 break;
268 case LE_RAP:
269 if (val < LE_MAXREG)
270 s->addr = val;
271 break;
272 default:
273 break;
274 }
275 lance_send(s);
276 }
278 static CPUReadMemoryFunc *lance_mem_read[3] = {
279 lance_mem_readw,
280 lance_mem_readw,
281 lance_mem_readw,
282 };
284 static CPUWriteMemoryFunc *lance_mem_write[3] = {
285 lance_mem_writew,
286 lance_mem_writew,
287 lance_mem_writew,
288 };
291 /* return the max buffer size if the LANCE can receive more data */
292 static int lance_can_receive(void *opaque)
293 {
294 LANCEState *s = opaque;
295 void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
296 struct lance_init_block *ib;
297 int i;
298 uint16_t temp;
300 if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
301 return 0;
303 ib = (void *) iommu_translate(dmaptr);
305 for (i = 0; i < RX_RING_SIZE; i++) {
306 cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
307 temp &= 0xff;
308 if (temp == (LE_R1_OWN)) {
309 #ifdef DEBUG_LANCE
310 fprintf(stderr, "lance: can receive %d\n", RX_BUFF_SIZE);
311 #endif
312 return RX_BUFF_SIZE;
313 }
314 }
315 #ifdef DEBUG_LANCE
316 fprintf(stderr, "lance: cannot receive\n");
317 #endif
318 return 0;
319 }
321 #define MIN_BUF_SIZE 60
323 static void lance_receive(void *opaque, const uint8_t *buf, int size)
324 {
325 LANCEState *s = opaque;
326 void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
327 struct lance_init_block *ib;
328 unsigned int i, old_rxptr, j;
329 uint16_t temp;
331 if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
332 return;
334 ib = (void *) iommu_translate(dmaptr);
336 old_rxptr = rxptr;
337 for (i = rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
338 cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
339 if (temp == (LE_R1_OWN)) {
340 rxptr = (rxptr + 1) & RX_RING_MOD_MASK;
341 temp = size;
342 bswap16s(&temp);
343 cpu_physical_memory_write(&ib->brx_ring[i].mblength, (void *) &temp, 2);
344 #if 0
345 cpu_physical_memory_write(&ib->rx_buf[i], buf, size);
346 #else
347 for (j = 0; j < size; j++) {
348 cpu_physical_memory_write(((void *)&ib->rx_buf[i]) + j, &buf[j], 1);
349 }
350 #endif
351 temp = LE_R1_POK;
352 cpu_physical_memory_write(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
353 s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR;
354 if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
355 pic_set_irq(s->irq, 1);
356 #ifdef DEBUG_LANCE
357 fprintf(stderr, "lance: got packet, len %d\n", size);
358 #endif
359 return;
360 }
361 }
362 }
364 static void lance_send(void *opaque)
365 {
366 LANCEState *s = opaque;
367 void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
368 struct lance_init_block *ib;
369 unsigned int i, old_txptr, j;
370 uint16_t temp;
371 char pkt_buf[PKT_BUF_SZ];
373 if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
374 return;
376 ib = (void *) iommu_translate(dmaptr);
378 old_txptr = txptr;
379 for (i = txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
380 cpu_physical_memory_read(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
381 if (temp == (LE_T1_POK|LE_T1_OWN)) {
382 cpu_physical_memory_read(&ib->btx_ring[i].length, (void *) &temp, 2);
383 bswap16s(&temp);
384 temp = (~temp) + 1;
385 #if 0
386 cpu_physical_memory_read(&ib->tx_buf[i], pkt_buf, temp);
387 #else
388 for (j = 0; j < temp; j++) {
389 cpu_physical_memory_read(((void *)&ib->tx_buf[i]) + j, &pkt_buf[j], 1);
390 }
391 #endif
393 #ifdef DEBUG_LANCE
394 fprintf(stderr, "lance: sending packet, len %d\n", temp);
395 #endif
396 qemu_send_packet(s->nd, pkt_buf, temp);
397 temp = LE_T1_POK;
398 cpu_physical_memory_write(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
399 txptr = (txptr + 1) & TX_RING_MOD_MASK;
400 s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR;
401 }
402 }
403 }
405 static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
406 {
407 LEDMAState *s = opaque;
408 uint32_t saddr;
410 saddr = (addr - s->addr) >> 2;
411 if (saddr < LEDMA_REGS)
412 return s->regs[saddr];
413 else
414 return 0;
415 }
417 static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
418 {
419 LEDMAState *s = opaque;
420 uint32_t saddr;
422 saddr = (addr - s->addr) >> 2;
423 if (saddr < LEDMA_REGS)
424 s->regs[saddr] = val;
425 }
427 static CPUReadMemoryFunc *ledma_mem_read[3] = {
428 ledma_mem_readl,
429 ledma_mem_readl,
430 ledma_mem_readl,
431 };
433 static CPUWriteMemoryFunc *ledma_mem_write[3] = {
434 ledma_mem_writel,
435 ledma_mem_writel,
436 ledma_mem_writel,
437 };
439 void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
440 {
441 LANCEState *s;
442 LEDMAState *led;
443 int lance_io_memory, ledma_io_memory;
445 s = qemu_mallocz(sizeof(LANCEState));
446 if (!s)
447 return;
449 s->paddr = leaddr;
450 s->nd = nd;
451 s->irq = irq;
453 lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s);
454 cpu_register_physical_memory(leaddr, 8, lance_io_memory);
456 led = qemu_mallocz(sizeof(LEDMAState));
457 if (!led)
458 return;
460 s->ledma = led;
461 led->addr = ledaddr;
462 ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, led);
463 cpu_register_physical_memory(ledaddr, 16, ledma_io_memory);
465 lance_reset(s);
466 qemu_add_read_packet(nd, lance_can_receive, lance_receive, s);
467 }